diff --git a/src/containers/sound-editor.jsx b/src/containers/sound-editor.jsx index abe292724939fb82e75b4ebed66bd56982e48306..d5a0f50f3440ff988ff875de5b944633022a5fd4 100644 --- a/src/containers/sound-editor.jsx +++ b/src/containers/sound-editor.jsx @@ -5,7 +5,7 @@ import WavEncoder from 'wav-encoder'; import {connect} from 'react-redux'; -import {computeChunkedRMS} from '../lib/audio/audio-util.js'; +import {computeChunkedRMS, SOUND_BYTE_LIMIT} from '../lib/audio/audio-util.js'; import AudioEffects from '../lib/audio/audio-effects.js'; import SoundEditorComponent from '../components/sound-editor/sound-editor.jsx'; import AudioBufferPlayer from '../lib/audio/audio-buffer-player.js'; @@ -65,13 +65,6 @@ class SoundEditor extends React.Component { }); } submitNewSamples (samples, sampleRate, skipUndo) { - if (!skipUndo) { - this.redoStack = []; - if (this.undoStack.length >= UNDO_STACK_SIZE) { - this.undoStack.shift(); // Drop the first element off the array - } - this.undoStack.push(this.copyCurrentBuffer()); - } // Encode the new sound into a wav so that it can be stored let wavBuffer = null; try { @@ -79,18 +72,38 @@ class SoundEditor extends React.Component { sampleRate: sampleRate, channelData: [samples] }); + + if (wavBuffer.byteLength > SOUND_BYTE_LIMIT) { + // Cancel the sound update by setting to null + wavBuffer = null; + log.error(`Refusing to encode sound larger than ${SOUND_BYTE_LIMIT} bytes`); + } } catch (e) { // This error state is mostly for the mock sounds used during testing. // Any incorrect sound buffer trying to get interpretd as a Wav file // should yield this error. + // This can also happen if the sound is too be allocated in memory. log.error(`Encountered error while trying to encode sound update: ${e}`); } - this.resetState(samples, sampleRate); - this.props.vm.updateSoundBuffer( - this.props.soundIndex, - this.audioBufferPlayer.buffer, - wavBuffer ? new Uint8Array(wavBuffer) : new Uint8Array()); + // Do not submit sound if it could not be encoded (i.e. if too large) + if (wavBuffer) { + if (!skipUndo) { + this.redoStack = []; + if (this.undoStack.length >= UNDO_STACK_SIZE) { + this.undoStack.shift(); // Drop the first element off the array + } + this.undoStack.push(this.copyCurrentBuffer()); + } + this.resetState(samples, sampleRate); + this.props.vm.updateSoundBuffer( + this.props.soundIndex, + this.audioBufferPlayer.buffer, + new Uint8Array(wavBuffer)); + + return true; // Update succeeded + } + return false; // Update failed } handlePlay () { this.audioBufferPlayer.play( @@ -145,8 +158,8 @@ class SoundEditor extends React.Component { effects.process(({renderedBuffer}) => { const samples = renderedBuffer.getChannelData(0); const sampleRate = renderedBuffer.sampleRate; - this.submitNewSamples(samples, sampleRate); - this.handlePlay(); + const success = this.submitNewSamples(samples, sampleRate); + if (success) this.handlePlay(); }); } handleUndo () { diff --git a/src/lib/audio/audio-util.js b/src/lib/audio/audio-util.js index a493fc7da73b1069c38c0bee92ac050bdd4eb809..2b68fcbe8af5978e87537e4fa904d431e502abf6 100644 --- a/src/lib/audio/audio-util.js +++ b/src/lib/audio/audio-util.js @@ -1,3 +1,5 @@ +const SOUND_BYTE_LIMIT = 10 * 1000 * 1000; // 10mb + const computeRMS = function (samples, scaling = 0.55) { if (samples.length === 0) return 0; // Calculate RMS, adapted from https://github.com/Tonejs/Tone.js/blob/master/Tone/component/Meter.js#L88 @@ -23,5 +25,6 @@ const computeChunkedRMS = function (samples, chunkSize = 1024) { export { computeRMS, - computeChunkedRMS + computeChunkedRMS, + SOUND_BYTE_LIMIT };