From 9c0e19a3be2288db79e2502e5fa450c3e20a668d Mon Sep 17 00:00:00 2001 From: Guenter Geiger Date: Fri, 9 May 2003 16:04:00 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r610, which included commits to RCS files with non-trunk default branches. svn path=/trunk/; revision=611 --- pd/src/s_audio.c | 410 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 410 insertions(+) create mode 100644 pd/src/s_audio.c (limited to 'pd/src/s_audio.c') diff --git a/pd/src/s_audio.c b/pd/src/s_audio.c new file mode 100644 index 00000000..ca5e34c6 --- /dev/null +++ b/pd/src/s_audio.c @@ -0,0 +1,410 @@ +/* Copyright (c) 2003, Miller Puckette and others. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* machine-independent (well, mostly!) audio layer. Stores and recalls + audio settings from argparse routine and from dialog window. +*/ + + +#include "m_pd.h" +#include "s_stuff.h" +#include +#ifdef UNIX +#include +#include +#include +#endif +#include +#include +#include + +#define SYS_DEFAULTCH 2 +#define SYS_MAXCH 100 +#define SYS_DEFAULTSRATE 44100 +typedef long t_pa_sample; +#define SYS_SAMPLEWIDTH sizeof(t_pa_sample) +#define SYS_BYTESPERCHAN (DEFDACBLKSIZE * SYS_SAMPLEWIDTH) +#define SYS_XFERSAMPS (SYS_DEFAULTCH*DEFDACBLKSIZE) +#define SYS_XFERSIZE (SYS_SAMPLEWIDTH * SYS_XFERSAMPS) +#define MAXAUDIODEV 4 + +int sys_inchannels; +int sys_outchannels; +int sys_advance_samples; /* scheduler advance in samples */ +int sys_blocksize = 256; /* audio I/O block size in sample frames */ +int sys_audioapi = API_DEFAULT; + +static int sys_meters; /* true if we're metering */ +static float sys_inmax; /* max input amplitude */ +static float sys_outmax; /* max output amplitude */ + + /* exported variables */ +#ifdef MSW +#define DEFAULTADVANCE 70000 +#else +#define DEFAULTADVANCE 50000 +#endif +int sys_schedadvance = DEFAULTADVANCE; /* scheduler advance in microseconds */ +float sys_dacsr; +int sys_hipriority = 0; +t_sample *sys_soundout; +t_sample *sys_soundin; + + /* set channels and sample rate. */ + +static void sys_setchsr(int chin, int chout, int sr) +{ + int nblk; + int inbytes = chin * (DEFDACBLKSIZE*sizeof(float)); + int outbytes = chout * (DEFDACBLKSIZE*sizeof(float)); + + sys_inchannels = chin; + sys_outchannels = chout; + sys_dacsr = sr; + sys_advance_samples = (sys_schedadvance * sys_dacsr) / (1000000.); + if (sys_advance_samples < 3 * DEFDACBLKSIZE) + sys_advance_samples = 3 * DEFDACBLKSIZE; + + if (sys_soundin) + free(sys_soundin); + sys_soundin = (t_float *)malloc(inbytes); + memset(sys_soundin, 0, inbytes); + + if (sys_soundout) + free(sys_soundout); + sys_soundout = (t_float *)malloc(outbytes); + memset(sys_soundout, 0, outbytes); + + if (sys_verbose) + post("input channels = %d, output channels = %d", + sys_inchannels, sys_outchannels); +} + +/* ----------------------- public routines ----------------------- */ + +#if 0 +void sys_open_audio(int naudioindev, int *audioindev, int nchindev, + int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev, + int *choutdev, int rate) /* IOhannes */ +{ + int inchans= + (nchindev > 0 ? chindev[0] : (nchindev == 0 ? 0 : SYS_DEFAULTCH)); + int outchans= + (nchoutdev > 0 ? choutdev[0] : (nchoutdev == 0 ? 0 : SYS_DEFAULTCH)); + int soundindev = (naudioindev <= 0 ? -1 : (audioindev[0]-1)); + int soundoutdev = (naudiooutdev <= 0 ? -1 : (audiooutdev[0]-1)); + int sounddev = (inchans > 0 ? soundindev : soundoutdev); + if (naudioindev > 1 || nchindev > 1 || naudiooutdev > 1 || nchoutdev > 1) + post("sorry, only one portaudio device can be open at once.\n"); + /* post("nindev %d, noutdev %d", naudioindev, naudiooutdev); + post("soundindev %d, soundoutdev %d", soundindev, soundoutdev); */ + if (sys_verbose) + post("channels in %d, out %d", inchans, outchans); + if (rate < 1) + rate = SYS_DEFAULTSRATE; + sys_setchsr(inchans, outchans, rate); + pa_open_audio(inchans, outchans, rate, sys_soundin, sys_soundout, + sys_blocksize, sys_advance_samples/sys_blocksize, + soundindev, soundoutdev); +} +#endif + +void sys_open_audio(int naudioindev, int *audioindev, int nchindev, + int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev, + int *choutdev, int rate) /* IOhannes */ +{ + int i, *ip; + int defaultchannels = SYS_DEFAULTCH; + int inchans, outchans; + if (rate < 1) + rate = SYS_DEFAULTSRATE; + + if (naudioindev == -1) + { /* not set */ + if (nchindev == -1) + { + nchindev=1; + chindev[0] = defaultchannels; + naudioindev = 1; + audioindev[0] = DEFAULTAUDIODEV; + } + else + { + for (i = 0; i < MAXAUDIODEV; i++) + audioindev[i] = i+1; + naudioindev = nchindev; + } + } + else + { + if (nchindev == -1) + { + nchindev = naudioindev; + for (i = 0; i < naudioindev; i++) + chindev[i] = defaultchannels; + } + else if (nchindev > naudioindev) + { + for (i = naudioindev; i < nchindev; i++) + { + if (i == 0) + audioindev[0] = DEFAULTAUDIODEV; + else audioindev[i] = audioindev[i-1] + 1; + } + naudioindev = nchindev; + } + else if (nchindev < naudioindev) + { + for (i = nchindev; i < naudioindev; i++) + { + if (i == 0) + chindev[0] = defaultchannels; + else chindev[i] = chindev[i-1]; + } + naudioindev = nchindev; + } + } + + if (naudiooutdev == -1) + { /* not set */ + if (nchoutdev == -1) + { + nchoutdev=1; + choutdev[0]=defaultchannels; + naudiooutdev=1; + audiooutdev[0] = DEFAULTAUDIODEV; + } + else + { + for (i = 0; i < MAXAUDIODEV; i++) + audiooutdev[i] = i+1; + naudiooutdev = nchoutdev; + } + } + else + { + if (nchoutdev == -1) + { + nchoutdev = naudiooutdev; + for (i = 0; i < naudiooutdev; i++) + choutdev[i] = defaultchannels; + } + else if (nchoutdev > naudiooutdev) + { + for (i = naudiooutdev; i < nchoutdev; i++) + { + if (i == 0) + audiooutdev[0] = DEFAULTAUDIODEV; + else audiooutdev[i] = audiooutdev[i-1] + 1; + } + naudiooutdev = nchoutdev; + } + else if (nchoutdev < naudiooutdev) + { + for (i = nchoutdev; i < naudiooutdev; i++) + { + if (i == 0) + choutdev[0] = defaultchannels; + else choutdev[i] = choutdev[i-1]; + } + naudiooutdev = nchoutdev; + } + } + for (i = inchans = 0; i < naudioindev; i++) + inchans += chindev[i]; + for (i = outchans = 0; i < naudiooutdev; i++) + outchans += choutdev[i]; + + sys_setchsr(inchans, outchans, rate); +#ifdef USEAPI_OSS + if (sys_audioapi == API_OSS) + oss_open_audio(naudioindev, audioindev, nchindev, chindev, + naudiooutdev, audiooutdev, nchoutdev, choutdev, rate); + else +#endif +#ifdef USEAPI_ALSA + /* for alsa, the "device numbers" are ignored; they are sent + straight to the alsa code via linux_alsa_devname(). Only one + device is supported for each of input, output. */ + if (sys_audioapi == API_ALSA) + alsa_open_audio((naudioindev > 0 ? chindev[0] : 0), + (naudiooutdev > 0 ? choutdev[0] : 0), rate); + else +#endif +#ifdef USEAPI_PORTAUDIO + if (sys_audioapi == API_PORTAUDIO) + pa_open_audio(inchans, outchans, rate, sys_soundin, sys_soundout, + sys_blocksize, sys_advance_samples/sys_blocksize, + (naudiooutdev > 0 ? audioindev[0] : 0), + (naudiooutdev > 0 ? audiooutdev[0] : 0)); + else +#endif +#ifdef USEAPI_MMIO + if (sys_audioapi == API_MMIO) + mmio_open_audio(naudioindev, audioindev, nchindev, chindev, + naudiooutdev, audiooutdev, nchoutdev, choutdev, rate); + else +#endif + post("unknown audio API specified"); +} + +void sys_close_audio(void) +{ + +#ifdef USEAPI_PORTAUDIO + if (sys_audioapi == API_PORTAUDIO) + pa_close_audio(); + else +#endif +#ifdef USEAPI_OSS + if (sys_audioapi == API_OSS) + oss_close_audio(); + else +#endif +#ifdef USEAPI_ALSA + if (sys_audioapi == API_ALSA) + alsa_close_audio(); + else +#ifdef USEAPI_MMIO + if (sys_audioapi == API_MMIO) + mmio_close_audio(); + else +#endif +#endif + post("unknown API"); + +} + +int sys_send_dacs(void) +{ + if (sys_meters) + { + int i, n; + float maxsamp; + for (i = 0, n = sys_inchannels * DEFDACBLKSIZE, maxsamp = sys_inmax; + i < n; i++) + { + float f = sys_soundin[i]; + if (f > maxsamp) maxsamp = f; + else if (-f > maxsamp) maxsamp = -f; + } + sys_inmax = maxsamp; + for (i = 0, n = sys_outchannels * DEFDACBLKSIZE, maxsamp = sys_outmax; + i < n; i++) + { + float f = sys_soundout[i]; + if (f > maxsamp) maxsamp = f; + else if (-f > maxsamp) maxsamp = -f; + } + sys_outmax = maxsamp; + } + +#ifdef USEAPI_PORTAUDIO + if (sys_audioapi == API_PORTAUDIO) + return (pa_send_dacs()); + else +#endif +#ifdef USEAPI_OSS + if (sys_audioapi == API_OSS) + return (oss_send_dacs()); + else +#endif +#ifdef USEAPI_ALSA + if (sys_audioapi == API_ALSA) + return (alsa_send_dacs()); + else +#endif +#ifdef USEAPI_MMIO + if (sys_audioapi == API_MMIO) + return (mmio_send_dacs()); + else +#endif + post("unknown API"); + return (0); +} + +float sys_getsr(void) +{ + return (sys_dacsr); +} + +int sys_get_outchannels(void) +{ + return (sys_outchannels); +} + +int sys_get_inchannels(void) +{ + return (sys_inchannels); +} + +void sys_audiobuf(int n) +{ + /* set the size, in milliseconds, of the audio FIFO */ + if (n < 5) n = 5; + else if (n > 5000) n = 5000; + sys_schedadvance = n * 1000; +} + +void sys_getmeters(float *inmax, float *outmax) +{ + if (inmax) + { + sys_meters = 1; + *inmax = sys_inmax; + *outmax = sys_outmax; + } + else + sys_meters = 0; + sys_inmax = sys_outmax = 0; +} + +void sys_reportidle(void) +{ +} + +void sys_listdevs(void ) +{ +#ifdef USEAPI_PORTAUDIO + if (sys_audioapi == API_PORTAUDIO) + pa_listdevs(); + else +#endif +#ifdef USEAPI_OSS + if (sys_audioapi == API_OSS) + oss_listdevs(); + else +#endif +#ifdef USEAPI_MMIO + if (sys_audioapi == API_MMIO) + mmio_listdevs(); + else +#endif +#ifdef USEAPI_ALSA + if (sys_audioapi == API_ALSA) + alsa_listdevs(); + else +#endif + post("unknown API"); + + sys_listmididevs(); +} + +void sys_setblocksize(int n) +{ + if (n < 1) + n = 1; + if (n != (1 << ilog2(n))) + post("warning: adjusting blocksize to power of 2: %d", + (n = (1 << ilog2(n)))); + sys_blocksize = n; +} + +void sys_set_sound_api(int which) +{ + sys_audioapi = which; + if (sys_verbose) + post("sys_audioapi %d", sys_audioapi); +} + -- cgit v1.2.1