Modified: trunk/Source/WebCore/platform/audio/AudioBus.cpp (116595 => 116596)
--- trunk/Source/WebCore/platform/audio/AudioBus.cpp 2012-05-10 02:00:38 UTC (rev 116595)
+++ trunk/Source/WebCore/platform/audio/AudioBus.cpp 2012-05-10 02:32:46 UTC (rev 116596)
@@ -45,13 +45,19 @@
namespace WebCore {
using namespace VectorMath;
-
+
+const unsigned MaxBusChannels = 32;
+
AudioBus::AudioBus(unsigned numberOfChannels, size_t length, bool allocate)
: m_length(length)
, m_busGain(1)
, m_isFirstTime(true)
, m_sampleRate(0)
{
+ ASSERT(numberOfChannels <= MaxBusChannels);
+ if (numberOfChannels > MaxBusChannels)
+ return;
+
m_channels.reserveInitialCapacity(numberOfChannels);
for (unsigned i = 0; i < numberOfChannels; ++i) {
@@ -307,106 +313,37 @@
}
}
-// Slowly change gain to desired gain.
-#define GAIN_DEZIPPER \
- gain += (totalDesiredGain - gain) * DezipperRate; \
- gain = DenormalDisabler::flushDenormalFloatToZero(gain);
-
-// De-zipper for the first framesToDezipper frames and skip de-zippering for the remaining frames
-// because the gain is close enough to the target gain.
-#define PROCESS_WITH_GAIN(OP) \
- for (k = 0; k < framesToDezipper; ++k) { \
- OP \
- GAIN_DEZIPPER \
- } \
- if (!framesToDezipper) \
- gain = totalDesiredGain; \
- OP##_V
-
-#define STEREO_SUM \
- { \
- float sumL = DenormalDisabler::flushDenormalFloatToZero(*destinationL + gain * *sourceL++); \
- float sumR = DenormalDisabler::flushDenormalFloatToZero(*destinationR + gain * *sourceR++); \
- *destinationL++ = sumL; \
- *destinationR++ = sumR; \
+void AudioBus::copyWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain)
+{
+ if (!topologyMatches(sourceBus)) {
+ ASSERT_NOT_REACHED();
+ zero();
+ return;
}
-#define STEREO_SUM_V \
- { \
- vsma(sourceL, 1, &gain, destinationL, 1, framesToProcess - k); \
- vsma(sourceR, 1, &gain, destinationR, 1, framesToProcess - k); \
+ if (sourceBus.isSilent()) {
+ zero();
+ return;
}
-// Mono -> stereo (mix equally into L and R)
-// FIXME: Really we should apply an equal-power scaling factor here, since we're effectively panning center...
-#define MONO2STEREO_SUM \
- { \
- float scaled = gain * *sourceL++; \
- float sumL = DenormalDisabler::flushDenormalFloatToZero(*destinationL + scaled); \
- float sumR = DenormalDisabler::flushDenormalFloatToZero(*destinationR + scaled); \
- *destinationL++ = sumL; \
- *destinationR++ = sumR; \
- }
+ unsigned numberOfChannels = this->numberOfChannels();
+ ASSERT(numberOfChannels <= MaxBusChannels);
+ if (numberOfChannels > MaxBusChannels)
+ return;
-#define MONO2STEREO_SUM_V \
- { \
- vsma(sourceL, 1, &gain, destinationL, 1, framesToProcess - k); \
- vsma(sourceL, 1, &gain, destinationR, 1, framesToProcess - k); \
- }
-
-#define MONO_SUM \
- { \
- float sum = DenormalDisabler::flushDenormalFloatToZero(*destinationL + gain * *sourceL++); \
- *destinationL++ = sum; \
- }
+ // If it is copying from the same bus and no need to change gain, just return.
+ if (this == &sourceBus && *lastMixGain == targetGain && targetGain == 1)
+ return;
-#define MONO_SUM_V \
- { \
- vsma(sourceL, 1, &gain, destinationL, 1, framesToProcess - k); \
- }
+ AudioBus& sourceBusSafe = const_cast<AudioBus&>(sourceBus);
+ const float* sources[MaxBusChannels];
+ float* destinations[MaxBusChannels];
-#define STEREO_NO_SUM \
- { \
- float sampleL = *sourceL++; \
- float sampleR = *sourceR++; \
- *destinationL++ = DenormalDisabler::flushDenormalFloatToZero(gain * sampleL); \
- *destinationR++ = DenormalDisabler::flushDenormalFloatToZero(gain * sampleR); \
+ for (unsigned i = 0; i < numberOfChannels; ++i) {
+ sources[i] = sourceBusSafe.channel(i)->data();
+ destinations[i] = channel(i)->mutableData();
}
-#define STEREO_NO_SUM_V \
- { \
- vsmul(sourceL, 1, &gain, destinationL, 1, framesToProcess - k); \
- vsmul(sourceR, 1, &gain, destinationR, 1, framesToProcess - k); \
- }
-
-// Mono -> stereo (mix equally into L and R)
-// FIXME: Really we should apply an equal-power scaling factor here, since we're effectively panning center...
-#define MONO2STEREO_NO_SUM \
- { \
- float sample = *sourceL++; \
- *destinationL++ = DenormalDisabler::flushDenormalFloatToZero(gain * sample); \
- *destinationR++ = DenormalDisabler::flushDenormalFloatToZero(gain * sample); \
- }
-
-#define MONO2STEREO_NO_SUM_V \
- { \
- vsmul(sourceL, 1, &gain, destinationL, 1, framesToProcess - k); \
- vsmul(sourceL, 1, &gain, destinationR, 1, framesToProcess - k); \
- }
-
-#define MONO_NO_SUM \
- { \
- float sampleL = *sourceL++; \
- *destinationL++ = DenormalDisabler::flushDenormalFloatToZero(gain * sampleL); \
- }
-
-#define MONO_NO_SUM_V \
- { \
- vsmul(sourceL, 1, &gain, destinationL, 1, framesToProcess - k); \
- }
-
-void AudioBus::processWithGainFromMonoStereo(const AudioBus &sourceBus, float* lastMixGain, float targetGain, bool sumToBus)
-{
// We don't want to suddenly change the gain from mixing one time slice to the next,
// so we "de-zipper" by slowly changing the gain each sample-frame until we've achieved the target gain.
@@ -417,24 +354,8 @@
float gain = static_cast<float>(m_isFirstTime ? totalDesiredGain : *lastMixGain);
m_isFirstTime = false;
- int numberOfSourceChannels = sourceBus.numberOfChannels();
- int numberOfDestinationChannels = numberOfChannels();
-
- AudioBus& sourceBusSafe = const_cast<AudioBus&>(sourceBus);
- const float* sourceL = sourceBusSafe.channelByType(ChannelLeft)->data();
- const float* sourceR = numberOfSourceChannels > 1 ? sourceBusSafe.channelByType(ChannelRight)->data() : 0;
-
- if (sourceBusSafe.isSilent()) {
- if (!sumToBus)
- zero();
- return;
- }
-
- float* destinationL = channelByType(ChannelLeft)->mutableData();
- float* destinationR = numberOfDestinationChannels > 1 ? channelByType(ChannelRight)->mutableData() : 0;
-
const float DezipperRate = 0.005f;
- int framesToProcess = length();
+ unsigned framesToProcess = length();
// If the gain is within epsilon of totalDesiredGain, we can skip dezippering.
// FIXME: this value may need tweaking.
@@ -442,66 +363,41 @@
float gainDiff = fabs(totalDesiredGain - gain);
// Number of frames to de-zipper before we are close enough to the target gain.
- int framesToDezipper = (gainDiff < epsilon) ? 0 : framesToProcess;
+ // FIXME: framesToDezipper could be smaller when target gain is close enough within this process loop.
+ unsigned framesToDezipper = (gainDiff < epsilon) ? 0 : framesToProcess;
- int k = 0;
+ if (framesToDezipper) {
+ if (!m_dezipperGainValues.get() || m_dezipperGainValues->size() < framesToDezipper)
+ m_dezipperGainValues = adoptPtr(new AudioFloatArray(framesToDezipper));
- if (sumToBus) {
- // Sum to our bus
- if (sourceR && destinationR) {
- // Stereo
- PROCESS_WITH_GAIN(STEREO_SUM)
- } else if (destinationR) {
- // Mono -> stereo
- PROCESS_WITH_GAIN(MONO2STEREO_SUM)
- } else {
- // Mono
- PROCESS_WITH_GAIN(MONO_SUM)
+ float* gainValues = m_dezipperGainValues->data();
+ for (unsigned i = 0; i < framesToDezipper; ++i) {
+ gain += (totalDesiredGain - gain) * DezipperRate;
+
+ // FIXME: If we are clever enough in calculating the framesToDezipper value, we can probably get
+ // rid of this DenormalDisabler::flushDenormalFloatToZero() call.
+ gain = DenormalDisabler::flushDenormalFloatToZero(gain);
+ *gainValues++ = gain;
}
- } else {
- // Process directly (without summing) to our bus
- if (sourceR && destinationR) {
- // Stereo
- PROCESS_WITH_GAIN(STEREO_NO_SUM)
- } else if (destinationR) {
- // Mono -> stereo
- PROCESS_WITH_GAIN(MONO2STEREO_NO_SUM)
- } else {
- // Mono
- PROCESS_WITH_GAIN(MONO_NO_SUM)
+
+ for (unsigned channelIndex = 0; channelIndex < numberOfChannels; ++channelIndex) {
+ vmul(sources[channelIndex], 1, m_dezipperGainValues->data(), 1, destinations[channelIndex], 1, framesToDezipper);
+ sources[channelIndex] += framesToDezipper;
+ destinations[channelIndex] += framesToDezipper;
}
+ } else
+ gain = totalDesiredGain;
+
+ // Apply constant gain after de-zippering has converged on target gain.
+ if (framesToDezipper < framesToProcess) {
+ for (unsigned channelIndex = 0; channelIndex < numberOfChannels; ++channelIndex)
+ vsmul(sources[channelIndex], 1, &gain, destinations[channelIndex], 1, framesToProcess - framesToDezipper);
}
// Save the target gain as the starting point for next time around.
*lastMixGain = gain;
}
-void AudioBus::processWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain, bool sumToBus)
-{
- // Make sure we're summing from same type of bus.
- // We *are* able to sum from mono -> stereo
- if (sourceBus.numberOfChannels() != 1 && !topologyMatches(sourceBus)) {
- ASSERT_NOT_REACHED();
- return;
- }
- // If it is copying from the same bus and no need to change gain, just return
- if (!sumToBus && this == &sourceBus && *lastMixGain == targetGain && targetGain == 1.0)
- return;
-
- // Dispatch for different channel layouts
- switch (numberOfChannels()) {
- case 1: // mono
- case 2: // stereo
- processWithGainFromMonoStereo(sourceBus, lastMixGain, targetGain, sumToBus);
- break;
- case 4: // FIXME: implement quad
- case 5: // FIXME: implement 5.0
- default:
- ASSERT_NOT_REACHED();
- break;
- }
-}
-
void AudioBus::copyWithSampleAccurateGainValuesFrom(const AudioBus &sourceBus, float* gainValues, unsigned numberOfGainValues)
{
// Make sure we're processing from the same type of bus.
@@ -531,16 +427,6 @@
}
}
-void AudioBus::copyWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain)
-{
- processWithGainFrom(sourceBus, lastMixGain, targetGain, false);
-}
-
-void AudioBus::sumWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain)
-{
- processWithGainFrom(sourceBus, lastMixGain, targetGain, true);
-}
-
PassOwnPtr<AudioBus> AudioBus::createBySampleRateConverting(const AudioBus* sourceBus, bool mixToMono, double newSampleRate)
{
// sourceBus's sample-rate must be known.
Modified: trunk/Source/WebCore/platform/audio/AudioBus.h (116595 => 116596)
--- trunk/Source/WebCore/platform/audio/AudioBus.h 2012-05-10 02:00:38 UTC (rev 116595)
+++ trunk/Source/WebCore/platform/audio/AudioBus.h 2012-05-10 02:32:46 UTC (rev 116596)
@@ -109,10 +109,6 @@
// Scales all samples by the same amount.
void scale(float scale);
- // Master gain for this bus - used with sumWithGainFrom() below
- void setGain(float gain) { m_busGain = gain; }
- float gain() const { return m_busGain; }
-
void reset() { m_isFirstTime = true; } // for de-zippering
// Assuming sourceBus has the same topology, copies sample data from each channel of sourceBus to our corresponding channel.
@@ -122,12 +118,11 @@
// Our own internal gain m_busGain is ignored.
void sumFrom(const AudioBus &sourceBus);
- // Copy or sum each channel from sourceBus into our corresponding channel.
+ // Copy each channel from sourceBus into our corresponding channel.
// We scale by targetGain (and our own internal gain m_busGain), performing "de-zippering" to smoothly change from *lastMixGain to (targetGain*m_busGain).
- // The caller is responsible for setting up lastMixGain to point to storage which is unique for every "stream" which will be summed to this bus.
+ // The caller is responsible for setting up lastMixGain to point to storage which is unique for every "stream" which will be applied to this bus.
// This represents the dezippering memory.
void copyWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain);
- void sumWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain);
// Copies the sourceBus by scaling with sample-accurate gain values.
void copyWithSampleAccurateGainValuesFrom(const AudioBus &sourceBus, float* gainValues, unsigned numberOfGainValues);
@@ -143,16 +138,11 @@
protected:
AudioBus() { };
- void processWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain, bool sumToBus);
- void processWithGainFromMonoStereo(const AudioBus &sourceBus, float* lastMixGain, float targetGain, bool sumToBus);
-
size_t m_length;
-
Vector<OwnPtr<AudioChannel> > m_channels;
-
int m_layout;
-
float m_busGain;
+ OwnPtr<AudioFloatArray> m_dezipperGainValues;
bool m_isFirstTime;
float m_sampleRate; // 0.0 if unknown or N/A
};