![]() |
Mixxx
|
00001 /*************************************************************************** 00002 enginevumeter.cpp - description 00003 ------------------- 00004 copyright : (C) 2002 by Tue and Ken Haste Andersen 00005 email : 00006 ***************************************************************************/ 00007 00008 /*************************************************************************** 00009 * * 00010 * This program is free software; you can redistribute it and/or modify * 00011 * it under the terms of the GNU General Public License as published by * 00012 * the Free Software Foundation; either version 2 of the License, or * 00013 * (at your option) any later version. * 00014 * * 00015 ***************************************************************************/ 00016 00017 #ifdef __WINDOWS__ 00018 #pragma intrinsic(fabs) 00019 #endif 00020 00021 #include "engine/enginevumeter.h" 00022 #include "controlpotmeter.h" 00023 #include "sampleutil.h" 00024 00025 EngineVuMeter::EngineVuMeter(const char * group) { 00026 // The VUmeter widget is controlled via a controlpotmeter, which means 00027 // that it should react on the setValue(int) signal. 00028 m_ctrlVuMeter = new ControlPotmeter(ConfigKey(group, "VuMeter"), 0., 1.); 00029 m_ctrlVuMeter->set(0); 00030 // left channel VU meter 00031 m_ctrlVuMeterL = new ControlPotmeter(ConfigKey(group, "VuMeterL"), 0., 1.); 00032 m_ctrlVuMeterL->set(0); 00033 // right channel VU meter 00034 m_ctrlVuMeterR = new ControlPotmeter(ConfigKey(group, "VuMeterR"), 0., 1.); 00035 m_ctrlVuMeterR->set(0); 00036 00037 // Initialize the calculation: 00038 m_iSamplesCalculated = 0; 00039 m_fRMSvolumeL = 0; 00040 m_fRMSvolumeSumL = 0; 00041 m_fRMSvolumeR = 0; 00042 m_fRMSvolumeSumR = 0; 00043 } 00044 00045 EngineVuMeter::~EngineVuMeter() 00046 { 00047 delete m_ctrlVuMeter; 00048 delete m_ctrlVuMeterL; 00049 delete m_ctrlVuMeterR; 00050 } 00051 00052 void EngineVuMeter::process(const CSAMPLE * pIn, const CSAMPLE *, const int iBufferSize) 00053 { 00054 00055 CSAMPLE fVolSumL, fVolSumR; 00056 SampleUtil::sumAbsPerChannel(&fVolSumL, &fVolSumR, pIn, iBufferSize); 00057 m_fRMSvolumeSumL += fVolSumL; 00058 m_fRMSvolumeSumR += fVolSumR; 00059 00060 m_iSamplesCalculated += iBufferSize/2; 00061 00062 // Are we ready to update the VU meter?: 00063 if (m_iSamplesCalculated > (44100/2/UPDATE_RATE) ) 00064 { 00065 doSmooth(m_fRMSvolumeL, log10(m_fRMSvolumeSumL/(m_iSamplesCalculated*1000)+1)); 00066 doSmooth(m_fRMSvolumeR, log10(m_fRMSvolumeSumR/(m_iSamplesCalculated*1000)+1)); 00067 00068 const double epsilon = .0001; 00069 00070 // Since VU meters are a rolling sum of audio, the no-op checks in 00071 // ControlObject will not prevent us from causing tons of extra 00072 // work. Because of this, we use an epsilon here to be gentle on the GUI 00073 // and MIDI controllers. 00074 if (fabs(m_fRMSvolumeL - m_ctrlVuMeterL->get()) > epsilon) 00075 m_ctrlVuMeterL->set(m_fRMSvolumeL); 00076 if (fabs(m_fRMSvolumeR - m_ctrlVuMeterR->get()) > epsilon) 00077 m_ctrlVuMeterR->set(m_fRMSvolumeR); 00078 00079 double fRMSvolume = (m_fRMSvolumeL + m_fRMSvolumeR) / 2.0; 00080 if (fabs(fRMSvolume - m_ctrlVuMeter->get()) > epsilon) 00081 m_ctrlVuMeter->set(fRMSvolume); 00082 00083 // Reset calculation: 00084 m_iSamplesCalculated = 0; 00085 m_fRMSvolumeSumL = 0; 00086 m_fRMSvolumeSumR = 0; 00087 } 00088 } 00089 00090 00091 void EngineVuMeter::doSmooth(FLOAT_TYPE ¤tVolume, FLOAT_TYPE newVolume) 00092 { 00093 if (currentVolume > newVolume) 00094 currentVolume -= DECAY_SMOOTHING * (currentVolume - newVolume); 00095 else 00096 currentVolume += ATTACK_SMOOTHING * (newVolume - currentVolume); 00097 if (currentVolume < 0) 00098 currentVolume=0; 00099 if (currentVolume > 1.0) 00100 currentVolume=1.0; 00101 }