From 5b6f33e1a41589fb395e672d92a0d9736213a4cd Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Fri, 13 Sep 2019 12:46:25 -0400 Subject: [PATCH 1/3] Use a larger buffer size for recording to prevent glitching --- src/lib/audio/audio-recorder.js | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/lib/audio/audio-recorder.js b/src/lib/audio/audio-recorder.js index b452b1f26..fa5e01882 100644 --- a/src/lib/audio/audio-recorder.js +++ b/src/lib/audio/audio-recorder.js @@ -1,12 +1,12 @@ import 'get-float-time-domain-data'; import getUserMedia from 'get-user-media-promise'; import SharedAudioContext from './shared-audio-context.js'; -import {computeRMS} from './audio-util.js'; +import {computeRMS, computeChunkedRMS} from './audio-util.js'; class AudioRecorder { constructor () { this.audioContext = new SharedAudioContext(); - this.bufferLength = 1024; + this.bufferLength = 8192; this.userMediaStream = null; this.mediaStreamSource = null; @@ -51,7 +51,7 @@ class AudioRecorder { this.userMediaStream = userMediaStream; this.mediaStreamSource = this.audioContext.createMediaStreamSource(userMediaStream); this.sourceNode = this.audioContext.createGain(); - this.scriptProcessorNode = this.audioContext.createScriptProcessor(this.bufferLength, 2, 2); + this.scriptProcessorNode = this.audioContext.createScriptProcessor(this.bufferLength, 1, 1); this.scriptProcessorNode.onaudioprocess = processEvent => { if (this.recording && !this.disposed) { @@ -68,9 +68,9 @@ class AudioRecorder { const update = () => { if (this.disposed) return; - requestAnimationFrame(update); this.analyserNode.getFloatTimeDomainData(dataArray); onUpdate(computeRMS(dataArray)); + requestAnimationFrame(update); }; requestAnimationFrame(update); @@ -83,7 +83,16 @@ class AudioRecorder { } stop () { - const chunkLevels = this.buffers.map(buffer => computeRMS(buffer)); + const buffer = new Float32Array(this.buffers.length * this.bufferLength); + + let offset = 0; + for (let i = 0; i < this.buffers.length; i++) { + const bufferChunk = this.buffers[i]; + buffer.set(bufferChunk, offset); + offset += bufferChunk.length; + } + + const chunkLevels = computeChunkedRMS(buffer); const maxRMS = Math.max.apply(null, chunkLevels); const threshold = maxRMS / 8; @@ -105,15 +114,6 @@ class AudioRecorder { trimEnd = 1; } - const buffer = new Float32Array(this.buffers.length * this.bufferLength); - - let offset = 0; - for (let i = 0; i < this.buffers.length; i++) { - const bufferChunk = this.buffers[i]; - buffer.set(bufferChunk, offset); - offset += bufferChunk.length; - } - return { levels: chunkLevels, samples: buffer, From 94bb677fd8185ceb4236c03a7a4aef22c30640f5 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Fri, 13 Sep 2019 14:04:54 -0400 Subject: [PATCH 2/3] Force meter and waveform to separate paint layer --- src/components/record-modal/record-modal.css | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/record-modal/record-modal.css b/src/components/record-modal/record-modal.css index ae9d8afcc..41fc90a96 100644 --- a/src/components/record-modal/record-modal.css +++ b/src/components/record-modal/record-modal.css @@ -20,8 +20,10 @@ border: 1px solid $ui-black-transparent; border-radius: 5px; padding: 3px; - + /* Force these to be on their own render layer because they update often */ + transform: translateZ(0); } + .meter-container { margin-right: 5px; height: 180px; From 2b9550f3d99058d0ae0973808dee575d0f71d80e Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Fri, 13 Sep 2019 14:05:07 -0400 Subject: [PATCH 3/3] Use single setState call instead of two --- src/containers/recording-step.jsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/containers/recording-step.jsx b/src/containers/recording-step.jsx index 6431ad372..39d928fc3 100644 --- a/src/containers/recording-step.jsx +++ b/src/containers/recording-step.jsx @@ -44,10 +44,10 @@ class RecordingStep extends React.Component { alert(this.props.intl.formatMessage(messages.alertMsg)); // eslint-disable-line no-alert } handleLevelUpdate (level) { - this.setState({level}); - if (this.props.recording) { - this.setState({levels: (this.state.levels || []).concat([level])}); - } + this.setState({ + level: level, + levels: this.props.recording ? (this.state.levels || []).concat([level]) : this.state.levels + }); } handleRecord () { this.audioRecorder.startRecording();