[SoftAE] change RunOutputStage to take in a boolean for audio (vs silence) and to...
authorJonathan Marshall <jmarshall@never.you.mind>
Mon, 9 Jul 2012 06:45:09 +0000 (18:45 +1200)
committerCory Fields <theuni-nospam-@xbmc.org>
Wed, 11 Jul 2012 03:37:52 +0000 (23:37 -0400)
xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp
xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.h

index 8c7eaa2..35c54f1 100644 (file)
@@ -858,7 +858,7 @@ void CSoftAE::Run()
   {
     bool restart = false;
 
-    (this->*m_outputStageFn)();
+    (this->*m_outputStageFn)(true);
 
     /* if we have enough room in the buffer */
     if (m_buffer.Free() >= m_frameSize)
@@ -895,10 +895,11 @@ void CSoftAE::AllocateConvIfNeeded(size_t convertedSize)
   }
 }
 
-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(); )
   {
@@ -926,18 +927,24 @@ void CSoftAE::MixSounds(float *buffer, unsigned int samples)
     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 */
@@ -973,21 +980,22 @@ void CSoftAE::FinalizeSamples(float *buffer, unsigned int samples)
 
   /* 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)
@@ -1009,12 +1017,13 @@ void CSoftAE::RunOutputStage()
   }
 
   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);
 
@@ -1046,17 +1055,19 @@ void CSoftAE::RunRawOutputStage()
   }
 
   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)
@@ -1078,7 +1089,7 @@ void CSoftAE::RunTranscodeStage()
     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;
@@ -1106,6 +1117,7 @@ void CSoftAE::RunTranscodeStage()
 
     m_encodedBuffer.Shift(NULL, wroteFrames * m_sinkFormat.m_frameSize);
   }
+  return encodedFrames;
 }
 
 unsigned int CSoftAE::RunRawStreamStage(unsigned int channelCount, void *out, bool &restart)
index 6922f61..09f9a31 100644 (file)
@@ -195,15 +195,35 @@ private:
   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);