summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbe_ <be.0@gmx.com>2017-06-20 14:32:35 -0500
committerbe_ <be.0@gmx.com>2017-06-21 14:24:48 -0500
commitda3702c603f04b4c8de4c55d1dfbf6eaabe3d7d5 (patch)
tree79ae940ec704c1fe037e225b628d468e3da87835
parentf61908e240b4c75621cfb030757eae0e7a3b8e71 (diff)
add a record/broadcast input
so users do not have to use external programs like Audacity and BUTT when using external mixers
-rw-r--r--src/engine/enginemaster.cpp21
-rw-r--r--src/engine/enginemaster.h1
-rw-r--r--src/engine/sidechain/enginesidechain.cpp19
-rw-r--r--src/engine/sidechain/enginesidechain.h13
-rw-r--r--src/soundio/soundmanager.cpp4
-rw-r--r--src/soundio/soundmanagerutil.cpp5
-rw-r--r--src/soundio/soundmanagerutil.h1
7 files changed, 54 insertions, 10 deletions
diff --git a/src/engine/enginemaster.cpp b/src/engine/enginemaster.cpp
index 0c3375188d..0719939081 100644
--- a/src/engine/enginemaster.cpp
+++ b/src/engine/enginemaster.cpp
@@ -48,6 +48,7 @@ EngineMaster::EngineMaster(UserSettingsPointer pConfig,
m_bBusOutputConnected[EngineChannel::LEFT] = false;
m_bBusOutputConnected[EngineChannel::CENTER] = false;
m_bBusOutputConnected[EngineChannel::RIGHT] = false;
+ m_bExternalRecordBroadcastInputConnected = false;
m_pWorkerScheduler = new EngineWorkerScheduler(this);
m_pWorkerScheduler->start(QThread::HighPriority);
@@ -379,6 +380,9 @@ void EngineMaster::process(const int iBufferSize) {
bool boothEnabled = m_pBoothEnabled->get();
bool headphoneEnabled = m_pHeadphoneEnabled->get();
+ // TODO: remove assumption of stereo buffer
+ const unsigned int kChannels = 2;
+ const unsigned int iFrames = iBufferSize / kChannels;
unsigned int iSampleRate = static_cast<int>(m_pMasterSampleRate->get());
if (m_pEngineEffectsManager) {
m_pEngineEffectsManager->onCallbackStart();
@@ -424,7 +428,7 @@ void EngineMaster::process(const int iBufferSize) {
double measuredRoundTripLatency = m_pRoundTripLatency->get();
// iBufferSize / iSampleRate gives double Mixxx's processing latency because
// there are 2 channels per buffer. FIXME when removing the assumption of stereo channels.
- double processingLatency = (double)iBufferSize / iSampleRate / 2.0 * 1000.0;
+ double processingLatency = (double)iBufferSize / iSampleRate / kChannels * 1000.0;
if (measuredRoundTripLatency == 0.0) {
inputLatencyCompensation = processingLatency;
} else {
@@ -657,7 +661,10 @@ void EngineMaster::process(const int iBufferSize) {
// Submit master samples to the side chain to do broadcasting, recording,
// etc. (cpu intensive non-realtime tasks)
- if (m_pEngineSideChain != NULL) {
+ // If recording/broadcasting from a sound card input,
+ // SoundManager will send the input buffer from the sound card to m_pSidechain
+ // so skip sending a signal to m_pSidechain here.
+ if (m_pEngineSideChain != NULL && !m_bExternalRecordBroadcastInputConnected) {
if (configuredTalkoverMixMode == TalkoverMixMode::DIRECT_MONITOR
&& m_pNumMicsConfigured->get() > 0) {
// When using direct monitoring, the user hears the microphone inputs
@@ -674,9 +681,9 @@ void EngineMaster::process(const int iBufferSize) {
m_pSidechain, 1.0,
m_pTalkover, 1.0,
iBufferSize);
- m_pEngineSideChain->writeSamples(m_pSidechain, iBufferSize);
+ m_pEngineSideChain->writeSamples(m_pSidechain, iFrames);
} else {
- m_pEngineSideChain->writeSamples(m_pMaster, iBufferSize);
+ m_pEngineSideChain->writeSamples(m_pMaster, iFrames);
}
}
@@ -907,6 +914,9 @@ void EngineMaster::onInputConnected(AudioInput input) {
case AudioInput::VINYLCONTROL:
// We don't track enabled vinyl control inputs.
break;
+ case AudioInput::RECORD_BROADCAST:
+ m_bExternalRecordBroadcastInputConnected = true;
+ break;
default:
break;
}
@@ -923,6 +933,9 @@ void EngineMaster::onInputDisconnected(AudioInput input) {
case AudioInput::VINYLCONTROL:
// We don't track enabled vinyl control inputs.
break;
+ case AudioInput::RECORD_BROADCAST:
+ m_bExternalRecordBroadcastInputConnected = false;
+ break;
default:
break;
}
diff --git a/src/engine/enginemaster.h b/src/engine/enginemaster.h
index 3ed0b50345..7e0c654571 100644
--- a/src/engine/enginemaster.h
+++ b/src/engine/enginemaster.h
@@ -364,6 +364,7 @@ class EngineMaster : public QObject, public AudioSource {
ControlObject* m_pHeadphoneEnabled;
volatile bool m_bBusOutputConnected[3];
+ bool m_bExternalRecordBroadcastInputConnected;
};
#endif
diff --git a/src/engine/sidechain/enginesidechain.cpp b/src/engine/sidechain/enginesidechain.cpp
index 6081fd966b..f7f2fec5a4 100644
--- a/src/engine/sidechain/enginesidechain.cpp
+++ b/src/engine/sidechain/enginesidechain.cpp
@@ -75,11 +75,24 @@ void EngineSideChain::addSideChainWorker(SideChainWorker* pWorker) {
m_workers.append(pWorker);
}
-void EngineSideChain::writeSamples(const CSAMPLE* newBuffer, int buffer_size) {
+void EngineSideChain::receiveBuffer(AudioInput input,
+ const CSAMPLE* pBuffer,
+ unsigned int iFrames) {
+ if (input.getType() != AudioInput::RECORD_BROADCAST) {
+ qDebug() << "WARNING: AudioInput type is not RECORD_BROADCAST. Ignoring incoming buffer.";
+ return;
+ }
+ writeSamples(pBuffer, iFrames);
+}
+
+void EngineSideChain::writeSamples(const CSAMPLE* pBuffer, int iFrames) {
Trace sidechain("EngineSideChain::writeSamples");
- int samples_written = m_sampleFifo.write(newBuffer, buffer_size);
+ // TODO: remove assumption of stereo buffer
+ const int kChannels = 2;
+ const int iSamples = iFrames * kChannels;
+ int samples_written = m_sampleFifo.write(pBuffer, iSamples);
- if (samples_written != buffer_size) {
+ if (samples_written != iFrames) {
Counter("EngineSideChain::writeSamples buffer overrun").increment();
}
diff --git a/src/engine/sidechain/enginesidechain.h b/src/engine/sidechain/enginesidechain.h
index 72904b3a94..8497c07d91 100644
--- a/src/engine/sidechain/enginesidechain.h
+++ b/src/engine/sidechain/enginesidechain.h
@@ -24,11 +24,12 @@
#include "preferences/usersettings.h"
#include "engine/sidechain/sidechainworker.h"
+#include "soundio/soundmanagerutil.h"
#include "util/fifo.h"
#include "util/mutex.h"
#include "util/types.h"
-class EngineSideChain : public QThread {
+class EngineSideChain : public QThread, public AudioDestination {
Q_OBJECT
public:
EngineSideChain(UserSettingsPointer pConfig);
@@ -37,13 +38,19 @@ class EngineSideChain : public QThread {
// Not thread-safe, wait-free. Submit buffer of samples to the sidechain for
// processing. Should only be called from a single writer thread (typically
// the engine callback).
- void writeSamples(const CSAMPLE* buffer, int buffer_size);
+ void writeSamples(const CSAMPLE* pBuffer, int iFrames);
+
+ // Thin wrapper around writeSamples that is used by SoundManager when receiving
+ // from a sound card input instead of the engine
+ void receiveBuffer(AudioInput input,
+ const CSAMPLE* pBuffer,
+ unsigned int iFrames) override;
// Thread-safe, blocking.
void addSideChainWorker(SideChainWorker* pWorker);
private:
- void run();
+ void run() override;
UserSettingsPointer m_pConfig;
// Indicates that the thread should exit.
diff --git a/src/soundio/soundmanager.cpp b/src/soundio/soundmanager.cpp
index ee000846de..51da1cd814 100644
--- a/src/soundio/soundmanager.cpp
+++ b/src/soundio/soundmanager.cpp
@@ -28,6 +28,7 @@
#include "engine/enginebuffer.h"
#include "engine/enginemaster.h"
#include "engine/sidechain/enginenetworkstream.h"
+#include "engine/sidechain/enginesidechain.h"
#include "soundio/sounddevice.h"
#include "soundio/sounddevicenetwork.h"
#include "soundio/sounddevicenotfound.h"
@@ -80,6 +81,9 @@ SoundManager::SoundManager(UserSettingsPointer pConfig,
m_pNetworkStream = QSharedPointer<EngineNetworkStream>(
new EngineNetworkStream(2, 0));
+ AudioInput recordInput = AudioInput(AudioPath::RECORD_BROADCAST, 0, 2);
+ registerInput(recordInput, pMaster->getSideChain());
+
queryDevices();
if (!m_config.readFromDisk()) {
diff --git a/src/soundio/soundmanagerutil.cpp b/src/soundio/soundmanagerutil.cpp
index 8abfe01fbe..e890aa6237 100644
--- a/src/soundio/soundmanagerutil.cpp
+++ b/src/soundio/soundmanagerutil.cpp
@@ -163,6 +163,8 @@ QString AudioPath::getStringFromType(AudioPathType type) {
return QString::fromAscii("Bus");
case DECK:
return QString::fromAscii("Deck");
+ case RECORD_BROADCAST:
+ return QString::fromAscii("Record/Broadcast");
case VINYLCONTROL:
return QString::fromAscii("Vinyl Control");
case MICROPHONE:
@@ -205,6 +207,8 @@ QString AudioPath::getTrStringFromType(AudioPathType type, unsigned char index)
case DECK:
return QString("%1 %2").arg(QObject::tr("Deck"),
QString::number(index + 1));
+ case RECORD_BROADCAST:
+ return QObject::tr("Record/Broadcast");
case VINYLCONTROL:
return QString("%1 %2").arg(QObject::tr("Vinyl Control"),
QString::number(index + 1));
@@ -446,6 +450,7 @@ QList<AudioPathType> AudioInput::getSupportedTypes() {
#endif
types.append(AUXILIARY);
types.append(MICROPHONE);
+ types.append(RECORD_BROADCAST);
return types;
}
diff --git a/src/soundio/soundmanagerutil.h b/src/soundio/soundmanagerutil.h
index 5088d3e10c..c8676b0c84 100644
--- a/src/soundio/soundmanagerutil.h
+++ b/src/soundio/soundmanagerutil.h
@@ -60,6 +60,7 @@ public:
HEADPHONES,
BUS,
DECK,
+ RECORD_BROADCAST,
VINYLCONTROL,
MICROPHONE,
AUXILIARY,