// PCMVolumeMaximizer.cpp: implementation of the PCMVolumeMaximizer class. // ////////////////////////////////////////////////////////////////////// #include #include "PCMVolumeMaximizer.h" #include "AudioSample.h" #include "Exception.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// PCMVolumeMaximizer::PCMVolumeMaximizer() : averageVolumeCalculator(&tracer) { char subFacilityName[100]; sprintf(subFacilityName, "PCMVolumeMaximizer:%x", this); tracer.SetSubFacilityName(subFacilityName); SetTraceLevel(); maximizePercentile = 100.0; maximumAmplification = 100; averageVolumeCalculator.SetCalculationInterval(100); } PCMVolumeMaximizer::~PCMVolumeMaximizer() { } int PCMVolumeMaximizer::TransformStarted() { averageVolumeCalculator.Reset(); return 0; } int PCMVolumeMaximizer::SetTraceLevel() { long SystemMask = 0; if ((SystemMask = GetRegKeyLong(HKEY_CURRENT_USER, "Software\\Cisco Systems\\MTC\\Tracing", "AllComponents", 0x0)) == 0) { SystemMask = GetRegKeyLong(HKEY_CURRENT_USER, "Software\\Cisco Systems\\MTC\\Tracing", "PCMVolumeMaximizer", 0x100000); } tracer.SetSystemMask(SystemMask); return 0; } int PCMVolumeMaximizer::SetMaximizePercentile(double percentile) { if (percentile < 0.0) { percentile = 0.0; } if (percentile > 100.0) { percentile = 100.0; } maximizePercentile = percentile; return 0; } int PCMVolumeMaximizer::SetMaximumAmplification(unsigned int amplification) { if (amplification < 100) { amplification = 100; } maximumAmplification = amplification; return 0; } int PCMVolumeMaximizer::TransformAudioSamples(std::vector > &data, AudioSample **ppAudioSample) { int result = 0; AudioSample *inSample = NULL; if (data.size() > 0) { inSample = data[0].first; } try { if (!inSample) { throw Exception(-10, "inSample = NULL"); } if (inSample->DataSize() <= 0) { throw Exception(-20, "inSample->DataSize is %d\n", inSample->DataSize()); } if (maximumAmplification <= 100) { throw Exception(0, "maximumAmplification is %d\n", maximumAmplification); } WAVEFORMATEX wfx; inSample->GetFormat(&wfx); int bytesPerSample(0); int numSamples(0); int numBytes = inSample->DataSize(); double maxValue(0.0); switch(wfx.wBitsPerSample) { case 8: bytesPerSample = 1; maxValue = 127; break; case 16: bytesPerSample = 2; maxValue = 32767; break; case 32: bytesPerSample = 4; maxValue = pow(2.0, 31) - 1; break; default: throw Exception(-30, "sample audioformat wBitsPerSample = %d", wfx.wBitsPerSample); break; } numSamples = numBytes/bytesPerSample; // make a histogram of the volume values memset(bins, 0, sizeof(unsigned int) * NUM_BINS); char *dataPtr = (char *)(inSample->Data()); for (int i=0; i=0; i--) { total += bins[i]; double percentile = (double)(numSamples - total) / (double)numSamples * 100; if (percentile >= maximizePercentile) { continue; } numBinsToAmplify = i+1; break; } // find out maximum amplification possible double amplification = (double)NUM_BINS / (double)numBinsToAmplify; if (amplification > (maximumAmplification / 100.0)) { amplification = maximumAmplification / 100.0; } averageVolumeCalculator.TakeNextValue(amplification); tracer.tracef(DET, "TransformAudioSamples : amplifying by %.2f\n", amplification); // now amplify the sample for (i=0; i maxValue) { newValue = maxValue; } if (newValue < -maxValue) { newValue = -maxValue; } *((char *)(dataPtr + (bytesPerSample * i))) = newValue; break; case 2: sampleValue = (double)(*((short *)(dataPtr + (bytesPerSample * i)))); newValue = sampleValue * amplification; if (newValue > maxValue) { newValue = maxValue; } if (newValue < -maxValue) { newValue = -maxValue; } *((short *)(dataPtr + (bytesPerSample * i))) = newValue; break; case 4: sampleValue = (double)(*((long *)(dataPtr + (bytesPerSample * i)))); newValue = sampleValue * amplification; if (newValue > maxValue) { newValue = maxValue; } if (newValue < -maxValue) { newValue = -maxValue; } *((long *)(dataPtr + (bytesPerSample * i))) = newValue; break; } } } catch (Exception ex) { if (result < 0) { tracer.tracef(ERR, "TransformAudioSamples : error %d. %s\n", ex.ErrorCode(), ex.ErrorMessage()); } else { tracer.tracef(DET, "TransformAudioSamples : error %d. %s\n", ex.ErrorCode(), ex.ErrorMessage()); } result = ex.ErrorCode(); } if (result == 0) { *ppAudioSample = inSample; if (inSample) { inSample->AddRef(this); } } return result; }