Mixxx

/home/maxime/Projets/Mixxx/1.10/mixxx/src/engine/enginepassthrough.cpp

Go to the documentation of this file.
00001 // enginepassthrough.cpp
00002 // created 4/8/2011 by Bill Good (bkgood@gmail.com)
00003 // shameless stolen from enginemicrophone.cpp (from RJ)
00004 
00005 #include <QtDebug>
00006 
00007 #include "engine/enginepassthrough.h"
00008 
00009 #include "configobject.h"
00010 #include "sampleutil.h"
00011 
00012 EnginePassthrough::EnginePassthrough(const char* pGroup)
00013         : EngineChannel(pGroup, EngineChannel::CENTER),
00014           m_clipping(pGroup),
00015           m_vuMeter(pGroup),
00016           m_pEnabled(new ControlObject(ConfigKey(pGroup, "passthrough_enabled"))),
00017           m_pPassing(new ControlPushButton(ConfigKey(pGroup, "passthrough_passing"))),
00018           m_pConversionBuffer(SampleUtil::alloc(MAX_BUFFER_LEN)),
00019           // Need a +1 here because the CircularBuffer only allows its size-1
00020           // items to be held at once (it keeps a blank spot open persistently)
00021           m_sampleBuffer(MAX_BUFFER_LEN+1) {
00022     m_pPassing->setToggleButton(true);
00023 }
00024 
00025 EnginePassthrough::~EnginePassthrough() {
00026     qDebug() << "~EnginePassthrough()";
00027     SampleUtil::free(m_pConversionBuffer);
00028     delete m_pEnabled;
00029     delete m_pPassing;
00030 }
00031 
00032 bool EnginePassthrough::isActive() {
00033     bool enabled = m_pEnabled->get() > 0.0;
00034     return enabled && !m_sampleBuffer.isEmpty();
00035 }
00036 
00037 bool EnginePassthrough::isPFL() {
00038     return true;
00039 }
00040 
00041 bool EnginePassthrough::isMaster() {
00042     return true;
00043 }
00044 
00045 void EnginePassthrough::onInputConnected(AudioInput input) {
00046     if (input.getType() != AudioPath::EXTPASSTHROUGH) {
00047         // This is an error!
00048         qDebug() << "WARNING: EnginePassthrough connected to AudioInput for a non-passthrough type!";
00049         return;
00050     }
00051     m_sampleBuffer.clear();
00052     m_pEnabled->set(1.0f);
00053 }
00054 
00055 void EnginePassthrough::onInputDisconnected(AudioInput input) {
00056     if (input.getType() != AudioPath::EXTPASSTHROUGH) {
00057         // This is an error!
00058         qDebug() << "WARNING: EnginePassthrough connected to AudioInput for a non-passthrough type!";
00059         return;
00060     }
00061     m_sampleBuffer.clear();
00062     m_pEnabled->set(0.0f);
00063 }
00064 
00065 void EnginePassthrough::receiveBuffer(AudioInput input, const short* pBuffer, unsigned int nFrames) {
00066 
00067     if (input.getType() != AudioPath::EXTPASSTHROUGH) {
00068         // This is an error!
00069         qDebug() << "WARNING: EnginePassthrough receieved an AudioInput for a non-passthrough type!";
00070         return;
00071     }
00072 
00073     // Use the conversion buffer to both convert from short and double into
00074     // stereo.
00075 
00076     // Check that the number of mono samples doesn't exceed MAX_BUFFER_LEN/2
00077     // because thats our conversion buffer size.
00078     if (nFrames > MAX_BUFFER_LEN / 2) {
00079         qDebug() << "WARNING: Dropping passthrough samples because the input buffer is too large.";
00080         nFrames = MAX_BUFFER_LEN / 2;
00081     }
00082 
00083     // There isn't a suitable SampleUtil method that can do mono->stereo and
00084     // short->float in one pass.
00085     // SampleUtil::convert(m_pConversionBuffer, pBuffer, iNumSamples);
00086     SampleUtil::convert(m_pConversionBuffer, pBuffer, nFrames*2);
00087 
00088     // TODO(rryan) (or bkgood?) do we need to verify the input is the one we asked for? Oh well.
00089     unsigned int samplesWritten = m_sampleBuffer.write(m_pConversionBuffer, nFrames*2);
00090     if (samplesWritten < nFrames*2) {
00091         // Buffer overflow. We aren't processing samples fast enough. This
00092         // shouldn't happen since the deck spits out samples just as fast as they
00093         // come in, right?
00094         Q_ASSERT(false);
00095     }
00096 }
00097 
00098 void EnginePassthrough::process(const CSAMPLE* pInput, const CSAMPLE* pOutput, const int iBufferSize) {
00099     CSAMPLE* pOut = const_cast<CSAMPLE*>(pOutput);
00100     Q_UNUSED(pInput);
00101 
00102     // If passthrough is enabled, then read into the output buffer. Otherwise,
00103     // skip the appropriate number of samples to throw them away.
00104     if (m_pPassing->get() > 0.0f) {
00105         int samplesRead = m_sampleBuffer.read(pOut, iBufferSize);
00106         if (samplesRead < iBufferSize) {
00107             // Buffer underflow. There aren't getting samples fast enough. This
00108             // shouldn't happen since PortAudio should feed us samples just as fast
00109             // as we consume them, right?
00110             Q_ASSERT(false);
00111         }
00112     } else {
00113         SampleUtil::applyGain(pOut, 0.0, iBufferSize);
00114         m_sampleBuffer.skip(iBufferSize);
00115     }
00116 
00117     // Apply clipping
00118     m_clipping.process(pOut, pOut, iBufferSize);
00119     // Update VU meter
00120     m_vuMeter.process(pOut, pOut, iBufferSize);
00121 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines