2 * Copyright (C) 2010 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
36 #include "SincResampler.h"
38 #include "VectorMath.h"
42 #include <wtf/OwnPtr.h>
43 #include <wtf/PassOwnPtr.h>
47 using namespace VectorMath;
49 AudioBus::AudioBus(unsigned numberOfChannels, size_t length, bool allocate)
55 m_channels.reserveInitialCapacity(numberOfChannels);
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);
62 m_layout = LayoutCanonical; // for now this is the only layout we define
65 void AudioBus::setChannelMemory(unsigned channelIndex, float* storage, size_t length)
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
75 for (unsigned i = 0; i < m_channels.size(); ++i)
76 m_channels[i]->zero();
79 AudioChannel* AudioBus::channelByType(unsigned channelType)
81 // For now we only support canonical channel layouts...
82 if (m_layout != LayoutCanonical)
85 switch (numberOfChannels()) {
87 if (channelType == ChannelMono || channelType == ChannelLeft)
92 switch (channelType) {
93 case ChannelLeft: return channel(0);
94 case ChannelRight: return channel(1);
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);
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);
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);
129 ASSERT_NOT_REACHED();
133 // Returns true if the channel count and frame-size match.
134 bool AudioBus::topologyMatches(const AudioBus& bus) const
136 if (numberOfChannels() != bus.numberOfChannels())
137 return false; // channel mismatch
139 // Make sure source bus has enough frames.
140 if (length() > bus.length())
141 return false; // frame-size mismatch
146 PassOwnPtr<AudioBus> AudioBus::createBufferFromRange(AudioBus* sourceBuffer, unsigned startFrame, unsigned endFrame)
148 size_t numberOfSourceFrames = sourceBuffer->length();
149 unsigned numberOfChannels = sourceBuffer->numberOfChannels();
152 bool isRangeSafe = startFrame < endFrame && endFrame <= numberOfSourceFrames;
157 size_t rangeLength = endFrame - startFrame;
159 OwnPtr<AudioBus> audioBus = adoptPtr(new AudioBus(numberOfChannels, rangeLength));
160 audioBus->setSampleRate(sourceBuffer->sampleRate());
162 for (unsigned i = 0; i < numberOfChannels; ++i)
163 audioBus->channel(i)->copyFromRange(sourceBuffer->channel(i), startFrame, endFrame);
165 return audioBus.release();
168 float AudioBus::maxAbsValue() const
171 for (unsigned i = 0; i < numberOfChannels(); ++i) {
172 const AudioChannel* channel = this->channel(i);
173 max = std::max(max, channel->maxAbsValue());
179 void AudioBus::normalize()
181 float max = maxAbsValue();
186 void AudioBus::scale(double scale)
188 for (unsigned i = 0; i < numberOfChannels(); ++i)
189 channel(i)->scale(scale);
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)
197 if (&sourceBus == this)
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);
211 ASSERT_NOT_REACHED();
215 void AudioBus::sumFrom(const AudioBus &sourceBus)
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);
228 ASSERT_NOT_REACHED();
232 void AudioBus::processWithGainFromMonoStereo(const AudioBus &sourceBus, double* lastMixGain, double targetGain, bool sumToBus)
234 // We don't want to suddenly change the gain from mixing one time slice to the next,
235 // so we "de-zipper" by slowly changing the gain each sample-frame until we've achieved the target gain.
237 // FIXME: optimize this method (SSE, etc.)
238 // FIXME: Need fast path here when gain has converged on targetGain. In this case, de-zippering is no longer needed.
239 // FIXME: Need fast path when this==sourceBus && lastMixGain==targetGain==1.0 && sumToBus==false (this is a NOP)
241 // Take master bus gain into account as well as the targetGain.
242 double totalDesiredGain = m_busGain * targetGain;
244 // First time, snap directly to totalDesiredGain.
245 double gain = m_isFirstTime ? totalDesiredGain : *lastMixGain;
246 m_isFirstTime = false;
248 int numberOfSourceChannels = sourceBus.numberOfChannels();
249 int numberOfDestinationChannels = numberOfChannels();
251 AudioBus& sourceBusSafe = const_cast<AudioBus&>(sourceBus);
252 const float* sourceL = sourceBusSafe.channelByType(ChannelLeft)->data();
253 const float* sourceR = numberOfSourceChannels > 1 ? sourceBusSafe.channelByType(ChannelRight)->data() : 0;
255 float* destinationL = channelByType(ChannelLeft)->data();
256 float* destinationR = numberOfDestinationChannels > 1 ? channelByType(ChannelRight)->data() : 0;
258 const double DezipperRate = 0.005;
259 int framesToProcess = length();
263 if (sourceR && destinationR) {
265 while (framesToProcess--) {
266 float sampleL = *sourceL++;
267 float sampleR = *sourceR++;
268 *destinationL++ += static_cast<float>(gain * sampleL);
269 *destinationR++ += static_cast<float>(gain * sampleR);
271 // Slowly change gain to desired gain.
272 gain += (totalDesiredGain - gain) * DezipperRate;
274 } else if (destinationR) {
275 // Mono -> stereo (mix equally into L and R)
276 // FIXME: Really we should apply an equal-power scaling factor here, since we're effectively panning center...
277 while (framesToProcess--) {
278 float sample = *sourceL++;
279 *destinationL++ += static_cast<float>(gain * sample);
280 *destinationR++ += static_cast<float>(gain * sample);
282 // Slowly change gain to desired gain.
283 gain += (totalDesiredGain - gain) * DezipperRate;
287 while (framesToProcess--) {
288 float sampleL = *sourceL++;
289 *destinationL++ += static_cast<float>(gain * sampleL);
291 // Slowly change gain to desired gain.
292 gain += (totalDesiredGain - gain) * DezipperRate;
296 // Process directly (without summing) to our bus
297 if (sourceR && destinationR) {
299 while (framesToProcess--) {
300 float sampleL = *sourceL++;
301 float sampleR = *sourceR++;
302 *destinationL++ = static_cast<float>(gain * sampleL);
303 *destinationR++ = static_cast<float>(gain * sampleR);
305 // Slowly change gain to desired gain.
306 gain += (totalDesiredGain - gain) * DezipperRate;
308 } else if (destinationR) {
309 // Mono -> stereo (mix equally into L and R)
310 // FIXME: Really we should apply an equal-power scaling factor here, since we're effectively panning center...
311 while (framesToProcess--) {
312 float sample = *sourceL++;
313 *destinationL++ = static_cast<float>(gain * sample);
314 *destinationR++ = static_cast<float>(gain * sample);
316 // Slowly change gain to desired gain.
317 gain += (totalDesiredGain - gain) * DezipperRate;
321 while (framesToProcess--) {
322 float sampleL = *sourceL++;
323 *destinationL++ = static_cast<float>(gain * sampleL);
325 // Slowly change gain to desired gain.
326 gain += (totalDesiredGain - gain) * DezipperRate;
331 // Save the target gain as the starting point for next time around.
335 void AudioBus::processWithGainFrom(const AudioBus &sourceBus, double* lastMixGain, double targetGain, bool sumToBus)
337 // Make sure we're summing from same type of bus.
338 // We *are* able to sum from mono -> stereo
339 if (sourceBus.numberOfChannels() != 1 && !topologyMatches(sourceBus))
342 // Dispatch for different channel layouts
343 switch (numberOfChannels()) {
346 processWithGainFromMonoStereo(sourceBus, lastMixGain, targetGain, sumToBus);
348 case 4: // FIXME: implement quad
349 case 5: // FIXME: implement 5.0
351 ASSERT_NOT_REACHED();
356 void AudioBus::copyWithGainFrom(const AudioBus &sourceBus, double* lastMixGain, double targetGain)
358 processWithGainFrom(sourceBus, lastMixGain, targetGain, false);
361 void AudioBus::sumWithGainFrom(const AudioBus &sourceBus, double* lastMixGain, double targetGain)
363 processWithGainFrom(sourceBus, lastMixGain, targetGain, true);
367 PassOwnPtr<AudioBus> AudioBus::createBySampleRateConverting(AudioBus* sourceBus, bool mixToMono, double newSampleRate)
369 // sourceBus's sample-rate must be known.
370 ASSERT(sourceBus && sourceBus->sampleRate());
371 if (!sourceBus || !sourceBus->sampleRate())
374 double sourceSampleRate = sourceBus->sampleRate();
375 double destinationSampleRate = newSampleRate;
376 unsigned numberOfSourceChannels = sourceBus->numberOfChannels();
378 if (numberOfSourceChannels == 1)
379 mixToMono = false; // already mono
381 if (sourceSampleRate == destinationSampleRate) {
382 // No sample-rate conversion is necessary.
384 return AudioBus::createByMixingToMono(sourceBus);
386 // Return exact copy.
387 return AudioBus::createBufferFromRange(sourceBus, 0, sourceBus->length());
390 // First, mix to mono (if necessary) then sample-rate convert.
391 AudioBus* resamplerSourceBus;
392 OwnPtr<AudioBus> mixedMonoBus;
394 mixedMonoBus = AudioBus::createByMixingToMono(sourceBus);
395 resamplerSourceBus = mixedMonoBus.get();
397 // Directly resample without down-mixing.
398 resamplerSourceBus = sourceBus;
401 // Calculate destination length based on the sample-rates.
402 double sampleRateRatio = sourceSampleRate / destinationSampleRate;
403 int sourceLength = resamplerSourceBus->length();
404 int destinationLength = sourceLength / sampleRateRatio;
406 // Create destination bus with same number of channels.
407 unsigned numberOfDestinationChannels = resamplerSourceBus->numberOfChannels();
408 OwnPtr<AudioBus> destinationBus(adoptPtr(new AudioBus(numberOfDestinationChannels, destinationLength)));
410 // Sample-rate convert each channel.
411 for (unsigned i = 0; i < numberOfDestinationChannels; ++i) {
412 float* source = resamplerSourceBus->channel(i)->data();
413 float* destination = destinationBus->channel(i)->data();
415 SincResampler resampler(sampleRateRatio);
416 resampler.process(source, destination, sourceLength);
419 destinationBus->setSampleRate(newSampleRate);
420 return destinationBus.release();
422 #endif // !PLATFORM(MAC)
424 PassOwnPtr<AudioBus> AudioBus::createByMixingToMono(AudioBus* sourceBus)
426 switch (sourceBus->numberOfChannels()) {
428 // Simply create an exact copy.
429 return AudioBus::createBufferFromRange(sourceBus, 0, sourceBus->length());
432 unsigned n = sourceBus->length();
433 OwnPtr<AudioBus> destinationBus(adoptPtr(new AudioBus(1, n)));
435 float* sourceL = sourceBus->channel(0)->data();
436 float* sourceR = sourceBus->channel(1)->data();
437 float* destination = destinationBus->channel(0)->data();
439 // Do the mono mixdown.
440 for (unsigned i = 0; i < n; ++i)
441 destination[i] = 0.5 * (sourceL[i] + sourceR[i]);
443 destinationBus->setSampleRate(sourceBus->sampleRate());
444 return destinationBus.release();
448 ASSERT_NOT_REACHED();
454 #endif // ENABLE(WEB_AUDIO)