Still confused about ALSA buffer sizes and their effect upon latency.
authorbruceperens <bruceperens@01035d8c-6547-0410-b346-abe4f91aad63>
Thu, 13 Mar 2014 22:45:48 +0000 (22:45 +0000)
committerbruceperens <bruceperens@01035d8c-6547-0410-b346-abe4f91aad63>
Thu, 13 Mar 2014 22:45:48 +0000 (22:45 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@1440 01035d8c-6547-0410-b346-abe4f91aad63

freedv-server/source/platform/linux/audio_in_alsa.cpp
freedv-server/source/platform/linux/audio_out_alsa.cpp

index 9c7741b4a41f0966ce492ff15a5146eb1214bb7a..1bc555a9d4c5dc7af91fb14d7dce35f293278ba6 100644 (file)
@@ -60,7 +60,7 @@ namespace FreeDV {
      1,
      SampleRate,
      (int)ceil(((double)SampleRate / 1000.0) * MinimumFrameDuration / 2),
-     (int)ceil(((double)SampleRate / 1000.0) * MaximumFrameDuration * 2));
+     (int)ceil(((double)SampleRate / 1000.0) * MaximumFrameDuration));
 
     snd_pcm_start(handle);
   }
@@ -80,10 +80,9 @@ namespace FreeDV {
     started = true;
     if ( result == -EPIPE ) {
       snd_pcm_recover(handle, result, 1);
-      result = snd_pcm_readi(handle, array, length);
+      snd_pcm_start(handle);
       std::cerr << "ALSA input \"" << parameters << "\": read underrun." << std::endl;
-      if ( result == -EPIPE )
-        return 0;
+      return 0;
     }
     if ( result >= 0 ) {
       return result;
@@ -109,15 +108,17 @@ namespace FreeDV {
   std::size_t
   AudioInALSA::ready()
   {
-    static const int period_size = (int)ceil(
+    static const int min_frame_size = (int)ceil(
      ((double)SampleRate * 1000.0) * MinimumFrameDuration);
 
     snd_pcm_sframes_t  available = 0;
     snd_pcm_sframes_t  delay = 0;
     int                        error;
 
-    if ( !started )
-      return period_size;
+    if ( !started ) {
+      snd_pcm_start(handle);
+      return min_frame_size;
+    }
 
     error = snd_pcm_avail_delay(handle, &available, &delay);
 
@@ -127,16 +128,16 @@ namespace FreeDV {
     if ( delay >= overlong_delay && available > 0 ) {
       snd_pcm_drop(handle);
       snd_pcm_prepare(handle);
-      started = false;
+      snd_pcm_start(handle);
 
       const double seconds = (double)delay / (double)SampleRate;
 
       error = snd_pcm_avail_delay(handle, &available, &delay);
 
       std::cerr << "ALSA input \"" << parameters << "\": overlong delay, dropped "
-       << seconds << " seconds of queued audio samples." << std::endl;
+       << seconds << " seconds of input." << std::endl;
 
-      return 0;
+      return min_frame_size / 2;
     }
 
     if ( error == -EPIPE ) {
index 3cf78946a31998b0991abff5914f65ad5708e155..8600c5448087c7fa81e0ff01df3e781a11fbb475 100644 (file)
@@ -17,7 +17,7 @@ namespace FreeDV {
   private:
     char * const       parameters;
     snd_pcm_t *                handle;
-    std::size_t                period_size;
+    std::size_t                min_frame_size;
     bool               started;
 
     void
@@ -49,7 +49,7 @@ namespace FreeDV {
 
   AudioOutALSA::AudioOutALSA(const char * p)
   : AudioOutput("alsa", p), parameters(strdup(p)),
-    period_size(
+    min_frame_size(
      (int)ceil(((double)SampleRate / 1000.0) * MinimumFrameDuration)),
     started(false)
   {
@@ -61,8 +61,9 @@ namespace FreeDV {
      SND_PCM_ACCESS_RW_INTERLEAVED,
      1,
      SampleRate,
-     period_size / 2,
-     (int)ceil(((double)SampleRate / 1000.0) * MaximumFrameDuration));
+     min_frame_size / 2,
+     min_frame_size * 8);
+    snd_pcm_pause(handle, 1);
   }
 
   AudioOutALSA::~AudioOutALSA()
@@ -112,16 +113,27 @@ namespace FreeDV {
     int                        error;
 
     if ( !started )
-      return period_size * 2;
+      return min_frame_size;
 
     error = snd_pcm_avail_delay(handle, &available, &delay);
+    if ( delay > (((double)SampleRate / 1000.0) * MaximumFrameDuration) ) {
+      const double seconds = (double)delay / (double)SampleRate;
+
+      std::cerr << "ALSA output \"" << parameters
+       << "\": overlong delay, dropped  "
+       << seconds << " seconds of output." << std::endl;
+      snd_pcm_drop(handle);
+      snd_pcm_prepare(handle);
+      started = false;
+      return 0;
+    }
 
     if ( error == -EPIPE ) {
       std::cerr << "ALSA output \"" << parameters << "\": ready underrun." << std::endl;
       snd_pcm_recover(handle, error, 1);
       snd_pcm_pause(handle, 1);
       started = false;
-      return (int)ceil(((double)SampleRate / 1000.0) * MinimumFrameDuration);
+      return min_frame_size;
 
       if ( error < 0 )
         return 0;