Skip to content

Commit

Permalink
refactor(soundio): Use SampleRate type instead of double
Browse files Browse the repository at this point in the history
  • Loading branch information
Holzhaus committed Sep 2, 2023
1 parent 6b8f0ff commit 884fd0b
Show file tree
Hide file tree
Showing 11 changed files with 92 additions and 83 deletions.
22 changes: 11 additions & 11 deletions src/engine/sidechain/enginenetworkstream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,15 @@ const mixxx::Logger kLogger("EngineNetworkStream");
} // namespace

EngineNetworkStream::EngineNetworkStream(int numOutputChannels,
int numInputChannels)
: m_pInputFifo(nullptr),
m_numOutputChannels(numOutputChannels),
m_numInputChannels(numInputChannels),
m_sampleRate(0),
m_inputStreamStartTimeUs(-1),
m_inputStreamFramesWritten(0),
m_inputStreamFramesRead(0),
m_outputWorkers(BROADCAST_MAX_CONNECTIONS) {
int numInputChannels)
: m_pInputFifo(nullptr),
m_numOutputChannels(numOutputChannels),
m_numInputChannels(numInputChannels),
m_sampleRate(),
m_inputStreamStartTimeUs(-1),
m_inputStreamFramesWritten(0),
m_inputStreamFramesRead(0),
m_outputWorkers(BROADCAST_MAX_CONNECTIONS) {
if (numInputChannels) {
m_pInputFifo = new FIFO<CSAMPLE>(numInputChannels * kBufferFrames);
}
Expand Down Expand Up @@ -73,7 +73,7 @@ EngineNetworkStream::~EngineNetworkStream() {
delete m_pInputFifo;
}

void EngineNetworkStream::startStream(double sampleRate) {
void EngineNetworkStream::startStream(mixxx::audio::SampleRate sampleRate) {
m_sampleRate = sampleRate;
m_inputStreamStartTimeUs = getNetworkTimeUs();
m_inputStreamFramesWritten = 0;
Expand Down Expand Up @@ -122,7 +122,7 @@ void EngineNetworkStream::read(CSAMPLE* buffer, int frames) {

qint64 EngineNetworkStream::getInputStreamTimeFrames() {
return static_cast<qint64>(static_cast<double>(getInputStreamTimeUs()) *
m_sampleRate / 1000000.0);
m_sampleRate.toDouble() / 1000000.0);
}

qint64 EngineNetworkStream::getInputStreamTimeUs() {
Expand Down
11 changes: 6 additions & 5 deletions src/engine/sidechain/enginenetworkstream.h
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
#pragma once

#include <engine/sidechain/networkoutputstreamworker.h>
#include <engine/sidechain/networkinputstreamworker.h>
#include <QVector>

#include "util/types.h"
#include "audio/types.h"
#include "engine/sidechain/networkinputstreamworker.h"
#include "engine/sidechain/networkoutputstreamworker.h"
#include "util/fifo.h"
#include "util/types.h"

class EngineNetworkStream {
public:
EngineNetworkStream(int numOutputChannels,
int numInputChannels);
virtual ~EngineNetworkStream();

void startStream(double sampleRate);
void startStream(mixxx::audio::SampleRate sampleRate);
void stopStream();

int getReadExpected();
Expand Down Expand Up @@ -47,7 +48,7 @@ class EngineNetworkStream {
FIFO<CSAMPLE>* m_pInputFifo;
int m_numOutputChannels;
int m_numInputChannels;
double m_sampleRate;
mixxx::audio::SampleRate m_sampleRate;
qint64 m_inputStreamStartTimeUs;
qint64 m_inputStreamFramesWritten;
qint64 m_inputStreamFramesRead;
Expand Down
28 changes: 15 additions & 13 deletions src/engine/sidechain/networkoutputstreamworker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ const mixxx::Logger kLogger("NetworkStreamWorker");
} // namespace

NetworkOutputStreamWorker::NetworkOutputStreamWorker()
: m_sampleRate(0),
m_numOutputChannels(0),
m_workerState(NETWORKSTREAMWORKER_STATE_NEW),
m_functionCode(0),
m_runCount(0),
m_streamStartTimeUs(-1),
m_streamFramesWritten(0),
m_writeOverflowCount(0),
m_outputDrift(false) {
: m_sampleRate(),
m_numOutputChannels(0),
m_workerState(NETWORKSTREAMWORKER_STATE_NEW),
m_functionCode(0),
m_runCount(0),
m_streamStartTimeUs(-1),
m_streamFramesWritten(0),
m_writeOverflowCount(0),
m_outputDrift(false) {
}

void NetworkOutputStreamWorker::outputAvailable() {
Expand All @@ -31,16 +31,17 @@ QSharedPointer<FIFO<CSAMPLE>> NetworkOutputStreamWorker::getOutputFifo() {
return QSharedPointer<FIFO<CSAMPLE>>();
}

void NetworkOutputStreamWorker::startStream(double samplerate, int numOutputChannels) {
m_sampleRate = samplerate;
void NetworkOutputStreamWorker::startStream(
mixxx::audio::SampleRate sampleRate, int numOutputChannels) {
m_sampleRate = sampleRate;
m_numOutputChannels = numOutputChannels;

m_streamStartTimeUs = EngineNetworkStream::getNetworkTimeUs();
m_streamFramesWritten = 0;
}

void NetworkOutputStreamWorker::stopStream() {
m_sampleRate = 0;
m_sampleRate = mixxx::audio::SampleRate();
m_numOutputChannels = 0;

m_streamStartTimeUs = -1;
Expand All @@ -51,7 +52,8 @@ bool NetworkOutputStreamWorker::threadWaiting() {
}

qint64 NetworkOutputStreamWorker::getStreamTimeFrames() {
return static_cast<qint64>(static_cast<double>(getStreamTimeUs()) * m_sampleRate / 1000000.0);
return static_cast<qint64>(static_cast<double>(getStreamTimeUs()) *
m_sampleRate.toDouble() / 1000000.0);
}

qint64 NetworkOutputStreamWorker::getStreamTimeUs() {
Expand Down
23 changes: 12 additions & 11 deletions src/engine/sidechain/networkoutputstreamworker.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

#include <QSharedPointer>

#include "util/types.h"
#include "audio/types.h"
#include "util/fifo.h"
#include "util/types.h"

/*
* States:
Expand Down Expand Up @@ -52,7 +53,7 @@ class NetworkOutputStreamWorker {
virtual void setOutputFifo(QSharedPointer<FIFO<CSAMPLE>> pOutputFifo);
virtual QSharedPointer<FIFO<CSAMPLE>> getOutputFifo();

void startStream(double samplerate, int numOutputChannels);
void startStream(mixxx::audio::SampleRate sampleRate, int numOutputChannels);
void stopStream();

virtual bool threadWaiting();
Expand Down Expand Up @@ -83,17 +84,17 @@ class NetworkOutputStreamWorker {
void incRunCount();

private:
double m_sampleRate;
int m_numOutputChannels;
mixxx::audio::SampleRate m_sampleRate;
int m_numOutputChannels;

int m_workerState;
int m_functionCode;
int m_runCount;
int m_workerState;
int m_functionCode;
int m_runCount;

qint64 m_streamStartTimeUs;
qint64 m_streamFramesWritten;
int m_writeOverflowCount;
bool m_outputDrift;
qint64 m_streamStartTimeUs;
qint64 m_streamFramesWritten;
int m_writeOverflowCount;
bool m_outputDrift;
};

typedef QSharedPointer<NetworkOutputStreamWorker> NetworkOutputStreamWorkerPtr;
13 changes: 6 additions & 7 deletions src/soundio/sounddevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@
#include "util/defs.h"
#include "util/sample.h"

constexpr mixxx::audio::SampleRate SoundDevice::kFallbackSampleRate =
mixxx::audio::SampleRate(44100);

SoundDevice::SoundDevice(UserSettingsPointer config, SoundManager* sm)
: m_pConfig(config),
m_pSoundManager(sm),
m_strDisplayName("Unknown Soundcard"),
m_iNumOutputChannels(2),
m_iNumInputChannels(2),
m_dSampleRate(44100.0),
m_sampleRate(kFallbackSampleRate),
m_hostAPI("Unknown API"),
m_configFramesPerBuffer(0) {
}
Expand All @@ -28,12 +31,8 @@ int SoundDevice::getNumOutputChannels() const {
return m_iNumOutputChannels;
}

void SoundDevice::setSampleRate(double sampleRate) {
if (sampleRate <= 0.0) {
// this is the default value used elsewhere in this file
sampleRate = 44100.0;
}
m_dSampleRate = sampleRate;
void SoundDevice::setSampleRate(mixxx::audio::SampleRate sampleRate) {
m_sampleRate = sampleRate.isValid() ? sampleRate : kFallbackSampleRate;
}

void SoundDevice::setConfigFramesPerBuffer(unsigned int framesPerBuffer) {
Expand Down
9 changes: 6 additions & 3 deletions src/soundio/sounddevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <QList>
#include <QString>

#include "audio/types.h"
#include "preferences/usersettings.h"
#include "soundio/sounddevicestatus.h"
#include "soundio/soundmanagerutil.h"
Expand Down Expand Up @@ -31,15 +32,15 @@ class SoundDevice {
inline const QString& getHostAPI() const {
return m_hostAPI;
}
void setSampleRate(double sampleRate);
void setSampleRate(mixxx::audio::SampleRate sampleRate);
void setConfigFramesPerBuffer(unsigned int framesPerBuffer);
virtual SoundDeviceStatus open(bool isClkRefDevice, int syncBuffers) = 0;
virtual bool isOpen() const = 0;
virtual SoundDeviceStatus close() = 0;
virtual void readProcess(SINT framesPerBuffer) = 0;
virtual void writeProcess(SINT framesPerBuffer) = 0;
virtual QString getError() const = 0;
virtual unsigned int getDefaultSampleRate() const = 0;
virtual mixxx::audio::SampleRate getDefaultSampleRate() const = 0;
int getNumOutputChannels() const;
int getNumInputChannels() const;
SoundDeviceStatus addOutput(const AudioOutputBuffer& out);
Expand All @@ -57,6 +58,8 @@ class SoundDevice {
bool operator==(const QString &other) const;

protected:
static const mixxx::audio::SampleRate kFallbackSampleRate;

void composeOutputBuffer(CSAMPLE* outputBuffer,
const SINT iFramesPerBuffer,
const SINT readOffset,
Expand All @@ -81,7 +84,7 @@ class SoundDevice {
// The number of input channels that the soundcard has
int m_iNumInputChannels;
// The current samplerate for the sound device.
double m_dSampleRate;
mixxx::audio::SampleRate m_sampleRate;
// The name of the audio API used by this device.
QString m_hostAPI;
// The **configured** number of frames per buffer. We'll tell PortAudio we
Expand Down
29 changes: 17 additions & 12 deletions src/soundio/sounddevicenetwork.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ constexpr int kNetworkLatencyFrames = 8192; // 185 ms @ 44100 Hz
// Which results in case of ogg in a dynamic latency from 0.14 ms to to 185 ms
// Now we have switched to a fixed latency of 8192 frames (stereo samples) =
// which is 185 @ 44100 ms and twice the maximum of the max mixxx audio buffer
//
constexpr auto kDefaultSampleRate = mixxx::audio::SampleRate(44100);

const mixxx::Logger kLogger("SoundDeviceNetwork");
} // namespace
Expand All @@ -43,7 +45,7 @@ SoundDeviceNetwork::SoundDeviceNetwork(
m_targetTime(0) {
// Setting parent class members:
m_hostAPI = "Network stream";
m_dSampleRate = 44100.0;
m_sampleRate = SoundDevice::kFallbackSampleRate;
m_deviceId.name = kNetworkDeviceInternalName;
m_strDisplayName = QObject::tr("Network stream");
m_iNumInputChannels = pNetworkStream->getNumInputChannels();
Expand All @@ -58,13 +60,13 @@ SoundDeviceStatus SoundDeviceNetwork::open(bool isClkRefDevice, int syncBuffers)
kLogger.debug() << "open:" << m_deviceId.name;

// Sample rate
if (m_dSampleRate <= 0) {
m_dSampleRate = 44100.0;
if (!m_sampleRate.isValid()) {
m_sampleRate = SoundDevice::kFallbackSampleRate;
}

const SINT framesPerBuffer = m_configFramesPerBuffer;
const auto requestedBufferTime = mixxx::Duration::fromSeconds(
framesPerBuffer / m_dSampleRate);
framesPerBuffer / m_sampleRate.toDouble());

// Feed the network device buffer directly from the
// clock reference device callback
Expand All @@ -78,18 +80,18 @@ SoundDeviceStatus SoundDeviceNetwork::open(bool isClkRefDevice, int syncBuffers)
m_iNumInputChannels * framesPerBuffer * 2);
}

m_pNetworkStream->startStream(m_dSampleRate);
m_pNetworkStream->startStream(m_sampleRate);

// Create the callback Thread if requested
if (isClkRefDevice) {
kLogger.debug() << "Clock Reference with:" << framesPerBuffer << "frames/buffer @"
<< m_dSampleRate << "Hz =" << requestedBufferTime.formatMillisWithUnit();
<< m_sampleRate << "Hz =" << requestedBufferTime.formatMillisWithUnit();

// Update the samplerate and latency ControlObjects, which allow the
// waveform view to properly correct for the latency.
ControlObject::set(ConfigKey("[Master]", "latency"),
requestedBufferTime.toDoubleMillis());
ControlObject::set(ConfigKey("[Master]", "samplerate"), m_dSampleRate);
ControlObject::set(ConfigKey("[Master]", "samplerate"), m_sampleRate);

// Network stream was just started above so we have to wait until
// we can pass one chunk.
Expand All @@ -100,7 +102,7 @@ SoundDeviceStatus SoundDeviceNetwork::open(bool isClkRefDevice, int syncBuffers)
m_pThread->start(QThread::TimeCriticalPriority);
} else {
kLogger.debug() << "Maximum:" << framesPerBuffer << "frames/buffer @"
<< m_dSampleRate << "Hz =" << requestedBufferTime.formatMillisWithUnit();
<< m_sampleRate << "Hz =" << requestedBufferTime.formatMillisWithUnit();
}

return SoundDeviceStatus::Ok;
Expand All @@ -125,6 +127,10 @@ SoundDeviceStatus SoundDeviceNetwork::close() {
return SoundDeviceStatus::Ok;
}

mixxx::audio::SampleRate SoundDeviceNetwork::getDefaultSampleRate() const {
return kDefaultSampleRate;
}

QString SoundDeviceNetwork::getError() const {
return QString();
}
Expand Down Expand Up @@ -501,7 +507,7 @@ void SoundDeviceNetwork::updateCallbackEntryToDacTime(SINT framesPerBuffer) {
m_clkRefTimer.start();
qint64 currentTime = m_pNetworkStream->getInputStreamTimeUs();
// This deadline for the next buffer in microseconds since the Unix epoch
m_targetTime += static_cast<qint64>(framesPerBuffer / m_dSampleRate * 1000000);
m_targetTime += static_cast<qint64>(framesPerBuffer / m_sampleRate.toDouble() * 1000000);
double callbackEntrytoDacSecs = (m_targetTime - currentTime) / 1000000.0;
callbackEntrytoDacSecs = math_max(callbackEntrytoDacSecs, 0.0001);
VisualPlayPosition::setCallbackEntryToDacSecs(callbackEntrytoDacSecs, m_clkRefTimer);
Expand All @@ -510,11 +516,10 @@ void SoundDeviceNetwork::updateCallbackEntryToDacTime(SINT framesPerBuffer) {

void SoundDeviceNetwork::updateAudioLatencyUsage(SINT framesPerBuffer) {
m_framesSinceAudioLatencyUsageUpdate += framesPerBuffer;
if (m_framesSinceAudioLatencyUsageUpdate
> (m_dSampleRate / CPU_USAGE_UPDATE_RATE)) {
if (m_framesSinceAudioLatencyUsageUpdate > (m_sampleRate.toDouble() / CPU_USAGE_UPDATE_RATE)) {
double secInAudioCb = m_timeInAudioCallback.toDoubleSeconds();
m_masterAudioLatencyUsage.set(secInAudioCb /
(m_framesSinceAudioLatencyUsageUpdate / m_dSampleRate));
(m_framesSinceAudioLatencyUsageUpdate / m_sampleRate.toDouble()));
m_timeInAudioCallback = mixxx::Duration::empty();
m_framesSinceAudioLatencyUsageUpdate = 0;
//qDebug() << m_pMasterAudioLatencyUsage->get();
Expand Down
5 changes: 1 addition & 4 deletions src/soundio/sounddevicenetwork.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ class ControlProxy;
class EngineNetworkStream;
class SoundDeviceNetworkThread;


class SoundDeviceNetwork : public SoundDevice {
public:
SoundDeviceNetwork(UserSettingsPointer config,
Expand All @@ -37,9 +36,7 @@ class SoundDeviceNetwork : public SoundDevice {
void writeProcess(SINT framesPerBuffer) override;
QString getError() const override;

unsigned int getDefaultSampleRate() const override {
return 44100;
}
mixxx::audio::SampleRate getDefaultSampleRate() const override;

// NOTE: This does not take a frames per buffer argument because that is
// always equal to the configured buffer size for network streams
Expand Down
4 changes: 2 additions & 2 deletions src/soundio/sounddevicenotfound.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class SoundDeviceNotFound : public SoundDevice {
return QObject::tr("Device not found");
};

unsigned int getDefaultSampleRate() const override {
return 44100;
mixxx::audio::SampleRate getDefaultSampleRate() const override {
return SoundDevice::kFallbackSampleRate;
}
};
Loading

0 comments on commit 884fd0b

Please sign in to comment.