diff --git a/src/engine/enginemaster.cpp b/src/engine/enginemaster.cpp index 96bfe767083..f570df7c416 100644 --- a/src/engine/enginemaster.cpp +++ b/src/engine/enginemaster.cpp @@ -4,6 +4,7 @@ #include #include +#include "audio/types.h" #include "control/controlaudiotaperpot.h" #include "control/controlpotmeter.h" #include "control/controlpushbutton.h" @@ -1048,16 +1049,35 @@ void EngineMaster::onInputDisconnected(const AudioInput& input) { } void EngineMaster::registerNonEngineChannelSoundIO(SoundManager* pSoundManager) { - pSoundManager->registerInput(AudioInput(AudioPath::RECORD_BROADCAST, 0, 2), - m_pEngineSideChain); - - pSoundManager->registerOutput(AudioOutput(AudioOutput::MASTER, 0, 2), this); - pSoundManager->registerOutput(AudioOutput(AudioOutput::HEADPHONES, 0, 2), this); - pSoundManager->registerOutput(AudioOutput(AudioOutput::BOOTH, 0, 2), this); + pSoundManager->registerInput(AudioInput(AudioPath::RECORD_BROADCAST, + 0, + mixxx::audio::ChannelCount::stereo()), + m_pEngineSideChain); + + pSoundManager->registerOutput(AudioOutput(AudioOutput::MASTER, + 0, + mixxx::audio::ChannelCount::stereo()), + this); + pSoundManager->registerOutput(AudioOutput(AudioOutput::HEADPHONES, + 0, + mixxx::audio::ChannelCount::stereo()), + this); + pSoundManager->registerOutput(AudioOutput(AudioOutput::BOOTH, + 0, + mixxx::audio::ChannelCount::stereo()), + this); for (int o = EngineChannel::LEFT; o <= EngineChannel::RIGHT; o++) { - pSoundManager->registerOutput(AudioOutput(AudioOutput::BUS, 0, 2, o), this); + pSoundManager->registerOutput( + AudioOutput(AudioOutput::BUS, + 0, + mixxx::audio::ChannelCount::stereo(), + o), + this); } - pSoundManager->registerOutput(AudioOutput(AudioOutput::RECORD_BROADCAST, 0, 2), this); + pSoundManager->registerOutput(AudioOutput(AudioOutput::RECORD_BROADCAST, + 0, + mixxx::audio::ChannelCount::stereo()), + this); } bool EngineMaster::sidechainMixRequired() const { diff --git a/src/engine/filters/enginefilterpan.h b/src/engine/filters/enginefilterpan.h index 51ad19c03d4..9f2986faaa6 100644 --- a/src/engine/filters/enginefilterpan.h +++ b/src/engine/filters/enginefilterpan.h @@ -2,11 +2,10 @@ #include +#include "engine/engine.h" #include "engine/engineobject.h" #include "util/assert.h" -static constexpr int numChannels = 2; - template class EngineFilterPan : public EngineObjectConstIn { public: @@ -123,7 +122,7 @@ class EngineFilterPan : public EngineObjectConstIn { int m_leftDelayFrames; int m_oldLeftDelayFrames; int m_delayFrame; - CSAMPLE m_buf[SIZE * numChannels]; + CSAMPLE m_buf[SIZE * mixxx::kEngineChannelCount]; bool m_doRamping; bool m_doStart; }; diff --git a/src/engine/filters/enginefilterpansingle.h b/src/engine/filters/enginefilterpansingle.h index 1861b97db8e..cbe292ff667 100644 --- a/src/engine/filters/enginefilterpansingle.h +++ b/src/engine/filters/enginefilterpansingle.h @@ -9,11 +9,10 @@ #include +#include "engine/engine.h" #include "engine/engineobject.h" #include "util/assert.h" -static constexpr int numChannels = 2; - template class EngineFilterPanSingle { public: @@ -78,6 +77,6 @@ class EngineFilterPanSingle { protected: int m_delayFrame; - CSAMPLE m_buf[SIZE * numChannels]; + CSAMPLE m_buf[SIZE * mixxx::kEngineChannelCount]; bool m_doStart; }; diff --git a/src/engine/sidechain/enginenetworkstream.h b/src/engine/sidechain/enginenetworkstream.h index f055a083717..902e51117ab 100644 --- a/src/engine/sidechain/enginenetworkstream.h +++ b/src/engine/sidechain/enginenetworkstream.h @@ -23,11 +23,11 @@ class EngineNetworkStream { qint64 getInputStreamTimeUs(); qint64 getInputStreamTimeFrames(); - int getNumOutputChannels() { + mixxx::audio::ChannelCount getNumOutputChannels() { return m_numOutputChannels; } - int getNumInputChannels() { + mixxx::audio::ChannelCount getNumInputChannels() { return m_numInputChannels; } @@ -46,8 +46,8 @@ class EngineNetworkStream { void debugOutputSlots(); FIFO* m_pInputFifo; - int m_numOutputChannels; - int m_numInputChannels; + mixxx::audio::ChannelCount m_numOutputChannels; + mixxx::audio::ChannelCount m_numInputChannels; mixxx::audio::SampleRate m_sampleRate; qint64 m_inputStreamStartTimeUs; qint64 m_inputStreamFramesWritten; diff --git a/src/engine/sidechain/enginesidechain.cpp b/src/engine/sidechain/enginesidechain.cpp index f6e6803db75..050e0b17317 100644 --- a/src/engine/sidechain/enginesidechain.cpp +++ b/src/engine/sidechain/enginesidechain.cpp @@ -78,11 +78,10 @@ void EngineSideChain::receiveBuffer(const AudioInput& input, void EngineSideChain::writeSamples(const CSAMPLE* pBuffer, int iFrames) { Trace sidechain("EngineSideChain::writeSamples"); // TODO: remove assumption of stereo buffer - constexpr int kChannels = 2; - const int iSamples = iFrames * kChannels; - int samples_written = m_sampleFifo.write(pBuffer, iSamples); + const int numSamples = iFrames * mixxx::kEngineChannelCount; + const int numSamplesWritten = m_sampleFifo.write(pBuffer, numSamples); - if (samples_written != iSamples) { + if (numSamplesWritten != numSamples) { Counter("EngineSideChain::writeSamples buffer overrun").increment(); } diff --git a/src/engine/sidechain/networkoutputstreamworker.cpp b/src/engine/sidechain/networkoutputstreamworker.cpp index 514fe84a5c6..fea7888b0a8 100644 --- a/src/engine/sidechain/networkoutputstreamworker.cpp +++ b/src/engine/sidechain/networkoutputstreamworker.cpp @@ -9,8 +9,7 @@ const mixxx::Logger kLogger("NetworkStreamWorker"); } // namespace NetworkOutputStreamWorker::NetworkOutputStreamWorker() - : m_numOutputChannels(0), - m_workerState(NETWORKSTREAMWORKER_STATE_NEW), + : m_workerState(NETWORKSTREAMWORKER_STATE_NEW), m_functionCode(0), m_runCount(0), m_streamStartTimeUs(-1), @@ -31,7 +30,7 @@ QSharedPointer> NetworkOutputStreamWorker::getOutputFifo() { } void NetworkOutputStreamWorker::startStream( - mixxx::audio::SampleRate sampleRate, int numOutputChannels) { + mixxx::audio::SampleRate sampleRate, mixxx::audio::ChannelCount numOutputChannels) { m_sampleRate = sampleRate; m_numOutputChannels = numOutputChannels; @@ -41,7 +40,7 @@ void NetworkOutputStreamWorker::startStream( void NetworkOutputStreamWorker::stopStream() { m_sampleRate = mixxx::audio::SampleRate(); - m_numOutputChannels = 0; + m_numOutputChannels = mixxx::audio::ChannelCount(); m_streamStartTimeUs = -1; } diff --git a/src/engine/sidechain/networkoutputstreamworker.h b/src/engine/sidechain/networkoutputstreamworker.h index a60e4e0f0bb..01e83de0763 100644 --- a/src/engine/sidechain/networkoutputstreamworker.h +++ b/src/engine/sidechain/networkoutputstreamworker.h @@ -53,7 +53,8 @@ class NetworkOutputStreamWorker { virtual void setOutputFifo(QSharedPointer> pOutputFifo); virtual QSharedPointer> getOutputFifo(); - void startStream(mixxx::audio::SampleRate sampleRate, int numOutputChannels); + void startStream(mixxx::audio::SampleRate sampleRate, + mixxx::audio::ChannelCount numOutputChannels); void stopStream(); virtual bool threadWaiting(); @@ -85,7 +86,7 @@ class NetworkOutputStreamWorker { private: mixxx::audio::SampleRate m_sampleRate; - int m_numOutputChannels; + mixxx::audio::ChannelCount m_numOutputChannels; int m_workerState; int m_functionCode; diff --git a/src/mixer/auxiliary.cpp b/src/mixer/auxiliary.cpp index 583c15a1ace..a914bb7628e 100644 --- a/src/mixer/auxiliary.cpp +++ b/src/mixer/auxiliary.cpp @@ -1,5 +1,6 @@ #include "mixer/auxiliary.h" +#include "audio/types.h" #include "control/controlproxy.h" #include "engine/channels/engineaux.h" #include "engine/enginemaster.h" @@ -17,7 +18,10 @@ Auxiliary::Auxiliary(PlayerManager* pParent, ChannelHandleAndGroup channelGroup = pEngine->registerChannelGroup(group); EngineAux* pAuxiliary = new EngineAux(channelGroup, pEffectsManager); pEngine->addChannel(pAuxiliary); - AudioInput auxInput = AudioInput(AudioPath::AUXILIARY, 0, 2, index); + AudioInput auxInput = AudioInput(AudioPath::AUXILIARY, + 0, + mixxx::audio::ChannelCount::stereo(), + index); pSoundManager->registerInput(auxInput, pAuxiliary); m_pInputConfigured = make_parented(group, "input_configured", this); diff --git a/src/mixer/microphone.cpp b/src/mixer/microphone.cpp index d5a67142872..d049443333e 100644 --- a/src/mixer/microphone.cpp +++ b/src/mixer/microphone.cpp @@ -1,5 +1,6 @@ #include "mixer/microphone.h" +#include "audio/types.h" #include "control/controlproxy.h" #include "engine/channels/enginemicrophone.h" #include "engine/enginemaster.h" @@ -18,7 +19,10 @@ Microphone::Microphone(PlayerManager* pParent, EngineMicrophone* pMicrophone = new EngineMicrophone(channelGroup, pEffectsManager); pEngine->addChannel(pMicrophone); - AudioInput micInput = AudioInput(AudioPath::MICROPHONE, 0, 2, index); + AudioInput micInput = AudioInput(AudioPath::MICROPHONE, + 0, + mixxx::audio::ChannelCount::stereo(), + index); pSoundManager->registerInput(micInput, pMicrophone); m_pInputConfigured = make_parented(group, "input_configured", this); diff --git a/src/mixer/playermanager.cpp b/src/mixer/playermanager.cpp index 53e6a5b82d7..8179be64c08 100644 --- a/src/mixer/playermanager.cpp +++ b/src/mixer/playermanager.cpp @@ -2,6 +2,7 @@ #include +#include "audio/types.h" #include "control/controlobject.h" #include "effects/effectsmanager.h" #include "engine/channels/enginedeck.h" @@ -428,12 +429,19 @@ void PlayerManager::addDeckInner() { // Register the deck output with SoundManager. m_pSoundManager->registerOutput( - AudioOutput(AudioOutput::DECK, 0, 2, deckIndex), m_pEngine); + AudioOutput(AudioOutput::DECK, + 0, + mixxx::audio::ChannelCount::stereo(), + deckIndex), + m_pEngine); // Register vinyl input signal with deck for passthrough support. EngineDeck* pEngineDeck = pDeck->getEngineDeck(); - m_pSoundManager->registerInput( - AudioInput(AudioInput::VINYLCONTROL, 0, 2, deckIndex), pEngineDeck); + m_pSoundManager->registerInput(AudioInput(AudioInput::VINYLCONTROL, + 0, + mixxx::audio::ChannelCount::stereo(), + deckIndex), + pEngineDeck); // Setup equalizer and QuickEffect chain for this deck. m_pEffectsManager->addDeck(handleGroup); diff --git a/src/preferences/dialog/dlgprefsounditem.cpp b/src/preferences/dialog/dlgprefsounditem.cpp index 940d1ecf97c..1f7e323a8ae 100644 --- a/src/preferences/dialog/dlgprefsounditem.cpp +++ b/src/preferences/dialog/dlgprefsounditem.cpp @@ -79,7 +79,7 @@ void DlgPrefSoundItem::refreshDevices(const QList& devices) void DlgPrefSoundItem::deviceChanged(int index) { channelComboBox->clear(); SoundDeviceId selection = deviceComboBox->itemData(index).value(); - unsigned int numChannels = 0; + mixxx::audio::ChannelCount numChannels; if (selection == SoundDeviceId()) { goto emitAndReturn; } else { @@ -93,12 +93,12 @@ void DlgPrefSoundItem::deviceChanged(int index) { } } } - if (numChannels == 0) { + if (!numChannels.isValid()) { goto emitAndReturn; } else { - unsigned char minChannelsForType = + mixxx::audio::ChannelCount minChannelsForType = AudioPath::minChannelsForType(m_type); - unsigned char maxChannelsForType = + mixxx::audio::ChannelCount maxChannelsForType = AudioPath::maxChannelsForType(m_type); // Count down from the max so that stereo channels are first. @@ -185,8 +185,7 @@ void DlgPrefSoundItem::writePath(SoundManagerConfig* config) const { QPoint channelData = channelComboBox->itemData( channelComboBox->currentIndex()).toPoint(); int channelBase = channelData.x(); - int channelCount = channelData.y(); - + const auto channelCount = mixxx::audio::ChannelCount(channelData.y()); if (m_isInput) { config->addInput( @@ -282,7 +281,7 @@ void DlgPrefSoundItem::setChannel(unsigned int channelBase, * Checks that a given device can act as a source/input for our type. */ int DlgPrefSoundItem::hasSufficientChannels(const SoundDevice& device) const { - unsigned char needed(AudioPath::minChannelsForType(m_type)); + const auto needed = AudioPath::minChannelsForType(m_type); if (m_isInput) { return device.getNumInputChannels() >= needed; diff --git a/src/soundio/sounddevice.cpp b/src/soundio/sounddevice.cpp index 5688d393746..0fe875af4a7 100644 --- a/src/soundio/sounddevice.cpp +++ b/src/soundio/sounddevice.cpp @@ -15,19 +15,19 @@ SoundDevice::SoundDevice(UserSettingsPointer config, SoundManager* sm) : m_pConfig(config), m_pSoundManager(sm), m_strDisplayName("Unknown Soundcard"), - m_iNumOutputChannels(2), - m_iNumInputChannels(2), + m_numOutputChannels(mixxx::audio::ChannelCount::stereo()), + m_numInputChannels(mixxx::audio::ChannelCount::stereo()), m_sampleRate(SoundManagerConfig::kMixxxDefaultSampleRate), m_hostAPI("Unknown API"), m_configFramesPerBuffer(0) { } -int SoundDevice::getNumInputChannels() const { - return m_iNumInputChannels; +mixxx::audio::ChannelCount SoundDevice::getNumInputChannels() const { + return m_numInputChannels; } -int SoundDevice::getNumOutputChannels() const { - return m_iNumOutputChannels; +mixxx::audio::ChannelCount SoundDevice::getNumOutputChannels() const { + return m_numOutputChannels; } void SoundDevice::setSampleRate(mixxx::audio::SampleRate sampleRate) { diff --git a/src/soundio/sounddevice.h b/src/soundio/sounddevice.h index 69f96858711..736c4f4dfa3 100644 --- a/src/soundio/sounddevice.h +++ b/src/soundio/sounddevice.h @@ -41,8 +41,8 @@ class SoundDevice { virtual void writeProcess(SINT framesPerBuffer) = 0; virtual QString getError() const = 0; virtual mixxx::audio::SampleRate getDefaultSampleRate() const = 0; - int getNumOutputChannels() const; - int getNumInputChannels() const; + mixxx::audio::ChannelCount getNumOutputChannels() const; + mixxx::audio::ChannelCount getNumInputChannels() const; SoundDeviceStatus addOutput(const AudioOutputBuffer& out); SoundDeviceStatus addInput(const AudioInputBuffer& in); const QList& inputs() const { @@ -78,9 +78,9 @@ class SoundDevice { // The name of the soundcard, as displayed to the user QString m_strDisplayName; // The number of output channels that the soundcard has - int m_iNumOutputChannels; + mixxx::audio::ChannelCount m_numOutputChannels; // The number of input channels that the soundcard has - int m_iNumInputChannels; + mixxx::audio::ChannelCount m_numInputChannels; // The current samplerate for the sound device. mixxx::audio::SampleRate m_sampleRate; // The name of the audio API used by this device. diff --git a/src/soundio/sounddevicenetwork.cpp b/src/soundio/sounddevicenetwork.cpp index 7f0988acf2c..13b5413b3b5 100644 --- a/src/soundio/sounddevicenetwork.cpp +++ b/src/soundio/sounddevicenetwork.cpp @@ -46,8 +46,8 @@ SoundDeviceNetwork::SoundDeviceNetwork( m_sampleRate = SoundManagerConfig::kMixxxDefaultSampleRate; m_deviceId.name = kNetworkDeviceInternalName; m_strDisplayName = QObject::tr("Network stream"); - m_iNumInputChannels = pNetworkStream->getNumInputChannels(); - m_iNumOutputChannels = pNetworkStream->getNumOutputChannels(); + m_numInputChannels = pNetworkStream->getNumInputChannels(); + m_numOutputChannels = pNetworkStream->getNumOutputChannels(); } SoundDeviceNetwork::~SoundDeviceNetwork() { @@ -69,13 +69,13 @@ SoundDeviceStatus SoundDeviceNetwork::open(bool isClkRefDevice, int syncBuffers) // Feed the network device buffer directly from the // clock reference device callback // This is what should work best. - if (m_iNumOutputChannels) { + if (m_numOutputChannels) { m_outputFifo = std::make_unique>( - m_iNumOutputChannels * framesPerBuffer * 2); + m_numOutputChannels * framesPerBuffer * 2); } - if (m_iNumInputChannels) { + if (m_numInputChannels) { m_inputFifo = std::make_unique>( - m_iNumInputChannels * framesPerBuffer * 2); + m_numInputChannels * framesPerBuffer * 2); } m_pNetworkStream->startStream(m_sampleRate); @@ -134,14 +134,13 @@ QString SoundDeviceNetwork::getError() const { } void SoundDeviceNetwork::readProcess(SINT framesPerBuffer) { - if (!m_inputFifo || !m_pNetworkStream || !m_iNumInputChannels) { + if (!m_inputFifo || !m_pNetworkStream || !m_numInputChannels.isValid()) { return; } DEBUG_ASSERT(m_configFramesPerBuffer >= framesPerBuffer); - int inChunkSize = framesPerBuffer * m_iNumInputChannels; - int readAvailable = m_pNetworkStream->getReadExpected() - * m_iNumInputChannels; + int inChunkSize = framesPerBuffer * m_numInputChannels; + int readAvailable = m_pNetworkStream->getReadExpected() * m_numInputChannels; int writeAvailable = m_inputFifo->writeAvailable(); int copyCount = qMin(writeAvailable, readAvailable); if (copyCount > 0) { @@ -153,12 +152,12 @@ void SoundDeviceNetwork::readProcess(SINT framesPerBuffer) { &dataPtr1, &size1, &dataPtr2, &size2); // Fetch fresh samples and write to the the input buffer m_pNetworkStream->read(dataPtr1, - size1 / m_iNumInputChannels); - CSAMPLE* lastFrame = &dataPtr1[size1 - m_iNumInputChannels]; + size1 / m_numInputChannels); + CSAMPLE* lastFrame = &dataPtr1[size1 - m_numInputChannels]; if (size2 > 0) { m_pNetworkStream->read(dataPtr2, - size2 / m_iNumInputChannels); - lastFrame = &dataPtr2[size2 - m_iNumInputChannels]; + size2 / m_numInputChannels); + lastFrame = &dataPtr2[size2 - m_numInputChannels]; } m_inputFifo->releaseWriteRegions(copyCount); @@ -178,9 +177,8 @@ void SoundDeviceNetwork::readProcess(SINT framesPerBuffer) { // duplicate one frame //kLogger.debug() << "readProcess() duplicate one frame" // << (float)writeAvailable / inChunkSize << (float)readAvailable / inChunkSize; - (void) m_inputFifo->aquireWriteRegions( - m_iNumInputChannels, &dataPtr1, &size1, - &dataPtr2, &size2); + (void)m_inputFifo->aquireWriteRegions( + m_numInputChannels, &dataPtr1, &size1, &dataPtr2, &size2); if (size1) { SampleUtil::copy(dataPtr1, lastFrame, size1); m_inputFifo->releaseWriteRegions(size1); @@ -210,13 +208,14 @@ void SoundDeviceNetwork::readProcess(SINT framesPerBuffer) { &dataPtr2, &size2); // Fetch fresh samples and write to the the output buffer composeInputBuffer(dataPtr1, - size1 / m_iNumInputChannels, 0, - m_iNumInputChannels); + size1 / m_numInputChannels, + 0, + m_numInputChannels); if (size2 > 0) { composeInputBuffer(dataPtr2, - size2 / m_iNumInputChannels, - size1 / m_iNumInputChannels, - m_iNumInputChannels); + size2 / m_numInputChannels, + size1 / m_numInputChannels, + m_numInputChannels); } m_inputFifo->releaseReadRegions(readCount); } @@ -229,12 +228,12 @@ void SoundDeviceNetwork::readProcess(SINT framesPerBuffer) { } void SoundDeviceNetwork::writeProcess(SINT framesPerBuffer) { - if (!m_outputFifo || !m_pNetworkStream || !m_iNumOutputChannels) { + if (!m_outputFifo || !m_pNetworkStream || !m_numOutputChannels) { return; } DEBUG_ASSERT(m_configFramesPerBuffer >= framesPerBuffer); - int outChunkSize = framesPerBuffer * m_iNumOutputChannels; + int outChunkSize = framesPerBuffer * m_numOutputChannels; int writeAvailable = m_outputFifo->writeAvailable(); int writeCount = outChunkSize; if (outChunkSize > writeAvailable) { @@ -252,12 +251,12 @@ void SoundDeviceNetwork::writeProcess(SINT framesPerBuffer) { (void)m_outputFifo->aquireWriteRegions(writeCount, &dataPtr1, &size1, &dataPtr2, &size2); // Fetch fresh samples and write to the the output buffer - composeOutputBuffer(dataPtr1, size1 / m_iNumOutputChannels, 0, m_iNumOutputChannels); + composeOutputBuffer(dataPtr1, size1 / m_numOutputChannels, 0, m_numOutputChannels); if (size2 > 0) { composeOutputBuffer(dataPtr2, - size2 / m_iNumOutputChannels, - size1 / m_iNumOutputChannels, - m_iNumOutputChannels); + size2 / m_numOutputChannels, + size1 / m_numOutputChannels, + m_numOutputChannels); } m_outputFifo->releaseWriteRegions(writeCount); } @@ -297,7 +296,7 @@ void SoundDeviceNetwork::workerWriteProcess(NetworkOutputStreamWorkerPtr pWorker int writeExpectedFrames = static_cast( pWorker->getStreamTimeFrames() - pWorker->framesWritten()); - int writeExpected = writeExpectedFrames * m_iNumOutputChannels; + int writeExpected = writeExpectedFrames * m_numOutputChannels; if (writeExpected <= 0) { // Overflow @@ -335,9 +334,9 @@ void SoundDeviceNetwork::workerWriteProcess(NetworkOutputStreamWorkerPtr pWorker // "skip one frame" // << (float)writeAvailable / outChunkSize // << (float)readAvailable / outChunkSize; - if (size1 >= m_iNumOutputChannels) { - dataPtr1 += m_iNumOutputChannels; - size1 -= m_iNumOutputChannels; + if (size1 >= m_numOutputChannels) { + dataPtr1 += m_numOutputChannels; + size1 -= m_numOutputChannels; } } else { pWorker->setOutputDrift(true); @@ -346,9 +345,9 @@ void SoundDeviceNetwork::workerWriteProcess(NetworkOutputStreamWorkerPtr pWorker pWorker->setOutputDrift(false); } - workerWrite(pWorker, dataPtr1, size1 / m_iNumOutputChannels); + workerWrite(pWorker, dataPtr1, size1 / m_numOutputChannels); if (size2 > 0) { - workerWrite(pWorker, dataPtr2, size2 / m_iNumOutputChannels); + workerWrite(pWorker, dataPtr2, size2 / m_numOutputChannels); } QSharedPointer> pFifo = pWorker->getOutputFifo(); @@ -356,8 +355,8 @@ void SoundDeviceNetwork::workerWriteProcess(NetworkOutputStreamWorkerPtr pWorker // interval = copyCount // Check for desired kNetworkLatencyFrames + 1/2 interval to // avoid big jitter due to interferences with sync code - if (pFifo->readAvailable() + copyCount / 2 - >= (m_iNumOutputChannels * kNetworkLatencyFrames)) { + if (pFifo->readAvailable() + copyCount / 2 >= + (m_numOutputChannels * kNetworkLatencyFrames)) { pWorker->outputAvailable(); } } @@ -374,7 +373,7 @@ void SoundDeviceNetwork::workerWrite(NetworkOutputStreamWorkerPtr pWorker, QSharedPointer> pFifo = pWorker->getOutputFifo(); if (pFifo) { int writeAvailable = pFifo->writeAvailable(); - int writeRequired = frames * m_iNumOutputChannels; + int writeRequired = frames * m_numOutputChannels; if (writeAvailable < writeRequired) { kLogger.warning() << "write: worker buffer full, losing samples"; pWorker->incOverflowCount(); @@ -387,7 +386,7 @@ void SoundDeviceNetwork::workerWrite(NetworkOutputStreamWorkerPtr pWorker, // This means in case of buffer full (where we loose some frames) // we do not get out of sync, and the syncing code tries to catch up the // stream by writing silence, once the buffer is free. - pWorker->addFramesWritten(copyCount / m_iNumOutputChannels); + pWorker->addFramesWritten(copyCount / m_numOutputChannels); } } } @@ -401,7 +400,7 @@ void SoundDeviceNetwork::workerWriteSilence(NetworkOutputStreamWorkerPtr pWorker QSharedPointer> pFifo = pWorker->getOutputFifo(); if (pFifo) { int writeAvailable = pFifo->writeAvailable(); - int writeRequired = frames * m_iNumOutputChannels; + int writeRequired = frames * m_numOutputChannels; if (writeAvailable < writeRequired) { kLogger.warning() << "writeSilence: worker buffer full, losing samples"; pWorker->incOverflowCount(); @@ -423,7 +422,7 @@ void SoundDeviceNetwork::workerWriteSilence(NetworkOutputStreamWorkerPtr pWorker pFifo->releaseWriteRegions(clearCount); // we advance the frame only by the samples we have actually cleared - pWorker->addFramesWritten(clearCount / m_iNumOutputChannels); + pWorker->addFramesWritten(clearCount / m_numOutputChannels); } } } diff --git a/src/soundio/sounddeviceportaudio.cpp b/src/soundio/sounddeviceportaudio.cpp index a9123257dcb..a1af79bd082 100644 --- a/src/soundio/sounddeviceportaudio.cpp +++ b/src/soundio/sounddeviceportaudio.cpp @@ -119,8 +119,8 @@ SoundDevicePortAudio::SoundDevicePortAudio(UserSettingsPointer config, } m_deviceId.portAudioIndex = devIndex; m_strDisplayName = QString::fromUtf8(deviceInfo->name); - m_iNumInputChannels = m_deviceInfo->maxInputChannels; - m_iNumOutputChannels = m_deviceInfo->maxOutputChannels; + m_numInputChannels = mixxx::audio::ChannelCount(m_deviceInfo->maxInputChannels); + m_numOutputChannels = mixxx::audio::ChannelCount(m_deviceInfo->maxOutputChannels); m_inputParams.device = 0; m_inputParams.channelCount = 0; @@ -662,7 +662,7 @@ void SoundDevicePortAudio::writeProcess(SINT framesPerBuffer) { if (m_outputDrift) { //qDebug() << "SoundDevicePortAudio::writeProcess() skip one frame" // << (float)writeAvailable / outChunkSize << (float)readAvailable / outChunkSize; - copyCount = qMin(readAvailable, copyCount + m_iNumOutputChannels); + copyCount = qMin(readAvailable, copyCount + m_numOutputChannels); } else { m_outputDrift = true; } diff --git a/src/soundio/soundmanager.cpp b/src/soundio/soundmanager.cpp index 3dbe471bd4d..f4ce7cb54ef 100644 --- a/src/soundio/soundmanager.cpp +++ b/src/soundio/soundmanager.cpp @@ -117,8 +117,8 @@ QList SoundManager::getDeviceList( // we want input devices, or don't have output channels when we want // output devices. If searching for both input and output devices, // make sure to include any devices that have >0 channels. - bool hasOutputs = pDevice->getNumOutputChannels() >= 0; - bool hasInputs = pDevice->getNumInputChannels() >= 0; + const bool hasOutputs = pDevice->getNumOutputChannels().isValid(); + const bool hasInputs = pDevice->getNumInputChannels().isValid(); if (pDevice->getHostAPI() != filterAPI || (bOutputDevices && !bInputDevices && !hasOutputs) || (bInputDevices && !bOutputDevices && !hasInputs) || @@ -393,7 +393,10 @@ SoundDeviceStatus SoundManager::setupDevices() { // Statically connect the Network Device to the Sidechain if (pDevice->getDeviceId().name == kNetworkDeviceInternalName) { - AudioOutput out(AudioPath::RECORD_BROADCAST, 0, 2, 0); + AudioOutput out(AudioPath::RECORD_BROADCAST, + 0, + mixxx::audio::ChannelCount::stereo(), + 0); outputs.append(out); if (m_config.getForceNetworkClock() && !jackApiUsed()) { pNewMasterClockRef = pDevice; diff --git a/src/soundio/soundmanagerconfig.cpp b/src/soundio/soundmanagerconfig.cpp index 93dbc20cf65..a691e064192 100644 --- a/src/soundio/soundmanagerconfig.cpp +++ b/src/soundio/soundmanagerconfig.cpp @@ -1,10 +1,11 @@ -#include - #include "soundio/soundmanagerconfig.h" -#include "soundio/soundmanagerutil.h" +#include + +#include "audio/types.h" #include "soundio/sounddevice.h" #include "soundio/soundmanager.h" +#include "soundio/soundmanagerutil.h" #include "util/cmdlineargs.h" #include "util/math.h" @@ -510,7 +511,10 @@ void SoundManagerConfig::loadDefaults(SoundManager* soundManager, unsigned int f if (pDevice->getNumOutputChannels() < 2) { continue; } - AudioOutput masterOut(AudioPath::MASTER, 0, 2, 0); + AudioOutput masterOut(AudioPath::MASTER, + 0, + mixxx::audio::ChannelCount::stereo(), + 0); addOutput(pDevice->getDeviceId(), masterOut); defaultSampleRate = pDevice->getDefaultSampleRate(); break; diff --git a/src/soundio/soundmanagerutil.cpp b/src/soundio/soundmanagerutil.cpp index c9ef04a04fc..ba37af10914 100644 --- a/src/soundio/soundmanagerutil.cpp +++ b/src/soundio/soundmanagerutil.cpp @@ -2,14 +2,15 @@ #include "engine/channels/enginechannel.h" +using mixxx::audio::ChannelCount; + /** * Constructs a ChannelGroup. * @param channelBase the first channel in the group. * @param channels the number of channels. */ -ChannelGroup::ChannelGroup(unsigned char channelBase, unsigned char channels) - : m_channelBase(channelBase) - , m_channels(channels) { +ChannelGroup::ChannelGroup(unsigned char channelBase, ChannelCount channels) + : m_channelBase(channelBase), m_channels(channels) { } /** @@ -22,7 +23,7 @@ unsigned char ChannelGroup::getChannelBase() const { /** * @return The number of channels in this ChannelGroup */ -unsigned char ChannelGroup::getChannelCount() const { +ChannelCount ChannelGroup::getChannelCount() const { return m_channels; } @@ -33,7 +34,7 @@ unsigned char ChannelGroup::getChannelCount() const { * false otherwise. */ bool ChannelGroup::clashesWith(const ChannelGroup &other) const { - if (m_channels == 0 || other.m_channels == 0) { + if (!m_channels.isValid() || !other.m_channels.isValid()) { return false; // can't clash if there are no channels in use } return (m_channelBase > other.m_channelBase @@ -50,10 +51,10 @@ bool ChannelGroup::clashesWith(const ChannelGroup &other) const { * @param channelBase the first channel on a sound device used by this AudioPath. * @param channels the number of channels used. */ -AudioPath::AudioPath(unsigned char channelBase, unsigned char channels) - : m_channelGroup(channelBase, channels), - m_type(INVALID), - m_index(0) { +AudioPath::AudioPath(unsigned char channelBase, mixxx::audio::ChannelCount channels) + : m_channelGroup(channelBase, channels), + m_type(INVALID), + m_index(0) { } /** @@ -232,29 +233,29 @@ AudioPathType AudioPath::getTypeFromInt(int typeInt) { } // static -unsigned char AudioPath::minChannelsForType(AudioPathType type) { +ChannelCount AudioPath::minChannelsForType(AudioPathType type) { switch (type) { case AudioPath::VINYLCONTROL: - return 2; + return ChannelCount::stereo(); default: - return 1; + return ChannelCount::mono(); } } // static -unsigned char AudioPath::maxChannelsForType(AudioPathType type) { +ChannelCount AudioPath::maxChannelsForType(AudioPathType type) { Q_UNUSED(type); - return 2; + return ChannelCount::stereo(); } /** * Constructs an AudioOutput. */ AudioOutput::AudioOutput(AudioPathType type, - unsigned char channelBase, - unsigned char channels, - unsigned char index) - : AudioPath(channelBase, channels) { + unsigned char channelBase, + ChannelCount channels, + unsigned char index) + : AudioPath(channelBase, channels) { // TODO(rryan): This is a virtual function call from a constructor. setType(type); if (isIndexed(type)) { @@ -273,7 +274,7 @@ QDomElement AudioOutput::toXML(QDomElement *element) const { element->setAttribute("type", AudioPath::getStringFromType(m_type)); element->setAttribute("index", m_index); element->setAttribute("channel", m_channelGroup.getChannelBase()); - element->setAttribute("channel_count", m_channelGroup.getChannelCount()); + element->setAttribute("channel_count", m_channelGroup.getChannelCount().value()); return *element; } @@ -285,13 +286,13 @@ AudioOutput AudioOutput::fromXML(const QDomElement &xml) { AudioPathType type(AudioPath::getTypeFromString(xml.attribute("type"))); unsigned int index(xml.attribute("index", "0").toUInt()); unsigned int channel(xml.attribute("channel", "0").toUInt()); - unsigned int channels(xml.attribute("channel_count", "0").toUInt()); + auto channels = ChannelCount::fromInt(xml.attribute("channel_count", "0").toInt()); // In Mixxx < 1.12.0 we didn't save channels to file since they directly // corresponded to the type. To migrate users over, use mono for all // microphones and stereo for everything else since previously microphone // inputs were the only mono AudioPath. - if (channels == 0) { - channels = 2; + if (!channels.isValid()) { + channels = ChannelCount::stereo(); } return AudioOutput(type, channel, channels, index); } @@ -328,9 +329,9 @@ void AudioOutput::setType(AudioPathType type) { * Constructs an AudioInput. */ AudioInput::AudioInput(AudioPathType type, - unsigned char channelBase, - unsigned char channels, - unsigned char index) + unsigned char channelBase, + ChannelCount channels, + unsigned char index) : AudioPath(channelBase, channels) { // TODO(rryan): This is a virtual function call from a constructor. setType(type); @@ -354,7 +355,7 @@ QDomElement AudioInput::toXML(QDomElement *element) const { element->setAttribute("type", AudioPath::getStringFromType(m_type)); element->setAttribute("index", m_index); element->setAttribute("channel", m_channelGroup.getChannelBase()); - element->setAttribute("channel_count", m_channelGroup.getChannelCount()); + element->setAttribute("channel_count", m_channelGroup.getChannelCount().value()); return *element; } @@ -366,13 +367,13 @@ AudioInput AudioInput::fromXML(const QDomElement &xml) { AudioPathType type(AudioPath::getTypeFromString(xml.attribute("type"))); unsigned int index(xml.attribute("index", "0").toUInt()); unsigned int channel(xml.attribute("channel", "0").toUInt()); - unsigned int channels(xml.attribute("channel_count", "0").toUInt()); + auto channels = ChannelCount::fromInt(xml.attribute("channel_count", "0").toInt()); // In Mixxx <1.12.0 we didn't save channels to file since they directly // corresponded to the type. To migrate users over, use mono for all // microphones and stereo for everything else since previously microphone // inputs were the only mono AudioPath. - if (channels == 0) { - channels = type == MICROPHONE ? 1 : 2; + if (!channels.isValid()) { + channels = type == MICROPHONE ? ChannelCount::mono() : ChannelCount::stereo(); } return AudioInput(type, channel, channels, index); } diff --git a/src/soundio/soundmanagerutil.h b/src/soundio/soundmanagerutil.h index 2b25616bfad..cb3b587ef7e 100644 --- a/src/soundio/soundmanagerutil.h +++ b/src/soundio/soundmanagerutil.h @@ -5,6 +5,7 @@ #include #include +#include "audio/types.h" #include "util/compatibility/qhash.h" #include "util/fifo.h" #include "util/types.h" @@ -12,13 +13,13 @@ /// Describes a group of channels, typically a pair for stereo sound in Mixxx. class ChannelGroup { public: - ChannelGroup(unsigned char channelBase, unsigned char channels); + ChannelGroup(unsigned char channelBase, mixxx::audio::ChannelCount channels); unsigned char getChannelBase() const; - unsigned char getChannelCount() const; + mixxx::audio::ChannelCount getChannelCount() const; bool clashesWith(const ChannelGroup& other) const; uint hashValue() const { - return (m_channels << 8) | + return (m_channels.value() << 8) | m_channelBase; } friend qhash_seed_t qHash( @@ -36,7 +37,7 @@ class ChannelGroup { private: unsigned char m_channelBase; // base (first) channel used on device - unsigned char m_channels; // number of channels used (s/b 2 in most cases) + mixxx::audio::ChannelCount m_channels; // number of channels used (s/b 2 in most cases) }; inline bool operator!=( @@ -68,7 +69,7 @@ class AudioPath { RECORD_BROADCAST, INVALID, // if this isn't last bad things will happen -bkgood }; - AudioPath(unsigned char channelBase, unsigned char channels); + AudioPath(unsigned char channelBase, mixxx::audio::ChannelCount channels); virtual ~AudioPath() = default; AudioPathType getType() const; ChannelGroup getChannelGroup() const; @@ -83,11 +84,11 @@ class AudioPath { /// Returns the minimum number of channels needed on a sound device for an /// AudioPathType. - static unsigned char minChannelsForType(AudioPathType type); + static mixxx::audio::ChannelCount minChannelsForType(AudioPathType type); // Returns the maximum number of channels needed on a sound device for an // AudioPathType. - static unsigned char maxChannelsForType(AudioPathType type); + static mixxx::audio::ChannelCount maxChannelsForType(AudioPathType type); uint hashValue() const { // Exclude m_channelGroup from hash value! @@ -139,9 +140,10 @@ constexpr bool operator==(const AudioPath& lhs, /// channels on an audio interface. class AudioOutput : public AudioPath { public: - AudioOutput(AudioPathType type, unsigned char channelBase, - unsigned char channels, - unsigned char index = 0); + AudioOutput(AudioPathType type, + unsigned char channelBase, + mixxx::audio::ChannelCount channels, + unsigned char index = 0); ~AudioOutput() override = default; QDomElement toXML(QDomElement *element) const; static AudioOutput fromXML(const QDomElement &xml); @@ -172,8 +174,10 @@ class AudioOutputBuffer : public AudioOutput { /// that is be processed in Mixxx. class AudioInput : public AudioPath { public: - AudioInput(AudioPathType type = INVALID, unsigned char channelBase = 0, - unsigned char channels = 0, unsigned char index = 0); + AudioInput(AudioPathType type = INVALID, + unsigned char channelBase = 0, + mixxx::audio::ChannelCount channels = mixxx::audio::ChannelCount(), + unsigned char index = 0); ~AudioInput() override; QDomElement toXML(QDomElement *element) const; static AudioInput fromXML(const QDomElement &xml); diff --git a/src/test/enginemicrophonetest.cpp b/src/test/enginemicrophonetest.cpp index ccdedefb31b..fad06b8d8b8 100644 --- a/src/test/enginemicrophonetest.cpp +++ b/src/test/enginemicrophonetest.cpp @@ -84,7 +84,8 @@ TEST_F(EngineMicrophoneTest, TestInputMatchesOutput) { FillBuffer(input, 0.1f, inputLength); ClearBuffer(output, outputLength); - AudioInput micInput = AudioInput(AudioPath::MICROPHONE, 0, 1, 0); + AudioInput micInput = AudioInput( + AudioPath::MICROPHONE, 0, mixxx::audio::ChannelCount::mono(), 0); m_pTalkover->set(1.0); m_pMicrophone->receiveBuffer(micInput, input, inputLength); @@ -96,7 +97,8 @@ TEST_F(EngineMicrophoneTest, TestInputMatchesOutput) { TEST_F(EngineMicrophoneTest, TestRepeatedInputMatchesOutput) { ClearBuffer(output, outputLength); - AudioInput micInput = AudioInput(AudioPath::MICROPHONE, 0, 1, 0); + AudioInput micInput = AudioInput( + AudioPath::MICROPHONE, 0, mixxx::audio::ChannelCount::mono(), 0); m_pTalkover->set(1.0); for (int i = 0; i < 10; i++) { diff --git a/src/util/sample.cpp b/src/util/sample.cpp index 68846459700..56bf630c728 100644 --- a/src/util/sample.cpp +++ b/src/util/sample.cpp @@ -623,8 +623,8 @@ void SampleUtil::addMonoToStereo(CSAMPLE* M_RESTRICT pDest, void SampleUtil::stripMultiToStereo( CSAMPLE* pBuffer, SINT numFrames, - int numChannels) { - DEBUG_ASSERT(numChannels > 2); + mixxx::audio::ChannelCount numChannels) { + DEBUG_ASSERT(numChannels > mixxx::audio::ChannelCount::stereo()); // forward loop for (SINT i = 0; i < numFrames; ++i) { pBuffer[i * 2] = pBuffer[i * numChannels]; @@ -637,8 +637,8 @@ void SampleUtil::copyMultiToStereo( CSAMPLE* M_RESTRICT pDest, const CSAMPLE* M_RESTRICT pSrc, SINT numFrames, - int numChannels) { - DEBUG_ASSERT(numChannels > 2); + mixxx::audio::ChannelCount numChannels) { + DEBUG_ASSERT(numChannels > mixxx::audio::ChannelCount::stereo()); // forward loop for (SINT i = 0; i < numFrames; ++i) { pDest[i * 2] = pSrc[i * numChannels]; @@ -646,7 +646,6 @@ void SampleUtil::copyMultiToStereo( } } - // static void SampleUtil::reverse(CSAMPLE* pBuffer, SINT numSamples) { for (SINT j = 0; j < numSamples / 4; ++j) { diff --git a/src/util/sample.h b/src/util/sample.h index 5ff3c833643..f24ba39806d 100644 --- a/src/util/sample.h +++ b/src/util/sample.h @@ -1,12 +1,12 @@ #pragma once +#include #include #include // memset -#include - -#include "util/types.h" +#include "audio/types.h" #include "util/platform.h" +#include "util/types.h" // A group of utilities for working with samples. class SampleUtil { @@ -92,22 +92,26 @@ class SampleUtil { return CSAMPLE_GAIN_clamp(in); } - inline static SINT roundPlayPosToFrameStart(double playPos, int numChannels) { + inline static SINT roundPlayPosToFrameStart( + double playPos, mixxx::audio::ChannelCount numChannels) { SINT playPosFrames = static_cast(round(playPos / numChannels)); return playPosFrames * numChannels; } - inline static SINT truncPlayPosToFrameStart(double playPos, int numChannels) { + inline static SINT truncPlayPosToFrameStart( + double playPos, mixxx::audio::ChannelCount numChannels) { SINT playPosFrames = static_cast(playPos / numChannels); return playPosFrames * numChannels; } - inline static SINT floorPlayPosToFrameStart(double playPos, int numChannels) { + inline static SINT floorPlayPosToFrameStart( + double playPos, mixxx::audio::ChannelCount numChannels) { SINT playPosFrames = static_cast(floor(playPos / numChannels)); return playPosFrames * numChannels; } - inline static SINT ceilPlayPosToFrameStart(double playPos, int numChannels) { + inline static SINT ceilPlayPosToFrameStart( + double playPos, mixxx::audio::ChannelCount numChannels) { SINT playPosFrames = static_cast(ceil(playPos / numChannels)); return playPosFrames * numChannels; } @@ -290,8 +294,9 @@ class SampleUtil { // channels are discarded. // pBuffer must contain (numFrames * numChannels) samples // (numFrames * 2) samples will be written into pBuffer - static void stripMultiToStereo(CSAMPLE* pBuffer, SINT numFrames, - int numChannels); + static void stripMultiToStereo(CSAMPLE* pBuffer, + SINT numFrames, + mixxx::audio::ChannelCount numChannels); // Copies and strips interleaved multi-channel sample data in pSrc with // numChannels >= 2 down to stereo samples into pDest. Only samples from @@ -299,8 +304,10 @@ class SampleUtil { // channels will be ignored. // pSrc must contain (numFrames * numChannels) samples // (numFrames * 2) samples will be written into pDest - static void copyMultiToStereo(CSAMPLE* pDest, const CSAMPLE* pSrc, - SINT numFrames, int numChannels); + static void copyMultiToStereo(CSAMPLE* pDest, + const CSAMPLE* pSrc, + SINT numFrames, + mixxx::audio::ChannelCount numChannels); // reverses stereo sample in place static void reverse(CSAMPLE* pBuffer, SINT numSamples); diff --git a/src/vinylcontrol/vinylcontrolmanager.cpp b/src/vinylcontrol/vinylcontrolmanager.cpp index dedfcba838c..2d3ada7a29a 100644 --- a/src/vinylcontrol/vinylcontrolmanager.cpp +++ b/src/vinylcontrol/vinylcontrolmanager.cpp @@ -2,6 +2,7 @@ #include +#include "audio/types.h" #include "control/controlobject.h" #include "control/controlproxy.h" #include "mixer/playermanager.h" @@ -30,7 +31,11 @@ VinylControlManager::VinylControlManager(QObject* pParent, // VinylControlProcessor. for (int i = 0; i < kMaximumVinylControlInputs; ++i) { pSoundManager->registerInput( - AudioInput(AudioInput::VINYLCONTROL, 0, 2, i), m_pProcessor); + AudioInput(AudioInput::VINYLCONTROL, + 0, + mixxx::audio::ChannelCount::stereo(), + i), + m_pProcessor); } } diff --git a/src/waveform/waveform.cpp b/src/waveform/waveform.cpp index ef1db7a1bcf..3f0331e1b31 100644 --- a/src/waveform/waveform.cpp +++ b/src/waveform/waveform.cpp @@ -3,12 +3,11 @@ #include #include "analyzer/constants.h" +#include "engine/engine.h" #include "proto/waveform.pb.h" using namespace mixxx::track; -constexpr int kNumChannels = 2; - // Return the smallest power of 2 which is greater than the desired size when // squared. int computeTextureStride(int size) { @@ -104,15 +103,14 @@ QByteArray Waveform::toByteArray() const { io::Waveform::Signal* high = filtered->mutable_high(); // TODO(vrince) set max/min for each signal - int numChannels = kNumChannels; all->set_units(io::Waveform::RMS); - all->set_channels(numChannels); + all->set_channels(mixxx::kEngineChannelCount); low->set_units(io::Waveform::RMS); - low->set_channels(numChannels); + low->set_channels(mixxx::kEngineChannelCount); mid->set_units(io::Waveform::RMS); - mid->set_channels(numChannels); + mid->set_channels(mixxx::kEngineChannelCount); high->set_units(io::Waveform::RMS); - high->set_channels(numChannels); + high->set_channels(mixxx::kEngineChannelCount); int dataSize = getDataSize(); for (int i = 0; i < dataSize; ++i) {