Silence the PCM buffer if no chunk is available

This commit is contained in:
badaix 2021-02-03 22:58:21 +01:00
parent 147e4e9b7e
commit 168bc3f98b
7 changed files with 31 additions and 11 deletions

View file

@ -108,7 +108,7 @@ void CoreAudioPlayer::playerCallback(AudioQueueRef queue, AudioQueueBufferRef bu
/// TODO: sometimes this bufferedMS or AudioTimeStamp wraps around 1s (i.e. we're 1s out of sync (behind)) and recovers later on
chronos::usec delay(bufferedMs * 1000);
char* buffer = (char*)bufferRef->mAudioData;
if (!pubStream_->getPlayerChunk(buffer, delay, frames_))
if (!pubStream_->getPlayerChunkOrSilence(buffer, delay, frames_))
{
if (chronos::getTickCount() - lastChunkTick > 5000)
{
@ -117,7 +117,6 @@ void CoreAudioPlayer::playerCallback(AudioQueueRef queue, AudioQueueBufferRef bu
return;
}
// LOG(INFO, LOG_TAG) << "Failed to get chunk. Playing silence.\n";
memset(buffer, 0, buff_size_);
}
else
{

View file

@ -85,20 +85,21 @@ void FilePlayer::requestAudio()
if (buffer_.size() < needed)
buffer_.resize(needed);
if (!stream_->getPlayerChunk(buffer_.data(), 10ms, numFrames))
if (!stream_->getPlayerChunkOrSilence(buffer_.data(), 10ms, numFrames))
{
// LOG(INFO, LOG_TAG) << "Failed to get chunk. Playing silence.\n";
memset(buffer_.data(), 0, needed);
}
else
{
adjustVolume(static_cast<char*>(buffer_.data()), numFrames);
}
if (file_)
{
fwrite(buffer_.data(), 1, needed, file_.get());
fflush(file_.get());
}
loop();
}

View file

@ -152,10 +152,9 @@ oboe::DataCallbackResult OboePlayer::onAudioReady(oboe::AudioStream* /*oboeStrea
// LOG(INFO, LOG_TAG) << "getCurrentOutputLatencyMillis: " << output_latency << ", frames: " << numFrames << "\n";
chronos::usec delay(static_cast<int>(output_latency * 1000.));
if (!stream_->getPlayerChunk(audioData, delay, numFrames))
if (!stream_->getPlayerChunkOrSilence(audioData, delay, numFrames))
{
// LOG(INFO, LOG_TAG) << "Failed to get chunk. Playing silence.\n";
memset(audioData, 0, numFrames * stream_->getFormat().frameSize());
}
else
{

View file

@ -78,10 +78,9 @@ void OpenslPlayer::playerCallback(SLAndroidSimpleBufferQueueItf bq)
return;
chronos::usec delay(ms_ * 1000);
if (!pubStream_->getPlayerChunk(buffer[curBuffer], delay, frames_))
if (!pubStream_->getPlayerChunkOrSilence(buffer[curBuffer], delay, frames_))
{
// LOG(INFO, LOG_TAG) << "Failed to get chunk. Playing silence.\n";
memset(buffer[curBuffer], 0, buff_size);
}
else
{

View file

@ -299,10 +299,9 @@ void PulsePlayer::writeCallback(pa_stream* stream, size_t nbytes)
if (buffer_.size() < nbytes)
buffer_.resize(nbytes);
// LOG(TRACE, LOG_TAG) << "writeCallback latency " << usec << " us, frames: " << numFrames << "\n";
if (!stream_->getPlayerChunk(buffer_.data(), std::chrono::microseconds(usec), numFrames))
if (!stream_->getPlayerChunkOrSilence(buffer_.data(), std::chrono::microseconds(usec), numFrames))
{
// LOG(INFO, LOG_TAG) << "Failed to get chunk. Playing silence.\n";
memset(buffer_.data(), 0, buffer_.size());
// LOG(TRACE, LOG_TAG) << "Failed to get chunk. Playing silence.\n";
}
else
{

View file

@ -24,6 +24,7 @@
#include "common/aixlog.hpp"
#include "common/snap_exception.hpp"
#include "common/str_compat.hpp"
#include "common/utils/logging.hpp"
#include "time_provider.hpp"
#include <cmath>
#include <iostream>
@ -441,3 +442,16 @@ bool Stream::getPlayerChunk(void* outputBuffer, const cs::usec& outputBufferDacT
return false;
}
}
bool Stream::getPlayerChunkOrSilence(void* outputBuffer, const chronos::usec& outputBufferDacTime, uint32_t frames)
{
bool result = getPlayerChunk(outputBuffer, outputBufferDacTime, frames);
if (!result)
{
static utils::logging::TimeConditional cond(1s);
LOG(DEBUG, LOG_TAG) << cond << "Failed to get chunk, returning silence\n";
getSilentPlayerChunk(outputBuffer, frames);
}
return result;
}

View file

@ -48,8 +48,17 @@ public:
/// Get PCM data, which will be played out in "outputBufferDacTime" time
/// frame = (num_channels) * (1 sample in bytes) = (2 channels) * (2 bytes (16 bits) per sample) = 4 bytes (32 bits)
/// @param[out] outputBuffer the buffer to be filled with PCM data
/// @param outputBufferDacTime the duration until the PCM chunk will be audible
/// @param frames the number of requested frames to be copied into outputBuffer
/// @return true if a chunk was available and successfully copied to outputBuffer
bool getPlayerChunk(void* outputBuffer, const chronos::usec& outputBufferDacTime, uint32_t frames);
/// Try to get a player chunk and fill the buffer with silence if it fails
/// @sa getPlayerChunk
/// @return true if a chunk was available and successfully copied to outputBuffer, else false and outputBuffer is filled with silence
bool getPlayerChunkOrSilence(void* outputBuffer, const chronos::usec& outputBufferDacTime, uint32_t frames);
/// "Server buffer": playout latency, e.g. 1000ms
void setBufferLen(size_t bufferLenMs);