source: gs3-extensions/web-audio/trunk/js-dsp/component/audio-mixer.js@ 28548

Last change on this file since 28548 was 28388, checked in by davidb, 11 years ago

Set of JS, CSS, PNG etc web resources to support a mixture of audio player/document display capabilities

File size: 6.7 KB
Line 
1
2//var org.greenstone.meandre.audio.util.MixType = {
3
4var MixType = {
5 LeftOnly: { value: 0, name: "Left only" },
6 RightOnly: { value: 1, name: "Right only" },
7 LeftRightAdd: { value: 2, name: "Left and Right add" },
8 LeftRightSub: { value: 3, name: "Left and Right subtract" }
9};
10
11
12var AudioMixer = function(numSamples,channels) {
13
14 this.getset = {};
15
16 this.numSamples = numSamples;
17 this.channels = 2;
18
19}
20
21AudioMixer.inherits(Component);
22
23//----------------------------- OVERVIEW -----------------------------------------------------
24
25AudioMixer.staticfield('Component', {
26
27 creator: "David Bainbridge (based on AudioFileRead by Kris West)",
28
29 description : "Overview: Takes a Signal object with file location metadata as input, "
30 + "reads in the corresponding audio file and streams out frames of data from that file."
31 + "Detailed Description: This module reads in audio files in a number of formats,"
32 + "enframes the data and streams out the frames. Mixing options include: LeftOnly, RightOnly, "
33 + "LeftRightAdd, LeftRightSub."
34 + "The frame size, overlap percentage and sample rate of the of the audio frames are appended to"
35 + "the metadata of the Signal object, which is \'passed through\' for later (optional) use but other components. "
36 + "The \"Read Frame Size\" parameter can be used to control how often data is read from "
37 + "disk."
38 + "Currently supported audio file formats include MP3 (.mp3) and Wave (.wav).",
39
40 name: "Audio Signal Mixer",
41
42 tags: "signal reader",
43
44 // dependency: [ "foundry-abstracts.jar", "seasr-commons-1.4.9.jar" ]
45});
46
47//------------------------------ INPUTS ------------------------------------------------------
48
49AudioMixer.staticfield('ComponentInputArray', [
50/*
51 {
52 name: "signal",
53 description: "A Signal object with \"fileLocation\" metadata, indicating the "
54 + "location of the corresponding audio file."
55 }
56*/
57
58 {
59 name: "rawInput",
60 description: "The raw float32 input from the underlying (decompressed if required) audio file"
61 }
62
63
64]);
65
66
67//------------------------------ PROPERTIES --------------------------------------------------
68
69AudioMixer.staticfield('ComponentPropertyArray', [
70/*
71 {
72 name: "outputFrameLength",
73 defaultValue: "0.023219954648526078",
74 description: "The length of audio frames to output, measured in seconds. This "
75 + "will be multiplied by the samplerate of the audio file and "
76 + "rounded to calculate the length in samples of the output "
77 + "vectors. This ensures that constant time resolution can be "
78 + "maintained at different sample rates. The default setting (0.023219...) "
79 + "produces 1024 sample frames at 44.1kHz and 512 at 22.05kHz."
80 },
81
82 {
83 name: "overlapPercent",
84 defaultValue: "0.5",
85 description: "The percentage to overlap concurrent output frames by (0.0-1.0)"
86 },
87
88 {
89 name: "mixType",
90 defaultValue: "LeftRightAdd",
91 description: "Controls how the Signal in should be mix. Assuming a stero "
92 + "input, then choices are: LeftOnly, RightOnly, LeftRightAdd, LeftRightSub."
93 + "In the case of mono input, the signal is passed straight through unchanged."
94 },
95
96
97 {
98 name: "readFrameSize",
99 defaultValue: "102400",
100 description: "Controls frame size of data read in by this module. If possible, "
101 + "this frame size will be used by the AudioReader responsible for "
102 + "the file otherwise buffering will be used to achieve the correct "
103 + "framesize. This parameter is used to control how often data is "
104 + "read from disk."
105 },
106
107
108 {
109 name: "limitAudioFrames",
110 defaultValue: "false",
111 description: "Controls whether the number of frames that are output is limited or not."
112 },
113
114
115 {
116 name: "maxOutFrames",
117 defaultValue: "10000",
118 description: "The maxium number of frames to output."
119 }
120*/
121]);
122
123
124//------------------------------ OUTPUTS -----------------------------------------------------
125
126AudioMixer.staticfield('ComponentOutputArray', [
127
128 {
129 name: "mixedFrames",
130 description: "Audio frames that are some combination of left and/or right channels "
131 + "as set by the mixType property"
132 },
133/*
134 {
135 name: "signal",
136 description: "The Signal Object used to read the file, with"
137 + " \"frameSize\", \"overlapSize\" and \"sampleRate\" metadata set."
138 }
139*/
140
141]);
142
143AudioMixer.prototype.defaults = function() {
144
145 /** enum representing how the left and right audio in channels are to be treated
146 */
147 getset.mixType = MixType.LeftRightAdd;
148
149 /** The length of audio frames output, measured in seconds. */
150 getset.outputFrameLength = (512.0 / 22050.0);
151
152 /** The desired read frame size. This parameter can be used to adjust the number
153 * of disk accesses per output frame.
154 */
155 getset.readFrameSize = 1024;
156
157 /** The percentage to overlap concurrent frames.
158 */
159 getset.overlapPercent = 0.5;
160
161 /** The maximum number of frames to output.
162 */
163 getset.maxOutFrames = 10000;
164 /** Determines whether number of frames is limited
165 */
166 getset.limitAudioFrames = false;
167
168}
169
170
171AudioMixer.prototype.initializeCallBack = function(ccp) {
172
173 // typeof(ccp) => ComponentContextProperties
174
175 // Put these into ComponentPropertyArray
176
177 this.concatLimit = 8;
178 this.concatCount = 0;
179
180 this.concatSignal = new Float32Array(this.numSamples * this.concatLimit); // mono
181
182}
183
184
185AudioMixer.prototype.executeCallBack = function(cc) {
186
187 // typeof(cc) => ComponentContext
188
189 // get the "[D" input
190
191 //console.log("*** AudioMixer::executeCallBack(): away to request 'rawInput'");
192
193 var fb = cc.getDataComponentFromInput("rawInput");
194/*
195 var mess = "";
196 for (var i=0; i<fb.length; i+=200) {
197 mess += fb[i] + ", ";
198 }
199 console.log("**** AudioMixer: data samples = " + mess);
200*/
201
202 // Mix number of channels down to one channel
203
204 var p =0;
205 for (var i=0; i<this.numSamples; i++ ) {
206
207 var sv = 0;
208 for (var c=0; c<this.channels; c++) {
209 sv += fb[p];
210 p++;
211 }
212 // signal[i] = sv / channels;
213 this.concatSignal[(this.concatCount*this.numSamples)+i] = sv / this.channels;
214 }
215
216 this.concatCount++;
217
218 //console.log("*** concatCount = " + this.concatCount);
219 //console.log("*** concatLimit = " + this.concatLimit);
220
221 if (this.concatCount==this.concatLimit) {
222 // send this mono-mixed concatenated array on its way
223
224 this.concatCount=0;
225 cc.pushDataComponentToOutput("mixedFrames", this.concatSignal);
226 }
227}
228
229
230AudioMixer.prototype.disposeCallBack = function(ccp) {
231
232 // typeof(ccp) => ComponentContextProperties
233
234 this.concatSignal = null;
235
236}
237
238
239
240
241
Note: See TracBrowser for help on using the repository browser.