mod_portaudio: update to support multiple io buffers
This commit is contained in:
parent
df43e51ca5
commit
b05965c88d
|
@ -98,41 +98,36 @@ struct private_object {
|
||||||
typedef struct private_object private_t;
|
typedef struct private_object private_t;
|
||||||
|
|
||||||
struct audio_stream {
|
struct audio_stream {
|
||||||
|
/*! Sampling rate */
|
||||||
|
int sample_rate;
|
||||||
|
/*! Buffer packetization (and therefore timing) */
|
||||||
|
int codec_ms;
|
||||||
|
/*! The PA input device */
|
||||||
int indev;
|
int indev;
|
||||||
|
/*! The PA output device */
|
||||||
int outdev;
|
int outdev;
|
||||||
|
/*! The io stream helper to buffer audio */
|
||||||
PABLIO_Stream *stream;
|
PABLIO_Stream *stream;
|
||||||
|
/*! How often to write */
|
||||||
switch_timer_t write_timer;
|
switch_timer_t write_timer;
|
||||||
|
/*! Next stream */
|
||||||
struct audio_stream *next;
|
struct audio_stream *next;
|
||||||
};
|
};
|
||||||
typedef struct audio_stream audio_stream_t;
|
typedef struct audio_stream audio_stream_t;
|
||||||
|
|
||||||
typedef struct _pa_shared_device {
|
typedef struct audio_endpoint {
|
||||||
/*! Sampling rate */
|
/*! Input stream for this endpoint */
|
||||||
int sample_rate;
|
audio_stream_t *in_stream;
|
||||||
/*! */
|
|
||||||
int codec_ms;
|
|
||||||
/*! Device number */
|
|
||||||
int devno;
|
|
||||||
/*! Running stream (if a stream is already running for devno) */
|
|
||||||
audio_stream_t *stream;
|
|
||||||
/*! The actual portaudio device number */
|
|
||||||
/*! It's a shared device after all */
|
|
||||||
switch_mutex_t *mutex;
|
|
||||||
} pa_shared_device_t;
|
|
||||||
|
|
||||||
typedef struct _pa_endpoint {
|
/*! Output stream for this endpoint */
|
||||||
/*! Input device for this endpoint */
|
audio_stream_t *out_stream;
|
||||||
pa_shared_device_t *indev;
|
|
||||||
|
|
||||||
/*! Output device for this endpoint */
|
/*! Channel index within the input stream where we get the audio for this endpoint */
|
||||||
pa_shared_device_t *outdev;
|
|
||||||
|
|
||||||
/*! Channel index within the input device stream */
|
|
||||||
int inchan;
|
int inchan;
|
||||||
|
|
||||||
/*! Channel index within the input device stream */
|
/*! Channel index within the output stream where we get the audio for this endpoint */
|
||||||
int outchan;
|
int outchan;
|
||||||
} pa_endpoint_t;
|
} audio_endpoint_t;
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
int debug;
|
int debug;
|
||||||
|
|
|
@ -83,9 +83,9 @@ static int iblockingIOCallback(const void *inputBuffer, void *outputBuffer,
|
||||||
|
|
||||||
/* This may get called with NULL inputBuffer during initial setup. */
|
/* This may get called with NULL inputBuffer during initial setup. */
|
||||||
if (inputBuffer != NULL) {
|
if (inputBuffer != NULL) {
|
||||||
if (PaUtil_WriteRingBuffer(&data->inFIFO, inputBuffer, numBytes) != numBytes) {
|
if (PaUtil_WriteRingBuffer(&data->inFIFOs[0], inputBuffer, numBytes) != numBytes) {
|
||||||
PaUtil_FlushRingBuffer(&data->inFIFO);
|
PaUtil_FlushRingBuffer(&data->inFIFOs[0]);
|
||||||
PaUtil_WriteRingBuffer(&data->inFIFO, inputBuffer, numBytes);
|
PaUtil_WriteRingBuffer(&data->inFIFOs[0], inputBuffer, numBytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ static int oblockingIOCallback(const void *inputBuffer, void *outputBuffer,
|
||||||
|
|
||||||
if (outputBuffer != NULL) {
|
if (outputBuffer != NULL) {
|
||||||
int i;
|
int i;
|
||||||
int numRead = PaUtil_ReadRingBuffer(&data->outFIFO, outputBuffer, numBytes);
|
int numRead = PaUtil_ReadRingBuffer(&data->outFIFOs[0], outputBuffer, numBytes);
|
||||||
/* Zero out remainder of buffer if we run out of data. */
|
/* Zero out remainder of buffer if we run out of data. */
|
||||||
for (i = numRead; i < numBytes; i++) {
|
for (i = numRead; i < numBytes; i++) {
|
||||||
((char *) outputBuffer)[i] = 0;
|
((char *) outputBuffer)[i] = 0;
|
||||||
|
@ -151,12 +151,12 @@ long WriteAudioStream(PABLIO_Stream * aStream, void *data, long numFrames, switc
|
||||||
|
|
||||||
switch_core_timer_next(timer);
|
switch_core_timer_next(timer);
|
||||||
|
|
||||||
bytesWritten = PaUtil_WriteRingBuffer(&aStream->outFIFO, p, numBytes);
|
bytesWritten = PaUtil_WriteRingBuffer(&aStream->outFIFOs[0], p, numBytes);
|
||||||
numBytes -= bytesWritten;
|
numBytes -= bytesWritten;
|
||||||
p += bytesWritten;
|
p += bytesWritten;
|
||||||
|
|
||||||
if (numBytes > 0) {
|
if (numBytes > 0) {
|
||||||
PaUtil_FlushRingBuffer(&aStream->outFIFO);
|
PaUtil_FlushRingBuffer(&aStream->outFIFOs[0]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return numFrames;
|
return numFrames;
|
||||||
|
@ -177,17 +177,17 @@ long ReadAudioStream(PABLIO_Stream * aStream, void *data, long numFrames, switch
|
||||||
|
|
||||||
while (totalBytes < neededBytes && --max > 0) {
|
while (totalBytes < neededBytes && --max > 0) {
|
||||||
|
|
||||||
avail = PaUtil_GetRingBufferReadAvailable(&aStream->inFIFO);
|
avail = PaUtil_GetRingBufferReadAvailable(&aStream->inFIFOs[0]);
|
||||||
//printf("AVAILABLE BYTES %ld pass %d\n", avail, 5000 - max);
|
//printf("AVAILABLE BYTES %ld pass %d\n", avail, 5000 - max);
|
||||||
if (avail >= neededBytes * 6) {
|
if (avail >= neededBytes * 6) {
|
||||||
PaUtil_FlushRingBuffer(&aStream->inFIFO);
|
PaUtil_FlushRingBuffer(&aStream->inFIFOs[0]);
|
||||||
avail = 0;
|
avail = 0;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
bytesRead = 0;
|
bytesRead = 0;
|
||||||
|
|
||||||
if (totalBytes < neededBytes && avail >= neededBytes) {
|
if (totalBytes < neededBytes && avail >= neededBytes) {
|
||||||
bytesRead = PaUtil_ReadRingBuffer(&aStream->inFIFO, p, neededBytes);
|
bytesRead = PaUtil_ReadRingBuffer(&aStream->inFIFOs[0], p, neededBytes);
|
||||||
totalBytes += bytesRead;
|
totalBytes += bytesRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,7 +208,7 @@ long ReadAudioStream(PABLIO_Stream * aStream, void *data, long numFrames, switch
|
||||||
*/
|
*/
|
||||||
long GetAudioStreamWriteable(PABLIO_Stream * aStream)
|
long GetAudioStreamWriteable(PABLIO_Stream * aStream)
|
||||||
{
|
{
|
||||||
int bytesEmpty = PaUtil_GetRingBufferWriteAvailable(&aStream->outFIFO);
|
int bytesEmpty = PaUtil_GetRingBufferWriteAvailable(&aStream->outFIFOs[0]);
|
||||||
return bytesEmpty / aStream->bytesPerFrame;
|
return bytesEmpty / aStream->bytesPerFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,7 +218,7 @@ long GetAudioStreamWriteable(PABLIO_Stream * aStream)
|
||||||
*/
|
*/
|
||||||
long GetAudioStreamReadable(PABLIO_Stream * aStream)
|
long GetAudioStreamReadable(PABLIO_Stream * aStream)
|
||||||
{
|
{
|
||||||
int bytesFull = PaUtil_GetRingBufferReadAvailable(&aStream->inFIFO);
|
int bytesFull = PaUtil_GetRingBufferReadAvailable(&aStream->inFIFOs[0]);
|
||||||
return bytesFull / aStream->bytesPerFrame;
|
return bytesFull / aStream->bytesPerFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,7 +274,7 @@ PaError OpenAudioStream(PABLIO_Stream ** rwblPtr,
|
||||||
/* Initialize Ring Buffers */
|
/* Initialize Ring Buffers */
|
||||||
|
|
||||||
if (inputParameters) {
|
if (inputParameters) {
|
||||||
err = PABLIO_InitFIFO(&aStream->inFIFO, numFrames, aStream->bytesPerFrame);
|
err = PABLIO_InitFIFO(&aStream->inFIFOs[0], numFrames, aStream->bytesPerFrame);
|
||||||
if (err != paNoError) {
|
if (err != paNoError) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -282,7 +282,7 @@ PaError OpenAudioStream(PABLIO_Stream ** rwblPtr,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (outputParameters) {
|
if (outputParameters) {
|
||||||
err = PABLIO_InitFIFO(&aStream->outFIFO, numFrames, aStream->bytesPerFrame);
|
err = PABLIO_InitFIFO(&aStream->outFIFOs[0], numFrames, aStream->bytesPerFrame);
|
||||||
if (err != paNoError) {
|
if (err != paNoError) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -355,15 +355,15 @@ PaError CloseAudioStream(PABLIO_Stream * aStream)
|
||||||
int byteSize;
|
int byteSize;
|
||||||
|
|
||||||
|
|
||||||
byteSize = aStream->outFIFO.bufferSize;
|
byteSize = aStream->outFIFOs[0].bufferSize;
|
||||||
|
|
||||||
if (aStream->has_out) {
|
if (aStream->has_out) {
|
||||||
/* If we are writing data, make sure we play everything written. */
|
/* If we are writing data, make sure we play everything written. */
|
||||||
if (byteSize > 0) {
|
if (byteSize > 0) {
|
||||||
bytesEmpty = PaUtil_GetRingBufferWriteAvailable(&aStream->outFIFO);
|
bytesEmpty = PaUtil_GetRingBufferWriteAvailable(&aStream->outFIFOs[0]);
|
||||||
while (bytesEmpty < byteSize) {
|
while (bytesEmpty < byteSize) {
|
||||||
Pa_Sleep(10);
|
Pa_Sleep(10);
|
||||||
bytesEmpty = PaUtil_GetRingBufferWriteAvailable(&aStream->outFIFO);
|
bytesEmpty = PaUtil_GetRingBufferWriteAvailable(&aStream->outFIFOs[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -399,11 +399,11 @@ PaError CloseAudioStream(PABLIO_Stream * aStream)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aStream->has_in) {
|
if (aStream->has_in) {
|
||||||
PABLIO_TermFIFO(&aStream->inFIFO);
|
PABLIO_TermFIFO(&aStream->inFIFOs[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aStream->has_out) {
|
if (aStream->has_out) {
|
||||||
PABLIO_TermFIFO(&aStream->outFIFO);
|
PABLIO_TermFIFO(&aStream->outFIFOs[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(aStream);
|
free(aStream);
|
||||||
|
|
|
@ -65,8 +65,8 @@ typedef struct {
|
||||||
int do_dual;
|
int do_dual;
|
||||||
int has_in;
|
int has_in;
|
||||||
int has_out;
|
int has_out;
|
||||||
PaUtilRingBuffer inFIFOs[2]
|
PaUtilRingBuffer inFIFOs[2];
|
||||||
PaUtilRingBuffer outFIFOs[2]
|
PaUtilRingBuffer outFIFOs[2];
|
||||||
int channelCount;
|
int channelCount;
|
||||||
} PABLIO_Stream;
|
} PABLIO_Stream;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue