From 93e654a02cef3d5913a2088d4c397418dc0cee2f Mon Sep 17 00:00:00 2001 From: pepper Date: Thu, 15 May 2014 19:06:59 -0700 Subject: doing this --- dynamicaudio.as | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 dynamicaudio.as (limited to 'dynamicaudio.as') diff --git a/dynamicaudio.as b/dynamicaudio.as new file mode 100644 index 0000000..45c2ceb --- /dev/null +++ b/dynamicaudio.as @@ -0,0 +1,80 @@ +package { + import flash.display.Sprite; + import flash.events.SampleDataEvent; + import flash.external.ExternalInterface; + import flash.media.Sound; + import flash.media.SoundChannel; + + public class dynamicaudio extends Sprite { + public var bufferSize:Number = 2048; // In samples + public var sound:Sound; + public var buffer:Array = []; + public var channel:SoundChannel; + public var writtenSampleCount:Number = 0; + + public function dynamicaudio() { + ExternalInterface.addCallback('write', write); + ExternalInterface.addCallback('stop', stop); + ExternalInterface.addCallback('bufferedDuration', bufferedDuration); + this.sound = new Sound(); + this.sound.addEventListener( + SampleDataEvent.SAMPLE_DATA, + soundGenerator + ); + this.channel = this.sound.play(); + } + + // Called from JavaScript to add samples to the buffer + // Note we are using a space separated string of samples instead of an + // array. Flash's stupid ExternalInterface passes every sample as XML, + // which is incredibly expensive to encode/decode + public function write(s:String):Number { + var multiplier:Number = 1/32768; + var alreadyBufferedDuration:Number = (this.writtenSampleCount + this.buffer.length/2) / 44.1; + for each (var sample:String in s.split(" ")) { + this.buffer.push(Number(sample)*multiplier); + } + return (this.channel ? alreadyBufferedDuration - this.channel.position : 0); + } + + public function bufferedDuration():Number { + // duration (in ms) of audio written to Flash so far = (writtenSampleCount * 1000 / sampleRate) + // number of ms in Flash's buffer = (writtenSampleCount * 1000 / sampleRate) - this.channel.position + // number of ms in our buffer = (this.buffer.length/2 * 1000 / sampleRate) + // (/2 because buffer stores stereo data => 2 elements per sample) + // for 44100Hz, x * 1000 / sampleRate => x / 44.1 + return (this.writtenSampleCount + this.buffer.length/2) / 44.1 - this.channel.position; + } + + public function stop():void { + this.channel.stop(); + this.buffer = []; + this.writtenSampleCount = 0; + this.channel = this.sound.play(); + } + + public function soundGenerator(event:SampleDataEvent):void { + var i:int; + + // If we haven't got enough data, write 2048 samples of silence to + // both channels, the minimum Flash allows + if (this.buffer.length < this.bufferSize*2) { + for (i = 0; i < 4096; i++) { + event.data.writeFloat(0.0); + } + this.writtenSampleCount += 2048; + return; + } + + var count:Number = Math.min(this.buffer.length, 16384); + + for each (var sample:Number in this.buffer.slice(0, count)) { + event.data.writeFloat(sample); + } + + this.writtenSampleCount += count/2; + this.buffer = this.buffer.slice(count, this.buffer.length); + } + } +} + -- cgit v1.2.3-70-g09d2