Make WebAudio API const-correct.
[WebKit-https.git] / Source / WebCore / platform / audio / AudioBus.cpp
1 /*
2  * Copyright (C) 2010 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include "config.h"
30
31 #if ENABLE(WEB_AUDIO)
32
33 #include "AudioBus.h"
34
35 #include "DenormalDisabler.h"
36
37 #include "SincResampler.h"
38 #include "VectorMath.h"
39 #include <algorithm>
40 #include <assert.h>
41 #include <math.h>
42 #include <wtf/OwnPtr.h>
43 #include <wtf/PassOwnPtr.h>
44
45 namespace WebCore {
46
47 using namespace VectorMath;
48     
49 AudioBus::AudioBus(unsigned numberOfChannels, size_t length, bool allocate)
50     : m_length(length)
51     , m_busGain(1)
52     , m_isFirstTime(true)
53     , m_sampleRate(0)
54 {
55     m_channels.reserveInitialCapacity(numberOfChannels);
56
57     for (unsigned i = 0; i < numberOfChannels; ++i) {
58         PassOwnPtr<AudioChannel> channel = allocate ? adoptPtr(new AudioChannel(length)) : adoptPtr(new AudioChannel(0, length));
59         m_channels.append(channel);
60     }
61
62     m_layout = LayoutCanonical; // for now this is the only layout we define
63 }
64
65 void AudioBus::setChannelMemory(unsigned channelIndex, float* storage, size_t length)
66 {
67     if (channelIndex < m_channels.size()) {
68         channel(channelIndex)->set(storage, length);
69         m_length = length; // FIXME: verify that this length matches all the other channel lengths
70     }
71 }
72
73 void AudioBus::zero()
74 {
75     for (unsigned i = 0; i < m_channels.size(); ++i)
76         m_channels[i]->zero();
77 }
78
79 AudioChannel* AudioBus::channelByType(unsigned channelType)
80 {
81     // For now we only support canonical channel layouts...
82     if (m_layout != LayoutCanonical)
83         return 0;
84
85     switch (numberOfChannels()) {
86     case 1: // mono
87         if (channelType == ChannelMono || channelType == ChannelLeft)
88             return channel(0);
89         return 0;
90
91     case 2: // stereo
92         switch (channelType) {
93         case ChannelLeft: return channel(0);
94         case ChannelRight: return channel(1);
95         default: return 0;
96         }
97
98     case 4: // quad
99         switch (channelType) {
100         case ChannelLeft: return channel(0);
101         case ChannelRight: return channel(1);
102         case ChannelSurroundLeft: return channel(2);
103         case ChannelSurroundRight: return channel(3);
104         default: return 0;
105         }
106
107     case 5: // 5.0
108         switch (channelType) {
109         case ChannelLeft: return channel(0);
110         case ChannelRight: return channel(1);
111         case ChannelCenter: return channel(2);
112         case ChannelSurroundLeft: return channel(3);
113         case ChannelSurroundRight: return channel(4);
114         default: return 0;
115         }
116
117     case 6: // 5.1
118         switch (channelType) {
119         case ChannelLeft: return channel(0);
120         case ChannelRight: return channel(1);
121         case ChannelCenter: return channel(2);
122         case ChannelLFE: return channel(3);
123         case ChannelSurroundLeft: return channel(4);
124         case ChannelSurroundRight: return channel(5);
125         default: return 0;
126         }
127     }
128     
129     ASSERT_NOT_REACHED();
130     return 0;
131 }
132
133 const AudioChannel* AudioBus::channelByType(unsigned type) const
134 {
135     return const_cast<AudioBus*>(this)->channelByType(type);
136 }
137
138 // Returns true if the channel count and frame-size match.
139 bool AudioBus::topologyMatches(const AudioBus& bus) const
140 {
141     if (numberOfChannels() != bus.numberOfChannels())
142         return false; // channel mismatch
143
144     // Make sure source bus has enough frames.
145     if (length() > bus.length())
146         return false; // frame-size mismatch
147
148     return true;
149 }
150
151 PassOwnPtr<AudioBus> AudioBus::createBufferFromRange(const AudioBus* sourceBuffer, unsigned startFrame, unsigned endFrame)
152 {
153     size_t numberOfSourceFrames = sourceBuffer->length();
154     unsigned numberOfChannels = sourceBuffer->numberOfChannels();
155
156     // Sanity checking
157     bool isRangeSafe = startFrame < endFrame && endFrame <= numberOfSourceFrames;
158     ASSERT(isRangeSafe);
159     if (!isRangeSafe)
160         return nullptr;
161
162     size_t rangeLength = endFrame - startFrame;
163
164     OwnPtr<AudioBus> audioBus = adoptPtr(new AudioBus(numberOfChannels, rangeLength));
165     audioBus->setSampleRate(sourceBuffer->sampleRate());
166
167     for (unsigned i = 0; i < numberOfChannels; ++i)
168         audioBus->channel(i)->copyFromRange(sourceBuffer->channel(i), startFrame, endFrame);
169
170     return audioBus.release();
171 }
172
173 float AudioBus::maxAbsValue() const
174 {
175     float max = 0.0f;
176     for (unsigned i = 0; i < numberOfChannels(); ++i) {
177         const AudioChannel* channel = this->channel(i);
178         max = std::max(max, channel->maxAbsValue());
179     }
180
181     return max;
182 }
183
184 void AudioBus::normalize()
185 {
186     float max = maxAbsValue();
187     if (max)
188         scale(1.0f / max);
189 }
190
191 void AudioBus::scale(float scale)
192 {
193     for (unsigned i = 0; i < numberOfChannels(); ++i)
194         channel(i)->scale(scale);
195 }
196
197 // Just copies the samples from the source bus to this one.
198 // This is just a simple copy if the number of channels match, otherwise a mixup or mixdown is done.
199 // For now, we just support a mixup from mono -> stereo.
200 void AudioBus::copyFrom(const AudioBus& sourceBus)
201 {
202     if (&sourceBus == this)
203         return;
204
205     if (numberOfChannels() == sourceBus.numberOfChannels()) {
206         for (unsigned i = 0; i < numberOfChannels(); ++i)
207             channel(i)->copyFrom(sourceBus.channel(i));
208     } else if (numberOfChannels() == 2 && sourceBus.numberOfChannels() == 1) {
209         // Handle mono -> stereo case (for now simply copy mono channel into both left and right)
210         // FIXME: Really we should apply an equal-power scaling factor here, since we're effectively panning center...
211         const AudioChannel* sourceChannel = sourceBus.channel(0);
212         channel(0)->copyFrom(sourceChannel);
213         channel(1)->copyFrom(sourceChannel);
214     } else {
215         // Case not handled
216         ASSERT_NOT_REACHED();
217     }
218 }
219
220 void AudioBus::sumFrom(const AudioBus &sourceBus)
221 {
222     if (numberOfChannels() == sourceBus.numberOfChannels()) {
223         for (unsigned i = 0; i < numberOfChannels(); ++i)
224             channel(i)->sumFrom(sourceBus.channel(i));
225     } else if (numberOfChannels() == 2 && sourceBus.numberOfChannels() == 1) {
226         // Handle mono -> stereo case (for now simply sum mono channel into both left and right)
227         // FIXME: Really we should apply an equal-power scaling factor here, since we're effectively panning center...
228         const AudioChannel* sourceChannel = sourceBus.channel(0);
229         channel(0)->sumFrom(sourceChannel);
230         channel(1)->sumFrom(sourceChannel);
231     } else {
232         // Case not handled
233         ASSERT_NOT_REACHED();
234     }
235 }
236
237 // Slowly change gain to desired gain.
238 #define GAIN_DEZIPPER \
239     gain += (totalDesiredGain - gain) * DezipperRate; \
240     gain = DenormalDisabler::flushDenormalFloatToZero(gain);
241
242 // De-zipper for the first framesToDezipper frames and skip de-zippering for the remaining frames
243 // because the gain is close enough to the target gain.
244 #define PROCESS_WITH_GAIN(OP) \
245     for (k = 0; k < framesToDezipper; ++k) { \
246         OP \
247         GAIN_DEZIPPER \
248     } \
249     gain = totalDesiredGain; \
250     OP##_V 
251
252 #define STEREO_SUM \
253     { \
254         float sumL = DenormalDisabler::flushDenormalFloatToZero(*destinationL + gain * *sourceL++); \
255         float sumR = DenormalDisabler::flushDenormalFloatToZero(*destinationR + gain * *sourceR++); \
256         *destinationL++ = sumL; \
257         *destinationR++ = sumR; \
258     }
259
260 #define STEREO_SUM_V \
261     { \
262         vsma(sourceL, 1, &gain, destinationL, 1, framesToProcess - k); \
263         vsma(sourceR, 1, &gain, destinationR, 1, framesToProcess - k); \
264     }
265
266 // Mono -> stereo (mix equally into L and R)
267 // FIXME: Really we should apply an equal-power scaling factor here, since we're effectively panning center...
268 #define MONO2STEREO_SUM \
269     { \
270         float scaled = gain * *sourceL++; \
271         float sumL = DenormalDisabler::flushDenormalFloatToZero(*destinationL + scaled); \
272         float sumR = DenormalDisabler::flushDenormalFloatToZero(*destinationR + scaled); \
273         *destinationL++ = sumL; \
274         *destinationR++ = sumR; \
275     }
276
277 #define MONO2STEREO_SUM_V \
278     { \
279         vsma(sourceL, 1, &gain, destinationL, 1, framesToProcess - k); \
280         vsma(sourceL, 1, &gain, destinationR, 1, framesToProcess - k); \
281     }
282     
283 #define MONO_SUM \
284     { \
285         float sum = DenormalDisabler::flushDenormalFloatToZero(*destinationL + gain * *sourceL++); \
286         *destinationL++ = sum; \
287     }
288
289 #define MONO_SUM_V \
290     { \
291         vsma(sourceL, 1, &gain, destinationL, 1, framesToProcess - k); \
292     } 
293
294 #define STEREO_NO_SUM \
295     { \
296         float sampleL = *sourceL++; \
297         float sampleR = *sourceR++; \
298         *destinationL++ = DenormalDisabler::flushDenormalFloatToZero(gain * sampleL); \
299         *destinationR++ = DenormalDisabler::flushDenormalFloatToZero(gain * sampleR); \
300     }
301
302 #define STEREO_NO_SUM_V \
303     { \
304         vsmul(sourceL, 1, &gain, destinationL, 1, framesToProcess - k); \
305         vsmul(sourceR, 1, &gain, destinationR, 1, framesToProcess - k); \
306     }
307
308 // Mono -> stereo (mix equally into L and R)
309 // FIXME: Really we should apply an equal-power scaling factor here, since we're effectively panning center...
310 #define MONO2STEREO_NO_SUM \
311     { \
312         float sample = *sourceL++; \
313         *destinationL++ = DenormalDisabler::flushDenormalFloatToZero(gain * sample); \
314         *destinationR++ = DenormalDisabler::flushDenormalFloatToZero(gain * sample); \
315     }
316
317 #define MONO2STEREO_NO_SUM_V \
318     { \
319         vsmul(sourceL, 1, &gain, destinationL, 1, framesToProcess - k); \
320         vsmul(sourceL, 1, &gain, destinationR, 1, framesToProcess - k); \
321     }
322
323 #define MONO_NO_SUM \
324     { \
325         float sampleL = *sourceL++; \
326         *destinationL++ = DenormalDisabler::flushDenormalFloatToZero(gain * sampleL); \
327     }
328
329 #define MONO_NO_SUM_V \
330     { \
331         vsmul(sourceL, 1, &gain, destinationL, 1, framesToProcess - k); \
332     } 
333
334 void AudioBus::processWithGainFromMonoStereo(const AudioBus &sourceBus, float* lastMixGain, float targetGain, bool sumToBus)
335 {
336     // We don't want to suddenly change the gain from mixing one time slice to the next,
337     // so we "de-zipper" by slowly changing the gain each sample-frame until we've achieved the target gain.
338     
339     // Take master bus gain into account as well as the targetGain.
340     float totalDesiredGain = static_cast<float>(m_busGain * targetGain);
341
342     // First time, snap directly to totalDesiredGain.
343     float gain = static_cast<float>(m_isFirstTime ? totalDesiredGain : *lastMixGain);
344     m_isFirstTime = false;
345
346     int numberOfSourceChannels = sourceBus.numberOfChannels();
347     int numberOfDestinationChannels = numberOfChannels();
348
349     AudioBus& sourceBusSafe = const_cast<AudioBus&>(sourceBus);
350     const float* sourceL = sourceBusSafe.channelByType(ChannelLeft)->data();
351     const float* sourceR = numberOfSourceChannels > 1 ? sourceBusSafe.channelByType(ChannelRight)->data() : 0;
352
353     float* destinationL = channelByType(ChannelLeft)->mutableData();
354     float* destinationR = numberOfDestinationChannels > 1 ? channelByType(ChannelRight)->mutableData() : 0;
355
356     const float DezipperRate = 0.005f;
357     int framesToProcess = length();
358
359     // If the gain is within epsilon of totalDesiredGain, we can skip dezippering. 
360     // FIXME: this value may need tweaking.
361     const float epsilon = 0.001f; 
362     float gainDiff = fabs(totalDesiredGain - gain);
363
364     // Number of frames to de-zipper before we are close enough to the target gain.
365     int framesToDezipper = (gainDiff < epsilon) ? 0 : framesToProcess; 
366
367     int k = 0;
368
369     if (sumToBus) {
370         // Sum to our bus
371         if (sourceR && destinationR) {
372             // Stereo
373             PROCESS_WITH_GAIN(STEREO_SUM)
374         } else if (destinationR) {
375             // Mono -> stereo 
376             PROCESS_WITH_GAIN(MONO2STEREO_SUM)
377         } else {
378             // Mono
379             PROCESS_WITH_GAIN(MONO_SUM)
380         }
381     } else {
382         // Process directly (without summing) to our bus
383         // If it is from the same bus and no need to change gain, just return
384         if (this == &sourceBus && *lastMixGain == targetGain && targetGain == 1.0)
385             return;
386
387         if (sourceR && destinationR) {
388             // Stereo
389             PROCESS_WITH_GAIN(STEREO_NO_SUM)
390         } else if (destinationR) {
391             // Mono -> stereo 
392             PROCESS_WITH_GAIN(MONO2STEREO_NO_SUM)
393         } else {
394             // Mono
395             PROCESS_WITH_GAIN(MONO_NO_SUM)
396         }
397     }
398
399     // Save the target gain as the starting point for next time around.
400     *lastMixGain = gain;
401 }
402
403 void AudioBus::processWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain, bool sumToBus)
404 {
405     // Make sure we're summing from same type of bus.
406     // We *are* able to sum from mono -> stereo
407     if (sourceBus.numberOfChannels() != 1 && !topologyMatches(sourceBus)) {
408         ASSERT_NOT_REACHED();
409         return;
410     }
411
412     // Dispatch for different channel layouts
413     switch (numberOfChannels()) {
414     case 1: // mono
415     case 2: // stereo
416         processWithGainFromMonoStereo(sourceBus, lastMixGain, targetGain, sumToBus);
417         break;
418     case 4: // FIXME: implement quad
419     case 5: // FIXME: implement 5.0
420     default:
421         ASSERT_NOT_REACHED();
422         break;
423     }
424 }
425
426 void AudioBus::copyWithSampleAccurateGainValuesFrom(const AudioBus &sourceBus, float* gainValues, unsigned numberOfGainValues)
427 {
428     // Make sure we're processing from the same type of bus.
429     // We *are* able to process from mono -> stereo
430     if (sourceBus.numberOfChannels() != 1 && !topologyMatches(sourceBus)) {
431         ASSERT_NOT_REACHED();
432         return;
433     }
434
435     if (!gainValues || numberOfGainValues > sourceBus.length()) {
436         ASSERT_NOT_REACHED();
437         return;
438     }
439
440     // We handle both the 1 -> N and N -> N case here.
441     const float* source = sourceBus.channel(0)->data();
442     for (unsigned channelIndex = 0; channelIndex < numberOfChannels(); ++channelIndex) {
443         if (sourceBus.numberOfChannels() == numberOfChannels())
444             source = sourceBus.channel(channelIndex)->data();
445         float* destination = channel(channelIndex)->mutableData();
446         vmul(source, 1, gainValues, 1, destination, 1, numberOfGainValues);
447     }
448 }
449
450 void AudioBus::copyWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain)
451 {
452     processWithGainFrom(sourceBus, lastMixGain, targetGain, false);
453 }
454
455 void AudioBus::sumWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain)
456 {
457     processWithGainFrom(sourceBus, lastMixGain, targetGain, true);
458 }
459
460 PassOwnPtr<AudioBus> AudioBus::createBySampleRateConverting(const AudioBus* sourceBus, bool mixToMono, double newSampleRate)
461 {
462     // sourceBus's sample-rate must be known.
463     ASSERT(sourceBus && sourceBus->sampleRate());
464     if (!sourceBus || !sourceBus->sampleRate())
465         return nullptr;
466
467     double sourceSampleRate = sourceBus->sampleRate();
468     double destinationSampleRate = newSampleRate;
469     unsigned numberOfSourceChannels = sourceBus->numberOfChannels();
470
471     if (numberOfSourceChannels == 1)
472         mixToMono = false; // already mono
473         
474     if (sourceSampleRate == destinationSampleRate) {
475         // No sample-rate conversion is necessary.
476         if (mixToMono)
477             return AudioBus::createByMixingToMono(sourceBus);
478
479         // Return exact copy.
480         return AudioBus::createBufferFromRange(sourceBus, 0, sourceBus->length());
481     }
482     
483     // First, mix to mono (if necessary) then sample-rate convert.
484     const AudioBus* resamplerSourceBus;
485     OwnPtr<AudioBus> mixedMonoBus;
486     if (mixToMono) {
487         mixedMonoBus = AudioBus::createByMixingToMono(sourceBus);
488         resamplerSourceBus = mixedMonoBus.get();
489     } else {
490         // Directly resample without down-mixing.
491         resamplerSourceBus = sourceBus;
492     }
493
494     // Calculate destination length based on the sample-rates.
495     double sampleRateRatio = sourceSampleRate / destinationSampleRate;
496     int sourceLength = resamplerSourceBus->length();
497     int destinationLength = sourceLength / sampleRateRatio;
498
499     // Create destination bus with same number of channels.
500     unsigned numberOfDestinationChannels = resamplerSourceBus->numberOfChannels();
501     OwnPtr<AudioBus> destinationBus(adoptPtr(new AudioBus(numberOfDestinationChannels, destinationLength)));
502
503     // Sample-rate convert each channel.
504     for (unsigned i = 0; i < numberOfDestinationChannels; ++i) {
505         const float* source = resamplerSourceBus->channel(i)->data();
506         float* destination = destinationBus->channel(i)->mutableData();
507
508         SincResampler resampler(sampleRateRatio);
509         resampler.process(source, destination, sourceLength);
510     }
511
512     destinationBus->setSampleRate(newSampleRate);    
513     return destinationBus.release();
514 }
515
516 PassOwnPtr<AudioBus> AudioBus::createByMixingToMono(const AudioBus* sourceBus)
517 {
518     switch (sourceBus->numberOfChannels()) {
519     case 1:
520         // Simply create an exact copy.
521         return AudioBus::createBufferFromRange(sourceBus, 0, sourceBus->length());
522     case 2:
523         {
524             unsigned n = sourceBus->length();
525             OwnPtr<AudioBus> destinationBus(adoptPtr(new AudioBus(1, n)));
526
527             const float* sourceL = sourceBus->channel(0)->data();
528             const float* sourceR = sourceBus->channel(1)->data();
529             float* destination = destinationBus->channel(0)->mutableData();
530         
531             // Do the mono mixdown.
532             for (unsigned i = 0; i < n; ++i)
533                 destination[i] = (sourceL[i] + sourceR[i]) / 2;
534
535             destinationBus->setSampleRate(sourceBus->sampleRate());    
536             return destinationBus.release();
537         }
538     }
539
540     ASSERT_NOT_REACHED();
541     return nullptr;
542 }
543
544 } // WebCore
545
546 #endif // ENABLE(WEB_AUDIO)