| @@ -73,7 +73,11 @@ class AudioStream { | |||
| this.audioReadableSignal = audioReadableSignal; | |||
| this.audioReadableSignal.onabort = (e) => console.log(e.type); | |||
| this.abortHandler = async (e) => { | |||
| await this.disconnect(true); | |||
| try { | |||
| await this.disconnect(true); | |||
| } catch (err) { | |||
| console.warn(err.message); | |||
| } | |||
| console.log( | |||
| `readOffset:${this.readOffset}, duration:${this.duration}, ac.currentTime:${this.ac.currentTime}`, | |||
| `generator.readyState:${this.generator.readyState}, audioWriter.desiredSize:${this.audioWriter.desiredSize}`, | |||
| @@ -97,9 +101,13 @@ class AudioStream { | |||
| this.osc.disconnect(); | |||
| this.outputSource.disconnect(); | |||
| this.track.stop(); | |||
| await this.audioWriter.close(); | |||
| await this.audioWriter.closed; | |||
| await this.inputReader.cancel(); | |||
| try { | |||
| await this.audioWriter.close(); | |||
| await this.audioWriter.closed; | |||
| await this.inputReader.cancel(); | |||
| } catch (err) { | |||
| throw err; | |||
| } | |||
| this.generator.stop(); | |||
| if (this.recorder && this.recorder.state === 'recording') { | |||
| this.recorder.stop(); | |||
| @@ -158,13 +166,13 @@ class AudioStream { | |||
| this.init = true; | |||
| i = 44; | |||
| } | |||
| for (; | |||
| i < value.buffer.byteLength; | |||
| i++, this.readOffset++ | |||
| ) { | |||
| for (; i < value.buffer.byteLength; i++, this.readOffset++) { | |||
| if (channelData.length === this.channelDataLength) { | |||
| this.inputController.enqueue(new Uint8Array(channelData)); | |||
| channelData.length = 0; | |||
| this.inputController.enqueue( | |||
| new Uint8Array( | |||
| channelData.splice(0, this.channelDataLength) | |||
| ) | |||
| ); | |||
| } | |||
| channelData.push(value[i]); | |||
| } | |||
| @@ -175,7 +183,7 @@ class AudioStream { | |||
| close: async () => { | |||
| console.log('Done writing input stream.'); | |||
| if (channelData.length) { | |||
| this.inputController.enqueue(channelData); | |||
| this.inputController.enqueue(new Uint8Array(channelData)); | |||
| } | |||
| this.inputController.close(); | |||
| this.source.postMessage('Done writing input stream.', '*'); | |||
| @@ -186,8 +194,14 @@ class AudioStream { | |||
| this.audioReadable.pipeTo( | |||
| new WritableStream({ | |||
| write: async ({ timestamp }) => { | |||
| if (this.inputController.desiredSize === 0) { | |||
| await this.disconnect(); | |||
| const { value, done } = await this.inputReader.read(); | |||
| if (done) { | |||
| await this.inputReader.closed; | |||
| try { | |||
| await this.disconnect(); | |||
| } catch (err) { | |||
| console.warn(err.message); | |||
| } | |||
| console.log( | |||
| `readOffset:${this.readOffset}, duration:${this.duration}, ac.currentTime:${this.ac.currentTime}`, | |||
| `generator.readyState:${this.generator.readyState}, audioWriter.desiredSize:${this.audioWriter.desiredSize}` | |||
| @@ -197,10 +211,6 @@ class AudioStream { | |||
| new Promise((resolve) => (this.ac.onstatechange = resolve)), | |||
| ]); | |||
| } | |||
| const { value, done } = await this.inputReader.read(); | |||
| if (done) { | |||
| console.log({ done }); | |||
| } | |||
| const uint16 = new Uint16Array(value.buffer); | |||
| // https://stackoverflow.com/a/35248852 | |||
| const floats = new Float32Array(this.channelDataLength / 2); | |||
| @@ -211,25 +221,19 @@ class AudioStream { | |||
| int >= 0x8000 ? -(0x10000 - int) / 0x8000 : int / 0x7fff; | |||
| floats[i] = float; | |||
| } | |||
| const buffer = new AudioBuffer({ | |||
| numberOfChannels: this.numberOfChannels, | |||
| length: floats.length, | |||
| sampleRate: this.sampleRate, | |||
| }); | |||
| buffer.getChannelData(0).set(floats); | |||
| this.duration += buffer.duration; | |||
| const frame = new AudioData({ | |||
| format:'FLTP', | |||
| format: 'FLTP', | |||
| sampleRate: 22050, | |||
| numberOfChannels: 1, | |||
| numberOfFrames: 220, | |||
| timestamp, | |||
| data: buffer.getChannelData(0), | |||
| data: floats, | |||
| }); | |||
| await this.audioWriter.write(frame); | |||
| this.duration += (frame.duration / 10**6); | |||
| if (this.recorder && this.recorder.state === 'inactive') { | |||
| this.recorder.start(); | |||
| } | |||
| await this.audioWriter.write(frame); | |||
| }, | |||
| abort(e) { | |||
| console.error(e.message); | |||
| @@ -242,7 +246,9 @@ class AudioStream { | |||
| ), | |||
| ]); | |||
| this.resolve( | |||
| this.recorder ? await this.data.arrayBuffer() : 'Done streaming.' | |||
| this.recorder | |||
| ? this.data && (await this.data.arrayBuffer()) | |||
| : 'Done streaming.' | |||
| ); | |||
| return this.promise; | |||
| } catch (err) { | |||