[Vm-dev] [commit] r2201 - adopt latest pulse audio driver from
Scratch
commits at squeakvm.org
commits at squeakvm.org
Tue Apr 13 14:51:56 UTC 2010
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 <doc at doconnel.f9.co.uk>
*
- * 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);
More information about the Vm-dev
mailing list