30489baa751e1343d6729af468b69258c70a7cac
[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 // Returns true if the channel count and frame-size match.
134 bool AudioBus::topologyMatches(const AudioBus& bus) const
135 {
136     if (numberOfChannels() != bus.numberOfChannels())
137         return false; // channel mismatch
138
139     // Make sure source bus has enough frames.
140     if (length() > bus.length())
141         return false; // frame-size mismatch
142
143     return true;
144 }
145
146 PassOwnPtr<AudioBus> AudioBus::createBufferFromRange(AudioBus* sourceBuffer, unsigned startFrame, unsigned endFrame)
147 {
148     size_t numberOfSourceFrames = sourceBuffer->length();
149     unsigned numberOfChannels = sourceBuffer->numberOfChannels();
150
151     // Sanity checking
152     bool isRangeSafe = startFrame < endFrame && endFrame <= numberOfSourceFrames;
153     ASSERT(isRangeSafe);
154     if (!isRangeSafe)
155         return nullptr;
156
157     size_t rangeLength = endFrame - startFrame;
158
159     OwnPtr<AudioBus> audioBus = adoptPtr(new AudioBus(numberOfChannels, rangeLength));
160     audioBus->setSampleRate(sourceBuffer->sampleRate());
161
162     for (unsigned i = 0; i < numberOfChannels; ++i)
163         audioBus->channel(i)->copyFromRange(sourceBuffer->channel(i), startFrame, endFrame);
164
165     return audioBus.release();
166 }
167
168 float AudioBus::maxAbsValue() const
169 {
170     float max = 0.0f;
171     for (unsigned i = 0; i < numberOfChannels(); ++i) {
172         const AudioChannel* channel = this->channel(i);
173         max = std::max(max, channel->maxAbsValue());
174     }
175
176     return max;
177 }
178
179 void AudioBus::normalize()
180 {
181     float max = maxAbsValue();
182     if (max)
183         scale(1.0f / max);
184 }
185
186 void AudioBus::scale(float scale)
187 {
188     for (unsigned i = 0; i < numberOfChannels(); ++i)
189         channel(i)->scale(scale);
190 }
191
192 // Just copies the samples from the source bus to this one.
193 // This is just a simple copy if the number of channels match, otherwise a mixup or mixdown is done.
194 // For now, we just support a mixup from mono -> stereo.
195 void AudioBus::copyFrom(const AudioBus& sourceBus)
196 {
197     if (&sourceBus == this)
198         return;
199
200     if (numberOfChannels() == sourceBus.numberOfChannels()) {
201         for (unsigned i = 0; i < numberOfChannels(); ++i)
202             channel(i)->copyFrom(sourceBus.channel(i));
203     } else if (numberOfChannels() == 2 && sourceBus.numberOfChannels() == 1) {
204         // Handle mono -> stereo case (for now simply copy mono channel into both left and right)
205         // FIXME: Really we should apply an equal-power scaling factor here, since we're effectively panning center...
206         const AudioChannel* sourceChannel = sourceBus.channel(0);
207         channel(0)->copyFrom(sourceChannel);
208         channel(1)->copyFrom(sourceChannel);
209     } else {
210         // Case not handled
211         ASSERT_NOT_REACHED();
212     }
213 }
214
215 void AudioBus::sumFrom(const AudioBus &sourceBus)
216 {
217     if (numberOfChannels() == sourceBus.numberOfChannels()) {
218         for (unsigned i = 0; i < numberOfChannels(); ++i)
219             channel(i)->sumFrom(sourceBus.channel(i));
220     } else if (numberOfChannels() == 2 && sourceBus.numberOfChannels() == 1) {
221         // Handle mono -> stereo case (for now simply sum mono channel into both left and right)
222         // FIXME: Really we should apply an equal-power scaling factor here, since we're effectively panning center...
223         const AudioChannel* sourceChannel = sourceBus.channel(0);
224         channel(0)->sumFrom(sourceChannel);
225         channel(1)->sumFrom(sourceChannel);
226     } else {
227         // Case not handled
228         ASSERT_NOT_REACHED();
229     }
230 }
231
232 // Slowly change gain to desired gain.
233 #define GAIN_DEZIPPER \
234     gain += (totalDesiredGain - gain) * DezipperRate; \
235     gain = DenormalDisabler::flushDenormalFloatToZero(gain);
236
237 // De-zipper for the first framesToDezipper frames and skip de-zippering for the remaining frames
238 // because the gain is close enough to the target gain.
239 #define PROCESS_WITH_GAIN(OP) \
240     for (k = 0; k < framesToDezipper; ++k) { \
241         OP \
242         GAIN_DEZIPPER \
243     } \
244     gain = totalDesiredGain; \
245     OP##_V 
246
247 #define STEREO_SUM \
248     { \
249         float sumL = DenormalDisabler::flushDenormalFloatToZero(*destinationL + gain * *sourceL++); \
250         float sumR = DenormalDisabler::flushDenormalFloatToZero(*destinationR + gain * *sourceR++); \
251         *destinationL++ = sumL; \
252         *destinationR++ = sumR; \
253     }
254
255 #define STEREO_SUM_V \
256     { \
257         vsma(sourceL, 1, &gain, destinationL, 1, framesToProcess - k); \
258         vsma(sourceR, 1, &gain, destinationR, 1, framesToProcess - k); \
259     }
260
261 // Mono -> stereo (mix equally into L and R)
262 // FIXME: Really we should apply an equal-power scaling factor here, since we're effectively panning center...
263 #define MONO2STEREO_SUM \
264     { \
265         float scaled = gain * *sourceL++; \
266         float sumL = DenormalDisabler::flushDenormalFloatToZero(*destinationL + scaled); \
267         float sumR = DenormalDisabler::flushDenormalFloatToZero(*destinationR + scaled); \
268         *destinationL++ = sumL; \
269         *destinationR++ = sumR; \
270     }
271
272 #define MONO2STEREO_SUM_V \
273     { \
274         vsma(sourceL, 1, &gain, destinationL, 1, framesToProcess - k); \
275         vsma(sourceL, 1, &gain, destinationR, 1, framesToProcess - k); \
276     }
277     
278 #define MONO_SUM \
279     { \
280         float sum = DenormalDisabler::flushDenormalFloatToZero(*destinationL + gain * *sourceL++); \
281         *destinationL++ = sum; \
282     }
283
284 #define MONO_SUM_V \
285     { \
286         vsma(sourceL, 1, &gain, destinationL, 1, framesToProcess - k); \
287     } 
288
289 #define STEREO_NO_SUM \
290     { \
291         float sampleL = *sourceL++; \
292         float sampleR = *sourceR++; \
293         *destinationL++ = DenormalDisabler::flushDenormalFloatToZero(gain * sampleL); \
294         *destinationR++ = DenormalDisabler::flushDenormalFloatToZero(gain * sampleR); \
295     }
296
297 #define STEREO_NO_SUM_V \
298     { \
299         vsmul(sourceL, 1, &gain, destinationL, 1, framesToProcess - k); \
300         vsmul(sourceR, 1, &gain, destinationR, 1, framesToProcess - k); \
301     }
302
303 // Mono -> stereo (mix equally into L and R)
304 // FIXME: Really we should apply an equal-power scaling factor here, since we're effectively panning center...
305 #define MONO2STEREO_NO_SUM \
306     { \
307         float sample = *sourceL++; \
308         *destinationL++ = DenormalDisabler::flushDenormalFloatToZero(gain * sample); \
309         *destinationR++ = DenormalDisabler::flushDenormalFloatToZero(gain * sample); \
310     }
311
312 #define MONO2STEREO_NO_SUM_V \
313     { \
314         vsmul(sourceL, 1, &gain, destinationL, 1, framesToProcess - k); \
315         vsmul(sourceL, 1, &gain, destinationR, 1, framesToProcess - k); \
316     }
317
318 #define MONO_NO_SUM \
319     { \
320         float sampleL = *sourceL++; \
321         *destinationL++ = DenormalDisabler::flushDenormalFloatToZero(gain * sampleL); \
322     }
323
324 #define MONO_NO_SUM_V \
325     { \
326         vsmul(sourceL, 1, &gain, destinationL, 1, framesToProcess - k); \
327     } 
328
329 void AudioBus::processWithGainFromMonoStereo(const AudioBus &sourceBus, float* lastMixGain, float targetGain, bool sumToBus)
330 {
331     // We don't want to suddenly change the gain from mixing one time slice to the next,
332     // so we "de-zipper" by slowly changing the gain each sample-frame until we've achieved the target gain.
333     
334     // Take master bus gain into account as well as the targetGain.
335     float totalDesiredGain = static_cast<float>(m_busGain * targetGain);
336
337     // First time, snap directly to totalDesiredGain.
338     float gain = static_cast<float>(m_isFirstTime ? totalDesiredGain : *lastMixGain);
339     m_isFirstTime = false;
340
341     int numberOfSourceChannels = sourceBus.numberOfChannels();
342     int numberOfDestinationChannels = numberOfChannels();
343
344     AudioBus& sourceBusSafe = const_cast<AudioBus&>(sourceBus);
345     const float* sourceL = sourceBusSafe.channelByType(ChannelLeft)->data();
346     const float* sourceR = numberOfSourceChannels > 1 ? sourceBusSafe.channelByType(ChannelRight)->data() : 0;
347
348     float* destinationL = channelByType(ChannelLeft)->data();
349     float* destinationR = numberOfDestinationChannels > 1 ? channelByType(ChannelRight)->data() : 0;
350
351     const float DezipperRate = 0.005f;
352     int framesToProcess = length();
353
354     // If the gain is within epsilon of totalDesiredGain, we can skip dezippering. 
355     // FIXME: this value may need tweaking.
356     const float epsilon = 0.001f; 
357     float gainDiff = fabs(totalDesiredGain - gain);
358
359     // Number of frames to de-zipper before we are close enough to the target gain.
360     int framesToDezipper = (gainDiff < epsilon) ? 0 : framesToProcess; 
361
362     int k = 0;
363
364     if (sumToBus) {
365         // Sum to our bus
366         if (sourceR && destinationR) {
367             // Stereo
368             PROCESS_WITH_GAIN(STEREO_SUM)
369         } else if (destinationR) {
370             // Mono -> stereo 
371             PROCESS_WITH_GAIN(MONO2STEREO_SUM)
372         } else {
373             // Mono
374             PROCESS_WITH_GAIN(MONO_SUM)
375         }
376     } else {
377         // Process directly (without summing) to our bus
378         // If it is from the same bus and no need to change gain, just return
379         if (this == &sourceBus && *lastMixGain == targetGain && targetGain == 1.0)
380             return;
381
382         if (sourceR && destinationR) {
383             // Stereo
384             PROCESS_WITH_GAIN(STEREO_NO_SUM)
385         } else if (destinationR) {
386             // Mono -> stereo 
387             PROCESS_WITH_GAIN(MONO2STEREO_NO_SUM)
388         } else {
389             // Mono
390             PROCESS_WITH_GAIN(MONO_NO_SUM)
391         }
392     }
393
394     // Save the target gain as the starting point for next time around.
395     *lastMixGain = gain;
396 }
397
398 void AudioBus::processWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain, bool sumToBus)
399 {
400     // Make sure we're summing from same type of bus.
401     // We *are* able to sum from mono -> stereo
402     if (sourceBus.numberOfChannels() != 1 && !topologyMatches(sourceBus)) {
403         ASSERT_NOT_REACHED();
404         return;
405     }
406
407     // Dispatch for different channel layouts
408     switch (numberOfChannels()) {
409     case 1: // mono
410     case 2: // stereo
411         processWithGainFromMonoStereo(sourceBus, lastMixGain, targetGain, sumToBus);
412         break;
413     case 4: // FIXME: implement quad
414     case 5: // FIXME: implement 5.0
415     default:
416         ASSERT_NOT_REACHED();
417         break;
418     }
419 }
420
421 void AudioBus::copyWithSampleAccurateGainValuesFrom(const AudioBus &sourceBus, float* gainValues, unsigned numberOfGainValues)
422 {
423     // Make sure we're processing from the same type of bus.
424     // We *are* able to process from mono -> stereo
425     if (sourceBus.numberOfChannels() != 1 && !topologyMatches(sourceBus)) {
426         ASSERT_NOT_REACHED();
427         return;
428     }
429
430     if (!gainValues || numberOfGainValues > sourceBus.length()) {
431         ASSERT_NOT_REACHED();
432         return;
433     }
434
435     // We handle both the 1 -> N and N -> N case here.
436     const float* source = sourceBus.channel(0)->data();
437     for (unsigned channelIndex = 0; channelIndex < numberOfChannels(); ++channelIndex) {
438         if (sourceBus.numberOfChannels() == numberOfChannels())
439             source = sourceBus.channel(channelIndex)->data();
440         float* destination = channel(channelIndex)->data();
441         vmul(source, 1, gainValues, 1, destination, 1, numberOfGainValues);
442     }
443 }
444
445 void AudioBus::copyWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain)
446 {
447     processWithGainFrom(sourceBus, lastMixGain, targetGain, false);
448 }
449
450 void AudioBus::sumWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain)
451 {
452     processWithGainFrom(sourceBus, lastMixGain, targetGain, true);
453 }
454
455 PassOwnPtr<AudioBus> AudioBus::createBySampleRateConverting(AudioBus* sourceBus, bool mixToMono, double newSampleRate)
456 {
457     // sourceBus's sample-rate must be known.
458     ASSERT(sourceBus && sourceBus->sampleRate());
459     if (!sourceBus || !sourceBus->sampleRate())
460         return nullptr;
461
462     double sourceSampleRate = sourceBus->sampleRate();
463     double destinationSampleRate = newSampleRate;
464     unsigned numberOfSourceChannels = sourceBus->numberOfChannels();
465
466     if (numberOfSourceChannels == 1)
467         mixToMono = false; // already mono
468         
469     if (sourceSampleRate == destinationSampleRate) {
470         // No sample-rate conversion is necessary.
471         if (mixToMono)
472             return AudioBus::createByMixingToMono(sourceBus);
473
474         // Return exact copy.
475         return AudioBus::createBufferFromRange(sourceBus, 0, sourceBus->length());
476     }
477     
478     // First, mix to mono (if necessary) then sample-rate convert.
479     AudioBus* resamplerSourceBus;
480     OwnPtr<AudioBus> mixedMonoBus;
481     if (mixToMono) {
482         mixedMonoBus = AudioBus::createByMixingToMono(sourceBus);
483         resamplerSourceBus = mixedMonoBus.get();
484     } else {
485         // Directly resample without down-mixing.
486         resamplerSourceBus = sourceBus;
487     }
488
489     // Calculate destination length based on the sample-rates.
490     double sampleRateRatio = sourceSampleRate / destinationSampleRate;
491     int sourceLength = resamplerSourceBus->length();
492     int destinationLength = sourceLength / sampleRateRatio;
493
494     // Create destination bus with same number of channels.
495     unsigned numberOfDestinationChannels = resamplerSourceBus->numberOfChannels();
496     OwnPtr<AudioBus> destinationBus(adoptPtr(new AudioBus(numberOfDestinationChannels, destinationLength)));
497
498     // Sample-rate convert each channel.
499     for (unsigned i = 0; i < numberOfDestinationChannels; ++i) {
500         float* source = resamplerSourceBus->channel(i)->data();
501         float* destination = destinationBus->channel(i)->data();
502
503         SincResampler resampler(sampleRateRatio);
504         resampler.process(source, destination, sourceLength);
505     }
506
507     destinationBus->setSampleRate(newSampleRate);    
508     return destinationBus.release();
509 }
510
511 PassOwnPtr<AudioBus> AudioBus::createByMixingToMono(AudioBus* sourceBus)
512 {
513     switch (sourceBus->numberOfChannels()) {
514     case 1:
515         // Simply create an exact copy.
516         return AudioBus::createBufferFromRange(sourceBus, 0, sourceBus->length());
517     case 2:
518         {
519             unsigned n = sourceBus->length();
520             OwnPtr<AudioBus> destinationBus(adoptPtr(new AudioBus(1, n)));
521
522             float* sourceL = sourceBus->channel(0)->data();
523             float* sourceR = sourceBus->channel(1)->data();
524             float* destination = destinationBus->channel(0)->data();
525         
526             // Do the mono mixdown.
527             for (unsigned i = 0; i < n; ++i)
528                 destination[i] = (sourceL[i] + sourceR[i]) / 2;
529
530             destinationBus->setSampleRate(sourceBus->sampleRate());    
531             return destinationBus.release();
532         }
533     }
534
535     ASSERT_NOT_REACHED();
536     return nullptr;
537 }
538
539 } // WebCore
540
541 #endif // ENABLE(WEB_AUDIO)