Commit 6405adaa authored by Ivica Bukvic's avatar Ivica Bukvic
Browse files

*updated most of the audio API to the latest version (with the exception of...

*updated most of the audio API to the latest version (with the exception of ALSA and JACK which are partial until our improvements can be merged and/or new implementation of JACK thoroughly tested to ensure we like its default behavior)
parent 3da3a699
...@@ -205,7 +205,7 @@ proc ::dialog_audio::pdtk_audio_dialog {id \ ...@@ -205,7 +205,7 @@ proc ::dialog_audio::pdtk_audio_dialog {id \
set audio_callback $callback set audio_callback $callback
set audio_blocksize $blocksize set audio_blocksize $blocksize
set audio_longform $longform set audio_longform $longform
set mytoplevel .prefs.nb.audio set mytoplevel .prefs.nb.audio
set apifr $mytoplevel.api set apifr $mytoplevel.api
if {![winfo exists $apifr]} { if {![winfo exists $apifr]} {
......
...@@ -8493,8 +8493,7 @@ proc pdtk_audio_dialog {mytoplevel indev1 indev2 indev3 indev4 \ ...@@ -8493,8 +8493,7 @@ proc pdtk_audio_dialog {mytoplevel indev1 indev2 indev3 indev4 \
inchan1 inchan2 inchan3 inchan4 \ inchan1 inchan2 inchan3 inchan4 \
outdev1 outdev2 outdev3 outdev4 \ outdev1 outdev2 outdev3 outdev4 \
outchan1 outchan2 outchan3 outchan4 sr advance multi callback \ outchan1 outchan2 outchan3 outchan4 sr advance multi callback \
longform} { longform blocksize} {
set blocksize 64
::dialog_audio::pdtk_audio_dialog \ ::dialog_audio::pdtk_audio_dialog \
$mytoplevel $indev1 $indev2 $indev3 $indev4 \ $mytoplevel $indev1 $indev2 $indev3 $indev4 \
$inchan1 $inchan2 $inchan3 $inchan4 \ $inchan1 $inchan2 $inchan3 $inchan4 \
......
...@@ -90,6 +90,11 @@ int audio_isopen(void) ...@@ -90,6 +90,11 @@ int audio_isopen(void)
|| (audio_naudiooutdev > 0 && audio_audiochoutdev[0] > 0))); || (audio_naudiooutdev > 0 && audio_audiochoutdev[0] > 0)));
} }
int sys_audio_get_blocksize(void)
{
return (audio_blocksize);
}
void sys_get_audio_params( void sys_get_audio_params(
int *pnaudioindev, int *paudioindev, int *chindev, int *pnaudioindev, int *paudioindev, int *chindev,
int *pnaudiooutdev, int *paudiooutdev, int *choutdev, int *pnaudiooutdev, int *paudiooutdev, int *choutdev,
...@@ -146,7 +151,6 @@ void sys_save_audio_params( ...@@ -146,7 +151,6 @@ void sys_save_audio_params(
audio_advance = advance; audio_advance = advance;
audio_callback = callback; audio_callback = callback;
audio_blocksize = blocksize; audio_blocksize = blocksize;
fprintf(stderr,"blocksize=%d\n", blocksize);
} }
/* init routines for any API which needs to set stuff up before /* init routines for any API which needs to set stuff up before
...@@ -421,7 +425,7 @@ void sys_reopen_audio( void) ...@@ -421,7 +425,7 @@ void sys_reopen_audio( void)
#ifdef USEAPI_PORTAUDIO #ifdef USEAPI_PORTAUDIO
if (sys_audioapi == API_PORTAUDIO) if (sys_audioapi == API_PORTAUDIO)
{ {
int blksize = (sys_blocksize ? sys_blocksize : 64); int blksize = (audio_blocksize ? audio_blocksize : 64);
outcome = pa_open_audio((naudioindev > 0 ? chindev[0] : 0), outcome = pa_open_audio((naudioindev > 0 ? chindev[0] : 0),
(naudiooutdev > 0 ? choutdev[0] : 0), rate, sys_soundin, (naudiooutdev > 0 ? choutdev[0] : 0), rate, sys_soundin,
sys_soundout, blksize, sys_advance_samples/blksize, sys_soundout, blksize, sys_advance_samples/blksize,
...@@ -441,7 +445,8 @@ void sys_reopen_audio( void) ...@@ -441,7 +445,8 @@ void sys_reopen_audio( void)
#ifdef USEAPI_OSS #ifdef USEAPI_OSS
if (sys_audioapi == API_OSS) if (sys_audioapi == API_OSS)
outcome = oss_open_audio(naudioindev, audioindev, naudioindev, outcome = oss_open_audio(naudioindev, audioindev, naudioindev,
chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate); chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate,
audio_blocksize);
else else
#endif #endif
#ifdef USEAPI_ALSA #ifdef USEAPI_ALSA
...@@ -456,7 +461,25 @@ void sys_reopen_audio( void) ...@@ -456,7 +461,25 @@ void sys_reopen_audio( void)
#ifdef USEAPI_MMIO #ifdef USEAPI_MMIO
if (sys_audioapi == API_MMIO) if (sys_audioapi == API_MMIO)
outcome = mmio_open_audio(naudioindev, audioindev, naudioindev, outcome = mmio_open_audio(naudioindev, audioindev, naudioindev,
chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate,
audio_blocksize);
else
#endif
#ifdef USEAPI_AUDIOUNIT
if (sys_audioapi == API_AUDIOUNIT)
outcome = audiounit_open_audio((naudioindev > 0 ? chindev[0] : 0),
(naudioindev > 0 ? choutdev[0] : 0), rate);
else
#endif
#ifdef USEAPI_ESD
if (sys_audioapi == API_ALSA)
outcome = esd_open_audio(naudioindev, audioindev, naudioindev,
chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate); chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate);
else
#endif
#ifdef USEAPI_DUMMY
if (sys_audioapi == API_DUMMY)
outcome = dummy_open_audio(naudioindev, naudiooutdev, rate);
else else
#endif #endif
if (sys_audioapi == API_NONE) if (sys_audioapi == API_NONE)
...@@ -735,7 +758,7 @@ void glob_audio_properties(t_pd *dummy, t_floatarg flongform) ...@@ -735,7 +758,7 @@ void glob_audio_properties(t_pd *dummy, t_floatarg flongform)
"pdtk_audio_dialog %%s \ "pdtk_audio_dialog %%s \
%d %d %d %d %d %d %d %d \ %d %d %d %d %d %d %d %d \
%d %d %d %d %d %d %d %d \ %d %d %d %d %d %d %d %d \
%d %d %d %d %d\n", %d %d %d %d %d %d\n",
audioindev1, audioindev2, audioindev3, audioindev4, audioindev1, audioindev2, audioindev3, audioindev4,
audioinchan1, audioinchan2, audioinchan3, audioinchan4, audioinchan1, audioinchan2, audioinchan3, audioinchan4,
audiooutdev1, audiooutdev2, audiooutdev3, audiooutdev4, audiooutdev1, audiooutdev2, audiooutdev3, audiooutdev4,
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
#include <windows.h> #include <windows.h>
#include <MMSYSTEM.H> #include <mmsystem.h>
/* ------------------------- audio -------------------------- */ /* ------------------------- audio -------------------------- */
...@@ -696,11 +696,11 @@ idle: ...@@ -696,11 +696,11 @@ idle:
int mmio_open_audio(int naudioindev, int *audioindev, int mmio_open_audio(int naudioindev, int *audioindev,
int nchindev, int *chindev, int naudiooutdev, int *audiooutdev, int nchindev, int *chindev, int naudiooutdev, int *audiooutdev,
int nchoutdev, int *choutdev, int rate) int nchoutdev, int *choutdev, int rate, int blocksize)
{ {
int nbuf; int nbuf;
nt_realdacblksize = (sys_blocksize ? sys_blocksize : DEFREALDACBLKSIZE); nt_realdacblksize = (blocksize ? blocksize : DEFREALDACBLKSIZE);
nbuf = sys_advance_samples/nt_realdacblksize; nbuf = sys_advance_samples/nt_realdacblksize;
if (nbuf >= MAXBUFFER) if (nbuf >= MAXBUFFER)
{ {
......
...@@ -5,7 +5,14 @@ ...@@ -5,7 +5,14 @@
/* this file inputs and outputs audio using the OSS API available on linux. */ /* this file inputs and outputs audio using the OSS API available on linux. */
#include <linux/soundcard.h> #include <sys/soundcard.h>
#ifndef SNDCTL_DSP_GETISPACE
#define SNDCTL_DSP_GETISPACE SOUND_PCM_GETISPACE
#endif
#ifndef SNDCTL_DSP_GETOSPACE
#define SNDCTL_DSP_GETOSPACE SOUND_PCM_GETOSPACE
#endif
#include "m_pd.h" #include "m_pd.h"
#include "s_stuff.h" #include "s_stuff.h"
...@@ -41,8 +48,11 @@ typedef int32_t t_oss_int32; ...@@ -41,8 +48,11 @@ typedef int32_t t_oss_int32;
#define OSS_XFERSIZE(chans, width) (DEFDACBLKSIZE * (chans) * (width)) #define OSS_XFERSIZE(chans, width) (DEFDACBLKSIZE * (chans) * (width))
/* GLOBALS */ /* GLOBALS */
static int linux_meters; /* true if we're metering */
static t_sample linux_inmax; /* max input amplitude */
static t_sample linux_outmax; /* max output amplitude */
static int linux_fragsize = 0; /* for block mode; block size (sample frames) */ static int linux_fragsize = 0; /* for block mode; block size (sample frames) */
extern int audio_blocksize; /* stolen from s_audio.c */
/* our device handles */ /* our device handles */
typedef struct _oss_dev typedef struct _oss_dev
...@@ -67,6 +77,7 @@ t_sample *sys_soundin; ...@@ -67,6 +77,7 @@ t_sample *sys_soundin;
/* OSS-specific private variables */ /* OSS-specific private variables */
static int oss_blockmode = 1; /* flag to use "blockmode" */ static int oss_blockmode = 1; /* flag to use "blockmode" */
static char ossdsp[] = "/dev/dsp%d";
/* don't assume we can turn all 31 bits when doing float-to-fix; /* don't assume we can turn all 31 bits when doing float-to-fix;
otherwise some audio drivers (e.g. Midiman/ALSA) wrap around. */ otherwise some audio drivers (e.g. Midiman/ALSA) wrap around. */
...@@ -117,10 +128,12 @@ int oss_reset(int fd) { ...@@ -117,10 +128,12 @@ int oss_reset(int fd) {
return err; return err;
} }
void oss_configure(t_oss_dev *dev, int srate, int dac, int skipblocksize) void oss_configure(t_oss_dev *dev, int srate, int dac, int skipblocksize,
int suggestedblocksize)
{ {
int orig, param, fd = dev->d_fd, wantformat; int orig, param, nblk, fd = dev->d_fd, wantformat;
int nchannels = dev->d_nchannels; int nchannels = dev->d_nchannels;
int advwas = sys_schedadvance;
audio_buf_info ainfo; audio_buf_info ainfo;
...@@ -148,7 +161,7 @@ void oss_configure(t_oss_dev *dev, int srate, int dac, int skipblocksize) ...@@ -148,7 +161,7 @@ void oss_configure(t_oss_dev *dev, int srate, int dac, int skipblocksize)
{ {
int fragbytes, logfragsize, nfragment; int fragbytes, logfragsize, nfragment;
/* setting fragment count and size. */ /* setting fragment count and size. */
linux_fragsize = sys_blocksize; linux_fragsize = suggestedblocksize;
if (!linux_fragsize) if (!linux_fragsize)
{ {
linux_fragsize = OSS_DEFFRAGSIZE; linux_fragsize = OSS_DEFFRAGSIZE;
...@@ -192,7 +205,7 @@ void oss_configure(t_oss_dev *dev, int srate, int dac, int skipblocksize) ...@@ -192,7 +205,7 @@ void oss_configure(t_oss_dev *dev, int srate, int dac, int skipblocksize)
out. */ out. */
int defect; int defect;
if (ioctl(fd, SOUND_PCM_GETOSPACE,&ainfo) < 0) if (ioctl(fd, SNDCTL_DSP_GETOSPACE,&ainfo) < 0)
fprintf(stderr,"OSS: ioctl on output device failed"); fprintf(stderr,"OSS: ioctl on output device failed");
dev->d_bufsize = ainfo.bytes; dev->d_bufsize = ainfo.bytes;
...@@ -234,7 +247,7 @@ static int oss_setchannels(int fd, int wantchannels, char *devname) ...@@ -234,7 +247,7 @@ static int oss_setchannels(int fd, int wantchannels, char *devname)
} }
} }
param = wantchannels; param = wantchannels;
//whynot: whynot:
while (param > 1) while (param > 1)
{ {
int save = param; int save = param;
...@@ -251,15 +264,19 @@ static int oss_setchannels(int fd, int wantchannels, char *devname) ...@@ -251,15 +264,19 @@ static int oss_setchannels(int fd, int wantchannels, char *devname)
#define O_AUDIOFLAG O_NDELAY #define O_AUDIOFLAG O_NDELAY
int oss_open_audio(int nindev, int *indev, int nchin, int *chin, int oss_open_audio(int nindev, int *indev, int nchin, int *chin,
int noutdev, int *outdev, int nchout, int *chout, int rate) int noutdev, int *outdev, int nchout, int *chout, int rate,
int blocksize)
{ {
int capabilities = 0; int capabilities = 0;
int inchannels = 0, outchannels = 0; int inchannels = 0, outchannels = 0;
char devname[20]; char devname[20];
int n, i, fd, flags; int n, i, fd, flags;
char buf[OSS_MAXSAMPLEWIDTH * DEFDACBLKSIZE * OSS_MAXCHPERDEV]; char buf[OSS_MAXSAMPLEWIDTH * DEFDACBLKSIZE * OSS_MAXCHPERDEV];
int num_devs = 0;
int wantmore=0; int wantmore=0;
int spread = 0;
audio_buf_info ainfo;
linux_nindevs = linux_noutdevs = 0; linux_nindevs = linux_noutdevs = 0;
/* mark devices unopened */ /* mark devices unopened */
for (i = 0; i < OSS_MAXDEV; i++) for (i = 0; i < OSS_MAXDEV; i++)
...@@ -350,7 +367,7 @@ int oss_open_audio(int nindev, int *indev, int nchin, int *chin, ...@@ -350,7 +367,7 @@ int oss_open_audio(int nindev, int *indev, int nchin, int *chin,
{ {
linux_dacs[linux_noutdevs].d_nchannels = gotchans; linux_dacs[linux_noutdevs].d_nchannels = gotchans;
linux_dacs[linux_noutdevs].d_fd = fd; linux_dacs[linux_noutdevs].d_fd = fd;
oss_configure(linux_dacs+linux_noutdevs, rate, 1, 0); oss_configure(linux_dacs+linux_noutdevs, rate, 1, 0, blocksize);
linux_noutdevs++; linux_noutdevs++;
outchannels += gotchans; outchannels += gotchans;
...@@ -425,7 +442,8 @@ int oss_open_audio(int nindev, int *indev, int nchin, int *chin, ...@@ -425,7 +442,8 @@ int oss_open_audio(int nindev, int *indev, int nchin, int *chin,
linux_adcs[linux_nindevs].d_nchannels = gotchans; linux_adcs[linux_nindevs].d_nchannels = gotchans;
oss_configure(linux_adcs+linux_nindevs, rate, 0, alreadyopened); oss_configure(linux_adcs+linux_nindevs, rate, 0, alreadyopened,
blocksize);
inchannels += gotchans; inchannels += gotchans;
linux_nindevs++; linux_nindevs++;
...@@ -499,14 +517,14 @@ static void oss_calcspace(void) ...@@ -499,14 +517,14 @@ static void oss_calcspace(void)
audio_buf_info ainfo; audio_buf_info ainfo;
for (dev=0; dev < linux_noutdevs; dev++) for (dev=0; dev < linux_noutdevs; dev++)
{ {
if (ioctl(linux_dacs[dev].d_fd, SOUND_PCM_GETOSPACE, &ainfo) < 0) if (ioctl(linux_dacs[dev].d_fd, SNDCTL_DSP_GETOSPACE, &ainfo) < 0)
fprintf(stderr,"OSS: ioctl on output device %d failed",dev); fprintf(stderr,"OSS: ioctl on output device %d failed",dev);
linux_dacs[dev].d_space = ainfo.bytes; linux_dacs[dev].d_space = ainfo.bytes;
} }
for (dev = 0; dev < linux_nindevs; dev++) for (dev = 0; dev < linux_nindevs; dev++)
{ {
if (ioctl(linux_adcs[dev].d_fd, SOUND_PCM_GETISPACE,&ainfo) < 0) if (ioctl(linux_adcs[dev].d_fd, SNDCTL_DSP_GETISPACE,&ainfo) < 0)
fprintf(stderr, "OSS: ioctl on input device %d, fd %d failed", fprintf(stderr, "OSS: ioctl on input device %d, fd %d failed",
dev, linux_adcs[dev].d_fd); dev, linux_adcs[dev].d_fd);
linux_adcs[dev].d_space = ainfo.bytes; linux_adcs[dev].d_space = ainfo.bytes;
...@@ -533,7 +551,7 @@ in audio output and/or input. */ ...@@ -533,7 +551,7 @@ in audio output and/or input. */
static void oss_doresync( void) static void oss_doresync( void)
{ {
int dev, zeroed = 0; int dev, zeroed = 0, wantsize;
char buf[OSS_MAXSAMPLEWIDTH * DEFDACBLKSIZE * OSS_MAXCHPERDEV]; char buf[OSS_MAXSAMPLEWIDTH * DEFDACBLKSIZE * OSS_MAXCHPERDEV];
audio_buf_info ainfo; audio_buf_info ainfo;
...@@ -554,7 +572,7 @@ static void oss_doresync( void) ...@@ -554,7 +572,7 @@ static void oss_doresync( void)
linux_adcs_read(linux_adcs[dev].d_fd, buf, linux_adcs_read(linux_adcs[dev].d_fd, buf,
OSS_XFERSIZE(linux_adcs[dev].d_nchannels, OSS_XFERSIZE(linux_adcs[dev].d_nchannels,
linux_adcs[dev].d_bytespersamp)); linux_adcs[dev].d_bytespersamp));
if (ioctl(linux_adcs[dev].d_fd, SOUND_PCM_GETISPACE, &ainfo) < 0) if (ioctl(linux_adcs[dev].d_fd, SNDCTL_DSP_GETISPACE, &ainfo) < 0)
{ {
fprintf(stderr, "OSS: ioctl on input device %d, fd %d failed", fprintf(stderr, "OSS: ioctl on input device %d, fd %d failed",
dev, linux_adcs[dev].d_fd); dev, linux_adcs[dev].d_fd);
...@@ -583,7 +601,7 @@ static void oss_doresync( void) ...@@ -583,7 +601,7 @@ static void oss_doresync( void)
linux_dacs_write(linux_dacs[dev].d_fd, buf, linux_dacs_write(linux_dacs[dev].d_fd, buf,
OSS_XFERSIZE(linux_dacs[dev].d_nchannels, OSS_XFERSIZE(linux_dacs[dev].d_nchannels,
linux_dacs[dev].d_bytespersamp)); linux_dacs[dev].d_bytespersamp));
if (ioctl(linux_dacs[dev].d_fd, SOUND_PCM_GETOSPACE, &ainfo) < 0) if (ioctl(linux_dacs[dev].d_fd, SNDCTL_DSP_GETOSPACE, &ainfo) < 0)
{ {
fprintf(stderr, "OSS: ioctl on output device %d, fd %d failed", fprintf(stderr, "OSS: ioctl on output device %d, fd %d failed",
dev, linux_dacs[dev].d_fd); dev, linux_dacs[dev].d_fd);
...@@ -612,9 +630,11 @@ static void oss_doresync( void) ...@@ -612,9 +630,11 @@ static void oss_doresync( void)
int oss_send_dacs(void) int oss_send_dacs(void)
{ {
t_sample *fp1, *fp2; t_sample *fp1, *fp2;
long fill;
int i, j, dev, rtnval = SENDDACS_YES; int i, j, dev, rtnval = SENDDACS_YES;
char buf[OSS_MAXSAMPLEWIDTH * DEFDACBLKSIZE * OSS_MAXCHPERDEV]; char buf[OSS_MAXSAMPLEWIDTH * DEFDACBLKSIZE * OSS_MAXCHPERDEV];
t_oss_int16 *sp; t_oss_int16 *sp;
t_oss_int32 *lp;
/* the maximum number of samples we should have in the ADC buffer */ /* the maximum number of samples we should have in the ADC buffer */
int idle = 0; int idle = 0;
int thischan; int thischan;
...@@ -655,6 +675,7 @@ int oss_send_dacs(void) ...@@ -655,6 +675,7 @@ int oss_send_dacs(void)
for (dev = 0;dev < linux_nindevs; dev++) for (dev = 0;dev < linux_nindevs; dev++)
if (linux_adcs[dev].d_space == 0) if (linux_adcs[dev].d_space == 0)
{ {
audio_buf_info ainfo;
sys_microsleep(2000); sys_microsleep(2000);
oss_calcspace(); oss_calcspace();
if (linux_adcs[dev].d_space != 0) continue; if (linux_adcs[dev].d_space != 0) continue;
......
This diff is collapsed.
/*
* pablio.c
* Portable Audio Blocking Input/Output utility.
*
* Author: Phil Burk, http://www.softsynth.com
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.audiomulch.com/portaudio/
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
/* changes by Miller Puckette to support Pd: device selection,
settable audio buffer size, and settable number of channels.
LATER also fix it to poll for input and output fifo fill points. */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "portaudio.h"
#include "s_audio_paring.h"
#include "s_audio_pablio.h" /* MSP */
#include <string.h>
/* MSP -- FRAMES_PER_BUFFER constant removed */
static void NPa_Sleep(int n) /* MSP wrapper to check we never stall... */
{
#if 0
fprintf(stderr, "sleep\n");
#endif
Pa_Sleep(n);
}
/************************************************************************/
/******** Prototypes ****************************************************/
/************************************************************************/
static int blockingIOCallback( const void *inputBuffer, void *outputBuffer, /*MSP */
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo *outTime,
PaStreamCallbackFlags myflags,
void *userData );
static PaError PABLIO_InitFIFO( sys_ringbuf *rbuf, long numFrames, long bytesPerFrame );
static PaError PABLIO_TermFIFO( sys_ringbuf *rbuf );
/************************************************************************/
/******** Functions *****************************************************/
/************************************************************************/
/* Called from PortAudio.
* Read and write data only if there is room in FIFOs.
*/
static int blockingIOCallback( const void *inputBuffer, void *outputBuffer, /* MSP */
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo *outTime,
PaStreamCallbackFlags myflags,
void *userData )
{
PABLIO_Stream *data = (PABLIO_Stream*)userData;
(void) outTime;
/* This may get called with NULL inputBuffer during initial setup. */
if( inputBuffer != NULL )
{
sys_ringbuf_Write( &data->inFIFO, inputBuffer,
data->inbytesPerFrame * framesPerBuffer );
}
if( outputBuffer != NULL )
{
int i;
int numBytes = data->outbytesPerFrame * framesPerBuffer;
int numRead = sys_ringbuf_Read( &data->outFIFO, outputBuffer,
numBytes);
/* Zero out remainder of buffer if we run out of data. */
for( i=numRead; i<numBytes; i++ )
{
((char *)outputBuffer)[i] = 0;
}
}
return 0;
}
/* Allocate buffer. */
static PaError PABLIO_InitFIFO( sys_ringbuf *rbuf, long numFrames, long bytesPerFrame )
{
long numBytes = numFrames * bytesPerFrame;
char *buffer = (char *) malloc( numBytes );
if( buffer == NULL ) return paInsufficientMemory;
memset( buffer, 0, numBytes );
return (PaError) sys_ringbuf_Init( rbuf, numBytes, buffer );
}
/* Free buffer. */
static PaError PABLIO_TermFIFO( sys_ringbuf *rbuf )
{
if( rbuf->buffer ) free( rbuf->buffer );
rbuf->buffer = NULL;
return paNoError;
}
/************************************************************
* Write data to ring buffer.
* Will not return until all the data has been written.
*/
long WriteAudioStream( PABLIO_Stream *aStream, void *data, long numFrames )
{
long bytesWritten;
char *p = (char *) data;
long numBytes = aStream->outbytesPerFrame * numFrames;
while( numBytes > 0)
{
bytesWritten = sys_ringbuf_Write( &aStream->outFIFO, p, numBytes );
numBytes -= bytesWritten;
p += bytesWritten;
if( numBytes > 0) NPa_Sleep(10); /* MSP */
}
return numFrames;
}
/************************************************************
* Read data from ring buffer.
* Will not return until all the data has been read.
*/
long ReadAudioStream( PABLIO_Stream *aStream, void *data, long numFrames )
{
long bytesRead;
char *p = (char *) data;
long numBytes = aStream->inbytesPerFrame * numFrames;
while( numBytes > 0)
{
bytesRead = sys_ringbuf_Read( &aStream->inFIFO, p, numBytes );
numBytes -= bytesRead;
p += bytesRead;
if( numBytes > 0) NPa_Sleep(10); /* MSP */
}
return numFrames;
}
/************************************************************
* Return the number of frames that could be written to the stream without
* having to wait.
*/
long GetAudioStreamWriteable( PABLIO_Stream *aStream )
{
int bytesEmpty = sys_ringbuf_GetWriteAvailable( &aStream->outFIFO );
return bytesEmpty / aStream->outbytesPerFrame;
}
/************************************************************
* Return the number of frames that are available to be read from the
* stream without having to wait.
*/
long GetAudioStreamReadable( PABLIO_Stream *aStream )
{
int bytesFull = sys_ringbuf_GetReadAvailable( &aStream->inFIFO );
return bytesFull / aStream->inbytesPerFrame;
}
/************************************************************/
static unsigned long RoundUpToNextPowerOf2( unsigned long n )
{
long numBits = 0;