[commit] r2201 - adopt latest pulse audio driver from Scratch

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[commit] r2201 - adopt latest pulse audio driver from Scratch

commits-3
 
Author: piumarta
Date: 2010-04-13 07:51:56 -0700 (Tue, 13 Apr 2010)
New Revision: 2201

Modified:
   trunk/platforms/unix/vm-sound-pulse/sqUnixSoundPulseAudio.c
Log:
adopt latest pulse audio driver from Scratch

Modified: trunk/platforms/unix/vm-sound-pulse/sqUnixSoundPulseAudio.c
===================================================================
--- trunk/platforms/unix/vm-sound-pulse/sqUnixSoundPulseAudio.c 2010-04-12 23:53:14 UTC (rev 2200)
+++ trunk/platforms/unix/vm-sound-pulse/sqUnixSoundPulseAudio.c 2010-04-13 14:51:56 UTC (rev 2201)
@@ -2,7 +2,7 @@
  *
  * Author: Derek O'Connell <[hidden email]>
  *
- *   Copyright (C) 2009 by Derek O'Connel
+ *   Copyright (C) 2009--2010 by Derek O'Connell
  *   All rights reserved.
  *  
  *   This file is part of Unix Squeak.
@@ -25,7 +25,7 @@
  *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  *   DEALINGS IN THE SOFTWARE.
  *
- * Last edited: 2009-09-14 14:15:05 by piumarta on ubuntu.piumarta.com
+ * Last edited: 2010-04-13 07:45:37 by piumarta on ubuntu
  */
 
 /* ========== */
@@ -150,8 +150,6 @@
  int bytesPerFrame;
 
  /* PULSE, Simple API parameters */
- pa_stream_direction_t dir;
- const char *stream_name;
  pa_simple *pa_conn;
   pa_sample_spec pa_spec;
  } audioIO_t;
@@ -327,13 +325,6 @@
  fprintf(stderr, "%0.0f usec    \r", (float)latency);
 }
 
-/*
-static int bytesPerChannel(audioIO_t *audioIO) {
- if ( PA_SAMPLE_S16LE == audioIO->rate) return SAMPLE_RATE_8KHZ;
- PA_SAMPLE_S16LE
-}
-*/
-
 /* ================================== Signal Ops */
 
 static void sigWait(gen_sig_t *sig) {
@@ -446,20 +437,12 @@
 }
 
 static int ioAllocBuffers(audioIO_t *audioIO, int frameCount) {
- int maxBytes;
  int i;
 
- /* NTS: should take audioIO->bytesPerFrame into account...
- and that depends on stereo or not. Revisit at later date.
- maxBytes = frameCount * audioIO->bytesPerFrame;
- */
+ /* Not preserving buffers when play/record stopped */
+ /* Choosing memory conservation over speed of starting play/record */
 
- if (audioIO->buffersAllocated)
- if (audioOut.maxSamples == frameCount)
- return true;
- else
- ioFreeBuffers(audioIO);
-
+ ioFreeBuffers(audioIO);
  audioIO->maxSamples = frameCount;
  audioIO->maxBytes   = audioIO->maxSamples * audioIO->bytesPerFrame;
  audioIO->maxWords   = audioIO->maxBytes >> 1;
@@ -468,8 +451,6 @@
  audioIO->buffer[i].isFree = true;
  }
  audioIO->buffersAllocated = true;
-
- return true;
 }
 
 static int ioIsFull(audioIO_t *audioIO) {
@@ -584,10 +565,6 @@
 /* if ((rc = snd_pcm_writei(audioOut.alsaHandle, buffer, frames)) < frames) {
 */
         
-        /* Experiment to see if draining removes delay, result: undecided, seems slightly better */
-       pa_simple_drain(audioOut.pa_conn, &rc);
-
-        
         /* PA: Have to assume for now that all frames were written */
         if (pa_simple_write(audioOut.pa_conn, buffer, (size_t) (frames * audioOut.bytesPerFrame), &rc) < 0) {
           fprintf(stderr, __FILE__": pa_simple_write() failed: %s\n", pa_strerror(rc));
@@ -702,7 +679,7 @@
  }
 */
 
- /* PA: Endian swap is N810 left-over... */
+ /* PA: Endian swap may not be needed... */
 
  /* Endian Swap (rc = frames = Word Count in this case) */
 /*
@@ -735,93 +712,20 @@
 }
 
 
-/* ================================== OPEN/CLOSE PA */
-
-static int closePulseAudio(audioIO_t *audioIO) {
- int rc;
-
-  if (!audioIO->pa_conn)
-   return true;
-
-  if (PA_STREAM_PLAYBACK == audioIO->dir)
- if (pa_simple_drain(audioIO->pa_conn, &rc) < 0)
- fprintf(stderr, __FILE__": pa_simple_drain() failed: %s\n", pa_strerror(rc));
-
-  pa_simple_free(audioIO->pa_conn);
-  audioIO->pa_conn = NULL;
-  
- printf("closePulseAudio((): %s\n", audioIO->dbgName);
-  
- return true;
-}
-
-static int openPulseAudio(audioIO_t *audioIO, int samplesPerSec, int stereo) {
- int rc;
- int channels;
-
-/*
-DBGMSG(">pa_Open()");
-#ifdef DBG
-printf("\tframeCount: %d, samplesPerSec: %d, stereo: %d\n", frameCount, samplesPerSec, stereo, semaIndex);
-#endif
-*/
-
- /* DMOC 090912:
- Connection for playback stream should already have been opened when module loaded so
- now only open if that failed or parameters have changed. Could also avoid buffer
- creation if default frameCount known/agreed.
- */
-
- channels = stereo ? 2 : 1;
-
- /* If already connected then check if same spec */
- if (audioIO->pa_conn)
- if ((audioIO->pa_spec.rate == samplesPerSec) && (audioIO->pa_spec.channels == channels))
- return true;
-
- if (audioIO->pa_conn)
- closePulseAudio(audioIO);
-
-  audioIO->pa_spec.rate = samplesPerSec;
-  audioIO->pa_spec.channels = channels;
-  
- if (!(audioIO->pa_conn = pa_simple_new(NULL, "Scratch", audioIO->dir, NULL, audioIO->stream_name, &audioIO->pa_spec, NULL, NULL, &rc))) {
- fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(rc));
- return false;
- }
-
-/*
-  if (PA_STREAM_PLAYBACK == audioIO->dir)
-  pa_simple_drain(audioIO->pa_conn, &rc);
-*/
- printf("openPulseAudio() %s, rate: %i, chans: %i\n", audioIO->dbgName, samplesPerSec, channels);
-  
- return true;
-}
-
 /* ================================== IO INIT */
 
-/* ioInit() called when module loaded...
- N810: Threads pre-started and held on semaphore
-  PA: Connection opened for audio-out with default settings
-*/
-
 static int ioInit() {
- int rc;
-
  if (initDone) return true;
  initDone = true;
 
- /* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */
- /* >>>>>>>>>>>>> AUDIO OUT >>>>>>>>>>>> */
- /* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */
+ /* AUDIO OUT */
 
 /* NOT USED >>> */
  audioOut.dbgName = "play";
  audioOut.device = "pa-simple";
 /* <<< */
 
- audioOut.open = false; /* Squeak state */
+ audioOut.open = false;
 
  audioOut.maxSamples = 0;
  audioOut.maxWords = 0;
@@ -856,35 +760,19 @@
  audioOut.rateID = 0;
  audioOut.bytesPerFrame = 4; /* Stereo S16LE */
 
- /* PA Specific (defaults for Scratch/Squeak) */
- audioOut.dir = PA_STREAM_PLAYBACK;
-  audioOut.stream_name = "playback";
-  audioOut.pa_spec.format = PA_SAMPLE_S16LE; /* Squeak default */
-  audioOut.pa_spec.rate = 0;
-  audioOut.pa_spec.channels = 0;
- audioOut.pa_conn = NULL;
+ audioOut.pa_conn = null;
 
- /* Open PA connection here to avoid delays later on */
- openPulseAudio(&audioOut, 22050, true);
-
- /* Allocate buffers here to avoid delays later on */
- /* Hmmm, tricky because varies... so not doing it atm */
-/* ioAllocBuffers(&audioOut, frameCount);
-*/
-
  ioThreadStart(&audioOut);
 
+ /* AUDIO IN */
 
- /* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */
- /* >>>>>>>>>>>>> AUDIO IN >>>>>>>>>>>>> */
- /* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */
+ audioIn.dbgName = "rec";
 
 /* NOT USED >>> */
- audioIn.dbgName = "rec";
  audioIn.device = "pa-simple";
 /* <<< */
 
- audioIn.open = false; /* Squeak state */
+ audioIn.open = false;
 
  audioIn.maxSamples = 0;
  audioIn.maxWords = 0;
@@ -919,16 +807,8 @@
  audioIn.rateID = 0;
  audioIn.bytesPerFrame = 2; /* Mono S16LE */
 
- /* PA Specific */
- audioIn.dir = PA_STREAM_RECORD;
-  audioIn.stream_name = "record";
-  audioIn.pa_spec.format = PA_SAMPLE_S16LE; /* Squeak default */
-  audioIn.pa_spec.rate = 0;
-  audioIn.pa_spec.channels = 0;
- audioIn.pa_conn = NULL;
+ audioIn.pa_conn = null;
 
- /* DMOC 090912: Not attempting to open default PA connection for recording */
-
  ioThreadStart(&audioIn);
 }
 
@@ -950,6 +830,7 @@
  return 0; /* or maxBytes? */
 }
 
+
 static sqInt sound_PlaySamplesFromAtLength(int frameCount, int arrayIndex, int startIndex) {
  unsigned int bufferNext, samples, sampleBytes;
 
@@ -971,10 +852,9 @@
  return 0; /* or maxBytes? */
 }
 
+
 static sqInt sound_Start(int frameCount, int samplesPerSec, int stereo, int semaIndex) {
  int rc;
- int channels;
- int reopen;
 
 DBGMSG(">sound_Start()");
 
@@ -984,23 +864,33 @@
 
  if (audioOut.open) return true;
 
- if (!openPulseAudio(&audioOut, samplesPerSec, stereo)) {
- success(false);
- return false;
+  audioOut.pa_spec.format = PA_SAMPLE_S16LE;
+  audioOut.pa_spec.rate = samplesPerSec; /* rate(SAMPLE_RATE_22_05KHZ) for Squeak */
+  audioOut.pa_spec.channels = stereo ? 2 : 1;
+  audioOut.pa_conn = NULL;
+
+ /* Create a new playback stream */
+ if (!(audioOut.pa_conn = pa_simple_new(NULL, "Scratch", PA_STREAM_PLAYBACK, NULL, "playback", &audioOut.pa_spec, NULL, NULL, &rc))) {
+ fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(rc));
+ success(false);
+ return false;
  }
-
- printf("sound_Start() frameCount >> 1: %i\n", frameCount >> 1);
   
- ioAllocBuffers(&audioOut, frameCount >> 1);
+ ioAllocBuffers(&audioOut, frameCount);
+ audioOut.bufferCount = audioOut.maxBuffers; /* Has to be reset everytime */
 
- /* EVERY TIME: Initialise buffer count, ie, Squeak-ready buffers (max for audio-out) */
- audioOut.bufferCount = audioOut.maxBuffers;
-
  audioOut.sqSemaphore = semaIndex;
+
  audioOut.open = true;
 
  sigSignal(&audioOut.sigRun);
 
+ /* error possibly left over from dsp-protocol.c code */
+ /* dsp-protocol.c in current ALSA not capturing EINTR/EAGAIN */
+ /* EINTR/EAGAIN from dsp-protocol.c not raised up to ALSA so not caught by ALSA */
+ /* Clearing errno here to see if Squeak can continue regardless */
+ errno = 0;
+
 DBGMSG("<sound_Start()");
  return true;
 }
@@ -1018,10 +908,16 @@
 
  ioThreadStall(&audioOut);
 
- closePulseAudio(&audioOut);
+ if (pa_simple_drain(audioOut.pa_conn, &rc) < 0) {
+ fprintf(stderr, __FILE__": pa_simple_drain() failed: %s\n", pa_strerror(rc));
+ }
+
+  if (NULL != audioOut.pa_conn)
+     pa_simple_free(audioOut.pa_conn);
 
  ioFreeBuffers(&audioOut);
 
+ audioOut.pa_conn = NULL;
  audioOut.sqSemaphore = 0;
 
 DBGMSG("<sound_Stop()");
@@ -1034,30 +930,57 @@
 
 static sqInt sound_StartRecording(int desiredSamplesPerSec, int stereo, int semaIndex) {
  int rc;
+ pa_buffer_attr pa_buffer_metrics; /* For recording */
 
 DBGMSG(">sound_StartRecording()");
 
  if (audioIn.open) return true;
 
+ audioIn.pa_spec.format = PA_SAMPLE_S16LE;
+ audioIn.pa_spec.rate = desiredSamplesPerSec;
+ audioIn.pa_spec.channels = stereo ? 2 : 1;
+ audioIn.pa_conn = NULL;
+    
+ pa_buffer_metrics.maxlength = (uint32_t) -1;
+ pa_buffer_metrics.tlength = (uint32_t) -1; /* playback only */
+ pa_buffer_metrics.prebuf = (uint32_t) -1; /* playback only */
+ pa_buffer_metrics.minreq = (uint32_t) -1; /* playback only */
+ pa_buffer_metrics.fragsize = pa_usec_to_bytes(20*1000, &audioIn.pa_spec);
+
+ /* Create the recording stream */
+ if (!(audioIn.pa_conn = pa_simple_new( NULL,
+ "Scratch",
+ PA_STREAM_RECORD,
+ NULL,
+ "record",
+ &audioIn.pa_spec,
+ NULL,
+ &pa_buffer_metrics,
+ &rc)))
+ {
+ fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(rc));
+ success(false);
+ return false;
+ }
+
   /* Only rate supported on the N810 (atm) is 8000 */
 /*  
-  desiredSamplesPerSec = 8000;
+  audioIn.alsaRate = 8000;
 */
   
- if (!openPulseAudio(&audioIn, desiredSamplesPerSec, stereo)) {
- success(false);
- return false;
- }
-
- /* Buffers will be filled before signalling Squeak. So rate & buffer size determined signalling freq... */
   /* 20Hz update freq for Squeak sounds reasonable, so... */
   audioIn.maxSamples = audioIn.pa_spec.rate / 20;
 
- ioAllocBuffers(&audioIn, audioIn.maxSamples);
-
- /* EVERY TIME: Initialise buffer count, ie, Squeak-ready buffers (ZERO for audio-in) */
- audioIn.bufferCount = 0;
+  /* Use a buffer large enough to hold one period (assuming 2 bytes/sample) */
+/*  
+  audioIn.alsaBufferSize = audioIn.maxSamples * 2 * audioIn.pa_spec.channels;
+  audioIn.alsaBuffer = (char *) malloc(audioIn.alsaBufferSize);
+*/
 
+ /* Buffers will be filled before signalling Squeak. So rate & buffer size determined signalling freq... */
+ ioAllocBuffers(&audioIn, audioIn.pa_spec.rate / 20 ); /* for Sq signalling rate of 20Hz */
+ audioIn.bufferCount = 0; /* Has to be reset everytime */
+
  audioIn.sqSemaphore = semaIndex;
 
  audioIn.open = true;
@@ -1078,7 +1001,7 @@
 
  ioThreadStall(&audioIn);
 
- closePulseAudio(&audioIn);  
+  pa_simple_free(audioIn.pa_conn);
   
  ioFreeBuffers(&audioIn);
 
@@ -1189,7 +1112,7 @@
 
 #include "SqSound.h"
 
-SqSoundDefine(pulse);
+SqSoundDefine(PA);
 
 #include "SqModule.h"
 
@@ -1235,12 +1158,13 @@
 }
 
 static void *sound_makeInterface(void) {
-//#ifdef NEWSIG
+/*#ifdef NEWSIG
 //  sigalrm_save(); // DMOC: Being here assumes old handler same for run duration! Same for sigio handler.
 //#else
 // DMOC: Rethink: Signal captured once, preserved and restored when/where necessary?
 //  sigio_save();
 //#endif
+*/
 
 #ifdef USE_RESOURCE_MANAGER
 printf("USE_RESOURCE_MANAGER\n");
@@ -1248,7 +1172,7 @@
 
  ioInit();
 
-  return &sound_pulse_itf;
+  return &sound_PA_itf;
 }
 
 SqModuleDefine(sound, pulse);