Mixxx

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

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