mirror of
https://github.com/VARCem/munt.git
synced 2026-07-08 18:16:13 +00:00
Introduced helper method AudioStream::renderAndUpdateState
This method is now used in majority of audio drivers that simplifies rendering loops or the callbacks yet ensures that all drivers invoke the related operations in the right order.
This commit is contained in:
@@ -59,8 +59,7 @@ void *AlsaAudioStream::processingThread(void *userData) {
|
||||
framesInAudioBuffer = (quint32)delayp;
|
||||
}
|
||||
}
|
||||
audioStream.updateTimeInfo(nanosNow, framesInAudioBuffer);
|
||||
audioStream.synthRoute.render(audioStream.buffer, audioStream.bufferSize);
|
||||
audioStream.renderAndUpdateState(audioStream.buffer, audioStream.bufferSize, nanosNow, framesInAudioBuffer);
|
||||
error = snd_pcm_writei(audioStream.stream, audioStream.buffer, audioStream.bufferSize);
|
||||
if (error < 0) {
|
||||
qDebug() << "snd_pcm_writei failed:" << snd_strerror(error) << "-> recovering...";
|
||||
@@ -75,7 +74,6 @@ void *AlsaAudioStream::processingThread(void *userData) {
|
||||
// isErrorOccured = true;
|
||||
// break;
|
||||
}
|
||||
audioStream.framesRendered(audioStream.bufferSize);
|
||||
}
|
||||
if (isErrorOccured) {
|
||||
snd_pcm_close(audioStream.stream);
|
||||
|
||||
@@ -82,6 +82,13 @@ quint64 AudioStream::computeMIDITimestamp(uint relativeFrameTime) const {
|
||||
return getRenderedFramesCount() + relativeFrameTime;
|
||||
}
|
||||
|
||||
// Only called from the rendering thread.
|
||||
void AudioStream::renderAndUpdateState(MT32Emu::Bit16s *buffer, const quint32 frameCount, const MasterClockNanos measuredNanos, const quint32 framesInAudioBuffer) {
|
||||
updateTimeInfo(measuredNanos, framesInAudioBuffer);
|
||||
synthRoute.render(buffer, frameCount);
|
||||
framesRendered(frameCount);
|
||||
}
|
||||
|
||||
// Only called from the rendering thread.
|
||||
void AudioStream::updateTimeInfo(const MasterClockNanos measuredNanos, const quint32 framesInAudioBuffer) {
|
||||
const TimeInfo &timeInfo = timeInfos[getSnapshotReadIx(timeInfoChangeCount)];
|
||||
|
||||
@@ -40,6 +40,7 @@ protected:
|
||||
} timeInfos[2];
|
||||
QAtomicInt timeInfoChangeCount;
|
||||
|
||||
void renderAndUpdateState(MT32Emu::Bit16s *buffer, const quint32 frameCount, const MasterClockNanos measuredNanos, const quint32 framesInAudioBuffer);
|
||||
void updateTimeInfo(const MasterClockNanos measuredNanos, const quint32 framesInAudioBuffer);
|
||||
bool isAutoLatencyMode() const;
|
||||
void framesRendered(quint32 frameCount);
|
||||
|
||||
@@ -93,11 +93,9 @@ void CoreAudioStream::renderOutputBuffer(void *userData, AudioQueueRef queue, Au
|
||||
qDebug() << "CoreAudio: AudioQueueGetCurrentTime() returns invalid sample time";
|
||||
}
|
||||
}
|
||||
stream->updateTimeInfo(nanosNow, framesInAudioBuffer);
|
||||
|
||||
uint frameCount = buffer->mAudioDataByteSize >> 2;
|
||||
stream->synthRoute.render((MT32Emu::Bit16s *)buffer->mAudioData, frameCount);
|
||||
stream->framesRendered(frameCount);
|
||||
stream->renderAndUpdateState((MT32Emu::Bit16s *)buffer->mAudioData, frameCount, nanosNow, framesInAudioBuffer);
|
||||
|
||||
OSStatus res = AudioQueueEnqueueBuffer(queue, buffer, 0, NULL);
|
||||
if (res) qDebug() << "CoreAudio: AudioQueueEnqueueBuffer() failed with error code:" << res;
|
||||
|
||||
@@ -64,8 +64,7 @@ void *OSSAudioStream::processingThread(void *userData) {
|
||||
} else {
|
||||
framesInAudioBuffer = 0;
|
||||
}
|
||||
audioStream.updateTimeInfo(nanosNow, framesInAudioBuffer);
|
||||
audioStream.synthRoute.render(audioStream.buffer, audioStream.bufferSize);
|
||||
audioStream.renderAndUpdateState(audioStream.buffer, audioStream.bufferSize, nanosNow, framesInAudioBuffer);
|
||||
error = write(audioStream.stream, audioStream.buffer, FRAME_SIZE * audioStream.bufferSize);
|
||||
if (error != int(FRAME_SIZE * audioStream.bufferSize)) {
|
||||
if (error == -1) {
|
||||
@@ -76,7 +75,6 @@ void *OSSAudioStream::processingThread(void *userData) {
|
||||
isErrorOccured = true;
|
||||
break;
|
||||
}
|
||||
audioStream.framesRendered(audioStream.bufferSize);
|
||||
}
|
||||
if (isErrorOccured) {
|
||||
close(audioStream.stream);
|
||||
|
||||
@@ -134,10 +134,8 @@ int PortAudioStream::paCallback(const void *inputBuffer, void *outputBuffer, uns
|
||||
} else {
|
||||
framesInAudioBuffer = 0;
|
||||
}
|
||||
stream->updateTimeInfo(nanosNow, framesInAudioBuffer);
|
||||
stream->renderAndUpdateState((Bit16s *)outputBuffer, quint32(frameCount), nanosNow, framesInAudioBuffer);
|
||||
|
||||
stream->synthRoute.render((Bit16s *)outputBuffer, frameCount);
|
||||
stream->framesRendered(quint32(frameCount));
|
||||
return paContinue;
|
||||
}
|
||||
|
||||
|
||||
@@ -151,8 +151,7 @@ void *PulseAudioStream::processingThread(void *userData) {
|
||||
} else {
|
||||
framesInAudioBuffer = 0;
|
||||
}
|
||||
audioStream.updateTimeInfo(nanosNow, framesInAudioBuffer);
|
||||
audioStream.synthRoute.render(audioStream.buffer, audioStream.bufferSize);
|
||||
audioStream.renderAndUpdateState(audioStream.buffer, audioStream.bufferSize, nanosNow, framesInAudioBuffer);
|
||||
if (_pa_simple_write(audioStream.stream, audioStream.buffer, audioStream.bufferSize * FRAME_SIZE, &error) < 0) {
|
||||
qDebug() << "pa_simple_write() failed:" << _pa_strerror(error);
|
||||
_pa_simple_free(audioStream.stream);
|
||||
@@ -162,7 +161,6 @@ void *PulseAudioStream::processingThread(void *userData) {
|
||||
audioStream.processingThreadID = 0;
|
||||
return NULL;
|
||||
}
|
||||
audioStream.framesRendered(audioStream.bufferSize);
|
||||
}
|
||||
audioStream.stopProcessing = false;
|
||||
audioStream.processingThreadID = 0;
|
||||
@@ -209,7 +207,7 @@ bool PulseAudioStream::start() {
|
||||
while (initFrames > 0) {
|
||||
if (_pa_simple_write(stream, buffer, FRAME_SIZE * bufferSize, &error) < 0) {
|
||||
qDebug() << "pa_simple_write() failed:" << _pa_strerror(error);
|
||||
_pa_simple_free(stream);
|
||||
_pa_simple_free(stream);
|
||||
stream = NULL;
|
||||
return false;
|
||||
}
|
||||
@@ -240,7 +238,7 @@ void PulseAudioStream::close() {
|
||||
if (_pa_simple_drain(stream, &error) < 0) {
|
||||
qDebug() << "pa_simple_drain() failed:" << _pa_strerror(error);
|
||||
}
|
||||
_pa_simple_free(stream);
|
||||
_pa_simple_free(stream);
|
||||
stream = NULL;
|
||||
}
|
||||
return;
|
||||
|
||||
@@ -51,10 +51,8 @@ public:
|
||||
} else {
|
||||
framesInAudioBuffer = 0;
|
||||
}
|
||||
stream.updateTimeInfo(nanosNow, framesInAudioBuffer);
|
||||
uint framesToRender = uint(len >> 2);
|
||||
stream.synthRoute.render((Bit16s *)data, framesToRender);
|
||||
stream.framesRendered(framesToRender);
|
||||
stream.renderAndUpdateState((Bit16s *)data, framesToRender, nanosNow, framesInAudioBuffer);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
@@ -150,9 +150,7 @@ void WinMMAudioProcessor::run() {
|
||||
}
|
||||
}
|
||||
DWORD framesInAudioBuffer = playCursor < renderPos ? renderPos - playCursor : (renderPos + stream.audioLatencyFrames) - playCursor;
|
||||
stream.updateTimeInfo(nanosNow, framesInAudioBuffer);
|
||||
stream.synthRoute.render(buf, frameCount);
|
||||
stream.framesRendered(frameCount);
|
||||
stream.renderAndUpdateState(buf, frameCount, nanosNow, framesInAudioBuffer);
|
||||
if (!stream.ringBufferMode && waveOutWrite(stream.hWaveOut, waveHdr, sizeof(WAVEHDR)) != MMSYSERR_NOERROR) {
|
||||
qDebug() << "WinMMAudioDriver: waveOutWrite failed, thread stopped";
|
||||
stream.stopProcessing = true;
|
||||
|
||||
Reference in New Issue
Block a user