source: gs3-extensions/web-audio/trunk/js-mad/script/main-jsmad.js@ 28388

Last change on this file since 28388 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: 5.7 KB
Line 
1
2var JsMadProcessing = function(audio_id,active_workflow) {
3
4 this.audio_id = audio_id;
5 this.active_workflow = active_workflow || null;
6
7 var url = $('#'+audio_id).attr("href");
8 console.info("JsMadProcessing::JsMadProcessing() retrieving over AJAX: " + url);
9
10 var stream = new Mad.AjaxStream(url);
11
12 var that = this;
13
14 var channels = 2; // stereo
15 var rate = 44100; // 44.1 Khz
16 //var rate = 48000; // 44.1 Khz
17 //var bufsize = 65536 * 4096;
18 //var bufsize = 65536 * 1024;
19 //var bufsize = 2048;
20 var bufsize = 1024 * 8;
21
22 //this.dev = Sink(function(buffer) {that.refill(buffer)}, channels, bufsize, rate);
23 //console.log("*** got sample rate of: " + this.dev.sampleRate);
24
25
26 this.playBufferStore = new Array();
27
28 stream.requestAbsolute(1 * 1024, function() { that.streamCallback(stream) });
29
30}
31
32
33
34
35JsMadProcessing.prototype.streamCallback = function(stream) {
36
37
38 var mp3 = new Mad.MP3File(stream);
39 var mpeg = mp3.getMpegStream();
40
41 //var howmuch = 10000;
42 var ss1 = Date.now();
43
44 var synth = new Mad.Synth();
45 var frame = new Mad.Frame();
46
47 frame = Mad.Frame.decode(frame, mpeg); // decode first frame to establish num channels and samplerate
48 var num_channels = frame.header.nchannels();
49 var sampleRate = frame.header.samplerate;
50
51 console.info("JsMadProcessing::streamCallback() decoding URL retrieved MP3 with " + num_channels + " channels, samplerate = " + sampleRate);
52
53
54 var that = this;
55
56 var numSamples = 0;
57
58 synth.frame(frame);
59 var prev_synth_frame_len = synth.pcm.samples[0].length;
60 console.info("JsMadProcesing.streamCallback(): synth frame length (initial frame) = " + prev_synth_frame_len);
61
62 var i=1; // already processed one frame
63
64 var overflowBuffer = null;
65
66 console.log("*** main-jsmad.js::stream_callback(): hardwiring workflow buffer size to 2048");
67
68 var speedup_batch_limit;
69 var speedup_pause;
70
71 if (BrowserDetect.browser == "Firefox") {
72 speedup_batch_limit = 100;
73 speedup_pause = 0;
74 }
75 else {
76 // e.g. Chrome
77 // => the following values played more nicely with letting DSP playback operate straightaway
78 // i.e. when jsmad is still working its way through the frames
79
80 speedup_batch_limit = 10;
81 speedup_pause = 2;
82
83 //speedup_batch_limit = 100;
84 //speedup_pause = 0;
85
86 console.log("*** Running JsMadProcessing with: batch limit = " + speedup_batch_limit
87 + ", pause = " + speedup_pause + " msecs");
88 }
89
90
91 (function() {
92
93 var more_frames = 1;
94 try {
95
96 var speedup_i = 0;
97
98 while (speedup_i < speedup_batch_limit) { // Decode 100 frames at a time, before setTimeout break
99
100 frame = Mad.Frame.decode(frame, mpeg);
101 synth.frame(frame);
102
103 var synth_frame_len = synth.pcm.samples[0].length;
104
105 var playBuffer = null;
106 var pbp = 0; // pbp = play buffer pos
107
108 if (overflowBuffer != null) {
109 playBuffer = new Float32Array(overflowBuffer.length+(synth_frame_len*num_channels));
110 playBuffer.set(overflowBuffer);
111 pbp = overflowBuffer.length;
112 overflowBuffer = null;
113 }
114 else {
115 playBuffer = new Float32Array(synth_frame_len*num_channels);
116 pbp = 0;
117 }
118
119
120 for (var sfp=0; sfp<synth_frame_len; sfp++) {
121 for (var c=0; c<num_channels; c++) {
122 playBuffer[pbp] = synth.pcm.samples[c][sfp];
123 pbp++;
124 }
125 }
126
127 numSamples += synth_frame_len;
128
129 // uncomment the following line if you want to hear speeded-up playback as it works through the audio file
130 //var written = pannedPlayback.mozWriteAudio(playBuffer);
131
132
133 if (synth_frame_len != prev_synth_frame_len) {
134 console.log("*** new synth frame len (frame num = " + i + "): len = " + synth_frame_len);
135 prev_synth_frame_len = synth_frame_len;
136 }
137
138 if (that.active_workflow != null) {
139 // Send the data into the Javascript DSP workflow
140
141 // Note: workflow geared to 2048 samples at a time
142
143 var wi = 0;
144
145 var playBufferLen = playBuffer.length;
146 while (wi<playBuffer.length) {
147
148 if (wi+2048<=playBufferLen) {
149 var workflowBuffer = playBuffer.subarray(wi,wi+2048);
150 that.active_workflow.pumpDataHead("rawInput",workflowBuffer);
151 that.playBufferStore.push(workflowBuffer);
152 }
153 else {
154 // tail end => set up in overflow buffer
155 var workflowBufferTail = playBuffer.subarray(wi);
156
157 overflowBuffer = new Float32Array(playBufferLen-wi);
158 overflowBuffer.set(workflowBufferTail);
159
160 }
161 wi += 2048;
162 }
163
164
165 // Old approach: pump data in, in frames that are set by webAudioContext
166 //that.active_workflow.pumpDataHead("rawInput",playBuffer);
167 }
168
169 speedup_i++;
170 i++;
171 }
172
173 }
174 catch(err) {
175 if (err == "Header decoding failed") {
176 console.info("JsMadProcessing::streamCallack() decoded " + i + " frames");
177 }
178 else {
179 console.error(err);
180 }
181 more_frames = 0;
182 }
183
184 if (more_frames) {
185 setTimeout(arguments.callee,speedup_pause); // even a delay of '0' gives the browser thread a break
186 }
187 else {
188 var ss2 = Date.now();
189
190 var song_duration = numSamples / sampleRate;
191 var speedup_duration = (ss2 - ss1)/1000;
192
193 var speedup_factor = song_duration / speedup_duration;
194 //console.log("Computed song duration: " + song_duration + " secs");
195 console.info("JsMad processing done in " + speedup_duration + " secs (a speed factor of " + speedup_factor + ")");
196 }
197
198 })();
199
200}
201
202
203JsMadProcessing.prototype.refill = function(buffer)
204{
205 console.log("refill called, asking for size = " + buffer.length);
206
207 var buffer_len = buffer.length;
208 var buffer_pos = 0;
209
210 while ((this.playBufferStore.length>0) && (buffer_pos<buffer_len)) {
211
212 var playBuffer = this.playBufferStore.shift();
213 buffer.set(playBuffer,buffer_pos);
214
215 buffer_pos += playBuffer.length;
216 }
217
218
219}
Note: See TracBrowser for help on using the repository browser.