-
Notifications
You must be signed in to change notification settings - Fork 42
/
XAudioJS.as
86 lines (86 loc) · 2.99 KB
/
XAudioJS.as
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
package {
import flash.media.Sound;
import flash.events.SampleDataEvent;
import flash.display.Sprite;
import flash.external.ExternalInterface;
public class XAudioJS extends Sprite {
public var sound:Sound = null;
public var channelBuffer:Vector.<Number> = new Vector.<Number>(8192, true);
public var channels:int = 0;
public var volume:Number = 0;
public var samplesFound:int = 0;
public function XAudioJS() {
ExternalInterface.addCallback('initialize', initialize);
ExternalInterface.addCallback('changeVolume', changeVolume);
}
//Initialization function for the flash backend of XAudioJS:
public function initialize(channels:Number, newVolume:Number):void {
//Initialize the new settings:
this.channels = (int(channels) == 2) ? 2 : 1;
this.changeVolume(newVolume);
this.checkForSound();
}
//Volume changing function for the flash backend of XAudioJS:
public function changeVolume(newVolume:Number):void {
//Set the new volume:
this.volume = Math.min(Math.max(newVolume, 0), 1);
}
//Calls the JavaScript function responsible for the polyfill:
public function requestSamples():Boolean {
//Call the javascript callback function:
var buffer:String = ExternalInterface.call("XAudioJSFlashAudioEvent");
//If we received an appropriate response:
if (buffer !== null) {
if ((buffer.length % this.channels) == 0) { //Outsmart bad programmers from messing us up. :/
var channelSample:Number = 0;
this.samplesFound = Math.min(buffer.length, 4096 * this.channels);
for (var index:int = 0; index < this.samplesFound; ++index) {
//Get the unsigned 15-bit encoded sample value at +0x3000 offset:
channelSample = buffer.charCodeAt(index);
//Range-check the sample frame value and convert it:
this.channelBuffer[index] = (channelSample >= 0x3000 && channelSample < 0xAFFF) ? (this.volume * (((channelSample - 0x3000) / 0x3FFF) - 1)) : 0;
}
return true;
}
}
return false;
}
//Check to make sure the audio stream is enabled:
public function checkForSound():void {
if (this.sound == null) {
this.sound = new Sound();
this.sound.addEventListener(
SampleDataEvent.SAMPLE_DATA,
soundCallback
);
this.sound.play();
}
}
//Flash Audio Refill Callback
public function soundCallback(e:SampleDataEvent):void {
var index:int = 0;
if (this.requestSamples()) {
if (this.channels == 2) {
//Stereo:
while (index < this.samplesFound) {
e.data.writeFloat(this.channelBuffer[index++]);
e.data.writeFloat(this.channelBuffer[index++]);
}
index >>= 1;
}
else {
//Mono:
while (index < this.samplesFound) {
e.data.writeFloat(this.channelBuffer[index]);
e.data.writeFloat(this.channelBuffer[index++]);
}
}
}
//Write some silence if not enough samples are found:
while (++index <= 2048) {
e.data.writeFloat(0);
e.data.writeFloat(0);
}
}
}
}