]> git.rkrishnan.org Git - pihpsdr.git/commitdiff
overhaul of audio modules
authorc vw <dl1ycf@darc.de>
Thu, 3 Jun 2021 14:52:39 +0000 (16:52 +0200)
committerc vw <dl1ycf@darc.de>
Thu, 3 Jun 2021 14:52:39 +0000 (16:52 +0200)
audio.c
portaudio.c
pulseaudio.c

diff --git a/audio.c b/audio.c
index 9c10a46283e240f94fdb0e1740786fc6624f6ff3..d2fc257bf614b29878f004c6df656120ee2801d6 100644 (file)
--- a/audio.c
+++ b/audio.c
@@ -62,11 +62,6 @@ static const int cw_high_water = 1152;                // high water mark for CW
 #include "transmitter.h"
 #include "audio.h"
 #include "mode.h"
-#include "new_protocol.h"
-#include "old_protocol.h"
-#ifdef SOAPYSDR
-#include "soapy_protocol.h"
-#endif
 #include "vfo.h"
 
 int audio = 0;
@@ -601,30 +596,23 @@ g_print("%s: snd_pcm_start\n", __FUNCTION__);
             sample=float_buffer[i];
             break;
         }
-        switch(protocol) {
-          case ORIGINAL_PROTOCOL:
-          case NEW_PROTOCOL:
-#ifdef SOAPYSDR
-          case SOAPYSDR_PROTOCOL:
-#endif
-           //
-           // put sample into ring buffer
-           //
-           if (mic_ring_buffer != NULL) {
-              // the "existence" of the ring buffer is now guaranteed for 1 msec,
-             // see audio_close_input().
-             newpt=mic_ring_write_pt +1;
-             if (newpt == MICRINGLEN) newpt=0;
-             if (newpt != mic_ring_read_pt) {
-               // buffer space available, do the write
-               mic_ring_buffer[mic_ring_write_pt]=sample;
-               // atomic update of mic_ring_write_pt
-               mic_ring_write_pt=newpt;
-             }
-            }
-            break;
-          default:
-            break;
+       //
+       // put sample into ring buffer
+       // Note check on the mic ring buffer is not necessary
+       // since audio_close_input() waits for this thread to
+       // complete.
+       //
+       if (mic_ring_buffer != NULL) {
+          // do not increase mic_ring_write_pt *here* since it must
+         // not assume an illegal value at any time
+         newpt=mic_ring_write_pt +1;
+         if (newpt == MICRINGLEN) newpt=0;
+         if (newpt != mic_ring_read_pt) {
+           // buffer space available, do the write
+           mic_ring_buffer[mic_ring_write_pt]=sample;
+           // atomic update of mic_ring_write_pt
+           mic_ring_write_pt=newpt;
+         }
         }
       }
     }
index 2bb66441b0d027c7c775850fb8c4058a4d13153a..fcad0577639c3eca4377b96461d715c22fe0a55d 100644 (file)
 #include <sched.h>
 #include <semaphore.h>
 
-#include "new_protocol.h"
-#include "old_protocol.h"
 #include "radio.h"
 #include "receiver.h"
 #include "mode.h"
 #include "portaudio.h"
 #include "audio.h"
-#ifdef SOAPYSDR
-#include "soapy_protocol.h"
-#endif
 
 static PaStream *record_handle=NULL;
 
index 59a7449ccddbe52c3ef27527c255b02b1861d44e..58318a1c465a05ca93c9b3324ae9af5f46fa5bfe 100644 (file)
@@ -8,12 +8,16 @@
 #include "transmitter.h"
 #include "audio.h"
 #include "mode.h"
-#include "new_protocol.h"
-#include "old_protocol.h"
 #include "vfo.h"
-#ifdef SOAPYSDR
-#include "soapy_protocol.h"
-#endif
+
+//
+// Used fixed buffer sizes.
+// The extremely large standard RX buffer size (2048)
+// does no good when combined with pulseaudio's internal
+// buffering
+//
+static const int out_buffer_size = 512;
+static const int mic_buffer_size = 512;
 
 int n_input_devices;
 AUDIO_DEVICE input_devices[MAX_AUDIO_DEVICES];
@@ -40,7 +44,6 @@ static float *local_microphone_buffer=NULL;
 static GThread *mic_read_thread_id=0;
 static gboolean running;
 
-gint local_microphone_buffer_size=720;
 static GMutex audio_mutex;
 
 static void source_list_cb(pa_context *context,const pa_source_info *s,int eol,void *data) {
@@ -133,6 +136,13 @@ int audio_open_output(RECEIVER *rx) {
   pa_sample_spec sample_spec;
   int err;
 
+  pa_buffer_attr attr;
+  attr.maxlength = (uint32_t) -1;
+  attr.tlength = (uint32_t) -1;
+  attr.prebuf = (uint32_t) 3072;  // about 64 msec "pre-filling"
+  attr.minreq = (uint32_t) -1;
+  attr.fragsize = (uint32_t) -1;
+
   if(rx->audio_name==NULL) {
     result=-1;
   } else {
@@ -145,21 +155,21 @@ int audio_open_output(RECEIVER *rx) {
     char stream_id[16];
     sprintf(stream_id,"RX-%d",rx->id);
 
-    rx->playstream=pa_simple_new(NULL,               // Use the default server.
-                    "piHPSDR",           // Our application's name.
+    rx->playstream=pa_simple_new(NULL,  // Use the default server.
+                    "piHPSDR",          // Our application's name.
                     PA_STREAM_PLAYBACK,
                     rx->audio_name,
-                    stream_id,            // Description of our stream.
-                    &sample_spec,                // Our sample format.
+                    stream_id,          // Description of our stream.
+                    &sample_spec,       // Our sample format.
                     NULL,               // Use default channel map
-                    NULL,               // Use default buffering attributes.
-                    &err               // error code if returns NULL
+                    &attr,              // use our "prebuf" value
+                    &err                // error code if returns NULL
                     );
 
     if(rx->playstream!=NULL) {
       rx->local_audio_buffer_offset=0;
-      rx->local_audio_buffer=g_new0(float,2*rx->local_audio_buffer_size);
-      g_print("%s: allocated local_audio_buffer %p size %ld bytes\n",__FUNCTION__,rx->local_audio_buffer,2*rx->local_audio_buffer_size*sizeof(float));
+      rx->local_audio_buffer=g_new0(float,2*out_buffer_size);
+      g_print("%s: allocated local_audio_buffer %p size %ld bytes\n",__FUNCTION__,rx->local_audio_buffer,2*out_buffer_size*sizeof(float));
     } else {
       result=-1;
       g_print("%s: pa-simple_new failed: err=%d\n",__FUNCTION__,err);
@@ -182,14 +192,14 @@ static void *mic_read_thread(gpointer arg) {
     //
     rc=pa_simple_read(microphone_stream,
             local_microphone_buffer,
-            local_microphone_buffer_size*sizeof(float),
+            mic_buffer_size*sizeof(float),
             &err);
     if(rc<0) {
       running=FALSE;
-      g_print("%s: returned %d error=%d (%s)\n",__FUNCTION__,rc,err,pa_strerror(err));
+      g_print("%s: simple_read returned %d error=%d (%s)\n",__FUNCTION__,rc,err,pa_strerror(err));
     } else {
       int newpt;
-      for(gint i=0;i<local_microphone_buffer_size;i++) {
+      for(gint i=0;i<mic_buffer_size;i++) {
         gfloat sample=local_microphone_buffer[i];
         //
         // put sample into ring buffer
@@ -232,21 +242,20 @@ int audio_open_input() {
   sample_spec.channels=1;
   sample_spec.format=PA_SAMPLE_FLOAT32NE;
 
-  microphone_stream=pa_simple_new(NULL,               // Use the default server.
-                  "piHPSDR",           // Our application's name.
+  microphone_stream=pa_simple_new(NULL,        // Use the default server.
+                  "piHPSDR",                   // Our application's name.
                   PA_STREAM_RECORD,
                   transmitter->microphone_name,
-                  "TX",            // Description of our stream.
+                  "TX",                        // Description of our stream.
                   &sample_spec,                // Our sample format.
-                  NULL,               // Use default channel map
-                  //NULL,
-                  &attr,               // Use default buffering attributes.
-                  NULL               // Ignore error code.
+                  NULL,                        // Use default channel map
+                  &attr,                       // Use default buffering attributes but set fragsize
+                  NULL                         // Ignore error code.
                   );
 
   if(microphone_stream!=NULL) {
     local_microphone_buffer_offset=0;
-    local_microphone_buffer=g_new0(float,local_microphone_buffer_size);
+    local_microphone_buffer=g_new0(float,mic_buffer_size);
 
     g_print("%s: allocating ring buffer\n",__FUNCTION__);
     mic_ring_buffer=(float *) g_new(float,MICRINGLEN);
@@ -293,7 +302,7 @@ void audio_close_input() {
   g_mutex_lock(&audio_mutex);
 
   if(mic_read_thread_id!=NULL) {
-g_print("audio_close_input: wait for thread to complete\n");
+g_print("%s: wait for mic thread to complete\n", __FUNCTION__);
     //
     // wait for the mic read thread to terminate,
     // then destroy the stream and the buffers
@@ -345,17 +354,22 @@ int cw_audio_write(RECEIVER *rx,float sample) {
 
   g_mutex_lock(&rx->local_audio_mutex);
 
-  if (rx->playstream != NULL && rx->local_audio_buffer != NULL) {  // Note this test must be done "mutex-protected"
+  if (rx->playstream != NULL && rx->local_audio_buffer != NULL) {
+    //
+    // Since this is mutex-protected, we know that both rx->playstream
+    // and rx->local_audio_buffer will not be destroyes until we
+    // are finished here.
+    //
     rx->local_audio_buffer[rx->local_audio_buffer_offset*2]=sample;
     rx->local_audio_buffer[(rx->local_audio_buffer_offset*2)+1]=sample;
     rx->local_audio_buffer_offset++;
-    if(rx->local_audio_buffer_offset>=rx->local_audio_buffer_size) {
+    if(rx->local_audio_buffer_offset>=out_buffer_size) {
       rc=pa_simple_write(rx->playstream,
                          rx->local_audio_buffer,
-                         rx->local_audio_buffer_size*sizeof(float)*2,
+                         out_buffer_size*sizeof(float)*2,
                          &err);
       if(rc!=0) {
-        fprintf(stderr,"cw_audio_write failed err=%d\n",err);
+        g_print("%s: simple_write failed err=%d\n",__FUNCTION__,err);
       }
       rx->local_audio_buffer_offset=0;
     }
@@ -377,17 +391,21 @@ int audio_write(RECEIVER *rx,float left_sample,float right_sample) {
 
   g_mutex_lock(&rx->local_audio_mutex);
 
-  if (rx->playstream != NULL && rx->local_audio_buffer != NULL) {  // Note this test must be done "mutex-protected"
+  if (rx->playstream != NULL && rx->local_audio_buffer != NULL) {
+    //
+    // Since this is mutex-protected, we know that both rx->playstream
+    // and rx->local_audio_buffer will not be destroyes until we
+    // are finished here.
     rx->local_audio_buffer[rx->local_audio_buffer_offset*2]=left_sample;
     rx->local_audio_buffer[(rx->local_audio_buffer_offset*2)+1]=right_sample;
     rx->local_audio_buffer_offset++;
-    if(rx->local_audio_buffer_offset>=rx->local_audio_buffer_size) {
+    if(rx->local_audio_buffer_offset>=out_buffer_size) {
       rc=pa_simple_write(rx->playstream,
                          rx->local_audio_buffer,
-                         rx->local_audio_buffer_size*sizeof(float)*2,
+                         out_buffer_size*sizeof(float)*2,
                          &err);
       if(rc!=0) {
-        fprintf(stderr,"audio_write failed err=%d\n",err);
+        g_print("%s: simple_write failed err=%d\n",__FUNCTION__,err);
       }
       rx->local_audio_buffer_offset=0;
     }