{
bool restart = false;
- (this->*m_outputStageFn)();
+ (this->*m_outputStageFn)(true);
/* if we have enough room in the buffer */
if (m_buffer.Free() >= m_frameSize)
}
}
-void CSoftAE::MixSounds(float *buffer, unsigned int samples)
+unsigned int CSoftAE::MixSounds(float *buffer, unsigned int samples)
{
SoundStateList::iterator itt;
+ unsigned int mixed = 0;
CSingleLock lock(m_soundSampleLock);
for (itt = m_playing_sounds.begin(); itt != m_playing_sounds.end(); )
{
ss->samples += mixSamples;
++itt;
+ ++mixed;
}
+ return mixed;
}
-void CSoftAE::FinalizeSamples(float *buffer, unsigned int samples)
+bool CSoftAE::FinalizeSamples(float *buffer, unsigned int samples, bool hasAudio)
{
if (m_soundMode != AE_SOUND_OFF)
- MixSounds(buffer, samples);
+ hasAudio |= MixSounds(buffer, samples) > 0;
+
+ /* no need to process if we don't have audio (buffer is memset to 0) */
+ if (!hasAudio)
+ return false;
if (m_muted)
{
memset(buffer, 0, samples * sizeof(float));
- return;
+ return false;
}
/* deamplify */
/* if there were no samples outside of the range, dont clamp the buffer */
if (!clamp)
- return;
+ return true;
CLog::Log(LOGDEBUG, "CSoftAE::FinalizeSamples - Clamping buffer of %d samples", samples);
CAEUtil::ClampArray(buffer, samples);
+ return true;
}
-void CSoftAE::RunOutputStage()
+int CSoftAE::RunOutputStage(bool hasAudio)
{
const unsigned int needSamples = m_sinkFormat.m_frames * m_sinkFormat.m_channelLayout.Count();
const size_t needBytes = needSamples * sizeof(float);
if (m_buffer.Used() < needBytes)
- return;
+ return 0;
void *data = m_buffer.Raw(needBytes);
- FinalizeSamples((float*)data, needSamples);
+ hasAudio = FinalizeSamples((float*)data, needSamples, hasAudio);
int wroteFrames;
if (m_convertFn)
}
m_buffer.Shift(NULL, wroteFrames * m_sinkFormat.m_channelLayout.Count() * sizeof(float));
+ return wroteFrames;
}
-void CSoftAE::RunRawOutputStage()
+int CSoftAE::RunRawOutputStage(bool hasAudio)
{
if(m_buffer.Used() < m_sinkBlockSize)
- return;
+ return 0;
void *data = m_buffer.Raw(m_sinkBlockSize);
}
m_buffer.Shift(NULL, wroteFrames * m_sinkFormat.m_frameSize);
+ return wroteFrames;
}
-void CSoftAE::RunTranscodeStage()
+int CSoftAE::RunTranscodeStage(bool hasAudio)
{
/* if we dont have enough samples to encode yet, return */
unsigned int block = m_encoderFormat.m_frames * m_encoderFormat.m_frameSize;
unsigned int sinkBlock = m_sinkFormat.m_frames * m_sinkFormat.m_frameSize;
+ int encodedFrames = 0;
if (m_buffer.Used() >= block && m_encodedBuffer.Used() < sinkBlock * 2)
{
- FinalizeSamples((float*)m_buffer.Raw(block), m_encoderFormat.m_frameSamples);
+ hasAudio = FinalizeSamples((float*)m_buffer.Raw(block), m_encoderFormat.m_frameSamples, hasAudio);
void *buffer;
if (m_convertFn)
else
buffer = m_buffer.Raw(block);
- int encodedFrames = m_encoder->Encode((float*)buffer, m_encoderFormat.m_frames);
+ encodedFrames = m_encoder->Encode((float*)buffer, m_encoderFormat.m_frames);
m_buffer.Shift(NULL, encodedFrames * m_encoderFormat.m_frameSize);
uint8_t *packet;
m_encodedBuffer.Shift(NULL, wroteFrames * m_sinkFormat.m_frameSize);
}
+ return encodedFrames;
}
unsigned int CSoftAE::RunRawStreamStage(unsigned int channelCount, void *out, bool &restart)
void AllocateConvIfNeeded(size_t convertedSize);
/* thread run stages */
- void MixSounds (float *buffer, unsigned int samples);
- void FinalizeSamples (float *buffer, unsigned int samples);
+
+ /*! \brief Mix UI sounds into the current stream.
+ \param buffer the buffer to mix into.
+ \param samples the number of samples in the buffer.
+ \return the number of sounds mixed into the buffer.
+ */
+ unsigned int MixSounds (float *buffer, unsigned int samples);
+
+ /*! \brief Finalize samples ready for sending to the output device.
+ Mixes in any UI sounds, applies volume adjustment, and clamps to [-1,1].
+ \param buffer the audio data.
+ \param samples the number of samples in the buffer.
+ \param hasAudio whether we have audio from a stream (true) or silence (false)
+ \return true if we have audio to output, false if we have only silence.
+ */
+ bool FinalizeSamples (float *buffer, unsigned int samples, bool hasAudio);
CSoftAEStream *m_masterStream;
- void (CSoftAE::*m_outputStageFn)();
- void RunOutputStage ();
- void RunRawOutputStage();
- void RunTranscodeStage();
+ /*! \brief Run the output stage on the audio.
+ Prepares streamed data, mixes in any UI sounds, converts to a format suitable
+ for the sink, then outputs to the sink.
+ \param hasAudio whether or not we have audio (true) or silence (false).
+ \return the number of samples sent to the sink.
+ */
+ int (CSoftAE::*m_outputStageFn)(bool);
+ int RunOutputStage (bool hasAudio);
+ int RunRawOutputStage(bool hasAudio);
+ int RunTranscodeStage(bool hasAudio);
unsigned int (CSoftAE::*m_streamStageFn)(unsigned int channelCount, void *out, bool &restart);
unsigned int RunRawStreamStage (unsigned int channelCount, void *out, bool &restart);