diff options
author | wiz <wiz@pkgsrc.org> | 2002-03-23 02:22:59 +0000 |
---|---|---|
committer | wiz <wiz@pkgsrc.org> | 2002-03-23 02:22:59 +0000 |
commit | 672215ec861f0e08861c82363b782f2e321c09bd (patch) | |
tree | 9d91d9629ccdfceac2fadc6025fd29bbda8b76c6 /audio/csound-bath/files | |
parent | 7205db5124228458f2b53fa6a36a7337787446df (diff) | |
download | pkgsrc-672215ec861f0e08861c82363b782f2e321c09bd.tar.gz |
Update to 4.18, provided by Ben Collver in pkg/14630.
Changes are unknown. Package changes:
* the c-preprocessor should now correctly chose whether to build big-endian
or little-endian specific code
* added support for NetBSD native audio API
Diffstat (limited to 'audio/csound-bath/files')
-rw-r--r-- | audio/csound-bath/files/rtNetBSD.c | 309 | ||||
-rw-r--r-- | audio/csound-bath/files/rtNetBSD.h | 20 |
2 files changed, 329 insertions, 0 deletions
diff --git a/audio/csound-bath/files/rtNetBSD.c b/audio/csound-bath/files/rtNetBSD.c new file mode 100644 index 00000000000..abc066f9d89 --- /dev/null +++ b/audio/csound-bath/files/rtNetBSD.c @@ -0,0 +1,309 @@ +/* + --- rtNetBSD.c --- + + Native NetBSD audio support. + + Ben Collver, collver@linuxfreemail.com +*/ + +#include <sys/types.h> +#include <sys/audioio.h> +#include <sys/ioctl.h> +#include <fcntl.h> +#include <stdio.h> +#include <unistd.h> + +#include "cs.h" +#include "soundio.h" +#include "rtNetBSD.h" + +static int dspfd; + +static int ishift = 0, oshift = 0, oMaxLag; +extern long nrecs; + long inrecs; +extern OPARMS O; +extern int Linefd; +#ifdef PIPES +extern FILE* Linepipe; +# define _pclose pclose +#endif + +static int getshift(int dsize) /* turn sample- or frame-size into shiftsize */ +{ + switch(dsize) { + case 1: return(0); + case 2: return(1); + case 4: return(2); + case 8: return(3); + default: die("rtaudio: illegal dsize"); + return(-1); /* Not reached */ + } +} + + +void display_audio_info( + int fd, + const char *message, + audio_info_t *info) +{ + audio_encoding_t encoding; + char *encoding_name; + + encoding.index = info->play.encoding; + if (ioctl(fd, AUDIO_GETENC, &encoding) == -1) { + asprintf(&encoding_name, "%d", info->play.encoding); + } else { + encoding_name = strdup(encoding.name); + } + printf("%-9s\n", message); + printf(" info.play.precision = %d\n", info->play.precision); + printf(" info.play.encoding = %s\n", encoding_name); + printf(" info.play.channels = %d\n", info->play.channels); + printf(" info.play.sample_rate = %d\n", info->play.sample_rate); + printf(" info.blocksize = %d\n\n", info->blocksize); + free(encoding_name); +} + +void setsndparms( + int fd, + int format, + int nchnls, + MYFLT esr, + unsigned bufsiz) +{ + audio_info_t info; + int count; + int frag_size; + + AUDIO_INITINFO(&info); + + switch (format) { + case AE_UNCH: + info.play.precision = 8; + info.play.encoding = AUDIO_ENCODING_ULINEAR; + break; + case AE_CHAR: + info.play.precision = 8; + info.play.encoding = AUDIO_ENCODING_SLINEAR; + break; + case AE_ULAW: + info.play.precision = 8; + info.play.encoding = AUDIO_ENCODING_ULAW; + break; + case AE_ALAW: + info.play.precision = 8; + info.play.encoding = AUDIO_ENCODING_ALAW; + break; + case AE_SHORT: + /* audio(4) says AUDIO_ENCODING_SLINEAR uses platform's + byte order, so the below will automatically be BE on + a BE system, and LE on a LE system. Good/Bad/Ok? */ + + info.play.precision = 16; + info.play.encoding = AUDIO_ENCODING_SLINEAR; + break; + case AE_LONG: + info.play.precision = 32; + info.play.encoding = AUDIO_ENCODING_SLINEAR; + break; + case AE_FLOAT: + die("NetBSD audio does not support floating-point samples"); + default: + die("unknown sample format"); + } + + info.play.channels = nchnls; + info.play.sample_rate = (unsigned int) esr; + + /* set DMA buffer fragment size to Csound's output buffer size */ + /* + * The or'ing is ABSOLUTELY crucial to obtaining quick response + * of csound to MIDI input - Please don't touch this line unless + * you know you can do better (in terms of MIDI response) + * [nicb@axnet.it] + */ + frag_size = 16; + count = 4; + while (frag_size < bufsiz && count < 18) { + frag_size <<= 1; + count++; + } + count |= 0x0020000; /* Larry Troxler's Idea */ + info.blocksize = frag_size; + + /* from ossaudio.c ioctl SNDCTL_DSP_SETFRAGMENT */ + info.hiwat = ((unsigned)count >> 16) & 0x7fff; + if (info.hiwat == 0) + info.hiwat = 65536; + + if (ioctl(fd, AUDIO_SETINFO, &info) == -1) { + display_audio_info(fd, "requested", &info); + if (ioctl(fd, AUDIO_GETINFO, &info) != -1) + display_audio_info(fd, "got", &info); + die("unable to configure soundcard"); + } +} + +int find_mixer_label(int fd, int class, const char *name) +{ + int i; + int mclass; + int retval = -1; + mixer_devinfo_t info; + + for (i = 0; ; i++) { + info.index = i; + if (ioctl(fd, AUDIO_MIXER_DEVINFO, &info) < 0) + break; + mclass = info.mixer_class; + if ((info.index == mclass || class == mclass) && + !strcmp(info.label.name, name)) + { + retval = i; + } + } + return retval; +} + +void setvolume(unsigned volume) +{ + int fd; + int i; + int output_class; + int vol_output; + mixer_devinfo_t info; + mixer_ctrl_t value; + + /* volume must be between 0 and 255 */ + + if ((fd = open(NETBSD_MIXER, O_WRONLY)) == -1) + die("unable to open soundcard mixer for setting volume"); + + output_class = find_mixer_label(fd, 0, "outputs"); + vol_output = find_mixer_label(fd, output_class, "master"); + + if (vol_output == -1) + die("Could not find mixer control for audio output."); + + + info.index = vol_output; + ioctl(fd, AUDIO_MIXER_DEVINFO, &info); + + value.dev = vol_output; + value.type = info.type; + value.un.value.num_channels = 2; + if (ioctl(fd, AUDIO_MIXER_READ, &value) < 0) { + value.un.value.num_channels = 1; + if (ioctl(fd, AUDIO_MIXER_READ, &value) < 0) + die("unable to read mixer on soundcard"); + } + + value.un.value.level[0] = 192; + value.un.value.level[1] = 192; + if (ioctl(fd, AUDIO_MIXER_WRITE, &value) < 0) { + die("unable to set output volume on soundcard"); + } +} + + +void NetBSD_open(int nchnls, int dsize, MYFLT esr, int scale, int audio_mode) +{ + int dup; + int wbufsiz; + int audio_props; + audio_device_t device_info; +#ifdef USE_SETSCHEDULER + extern void setscheduler(void); +#endif + + oMaxLag = O.oMaxLag; /* import DAC setting from command line */ + if (oMaxLag <= 0) /* if DAC sampframes ndef in command line */ + oMaxLag = IODACSAMPS; /* use the default value */ + wbufsiz = oMaxLag * O.insampsiz; + switch (audio_mode) { + case NETBSD_RECORD: + if ((dspfd = open(NETBSD_SAMPLER, O_RDONLY)) == -1) + die("error while opening soundcard for audio input"); + setsndparms(dspfd, O.informat, nchnls, esr, wbufsiz); + ishift = getshift(dsize); + break; + case NETBSD_PLAY: + if ((dspfd = open(NETBSD_SAMPLER, O_WRONLY)) == -1) { + perror("foo"); + die("error while opening soundcard for audio output"); + } + setsndparms(dspfd, O.outformat, nchnls, esr, wbufsiz); + /* 'oshift' is not currently used by the Linux driver, but... */ + oshift = getshift(nchnls * dsize); + break; + case NETBSD_DUPLEX: + if ((dspfd = open(NETBSD_SAMPLER, O_RDWR)) == -1) + die("error during soundcard duplex mode query:"); + ioctl(dspfd, AUDIO_GETPROPS, &audio_props); + if (!(audio_props | AUDIO_PROP_FULLDUPLEX)) + die("hardware does not support full duplex mode"); + setsndparms(dspfd, O.outformat, nchnls, esr, wbufsiz); + if (ioctl(dspfd, AUDIO_SETFD, audio_props) == -1) + die("error setting hardware to full duplex mode"); + /* are these functions both required? */ + oshift = getshift(nchnls * dsize); + ishift = getshift(dsize); + break; + default: + fprintf(stderr, "mode specification error in NetBSD_open: "); + fprintf(stderr, "unknown argument %d\n", audio_mode); + exit(1); + } + + ioctl(dspfd, AUDIO_GETDEV, &device_info); + fprintf(stderr, "NetBSD audio info: %s, %s, %s\n", + device_info.name, + device_info.version, + device_info.config); +#ifdef USE_SETSCHEDULER + setscheduler(); +#endif +} + +int rtrecord(char *inbuf, int nbytes) /* get samples from ADC */ +{ + /* J. Mohr 1995 Oct 17 */ + if ( (nbytes = read(dspfd, inbuf, nbytes)) == -1 ) + die("error while reading DSP device for audio input"); + return(nbytes); +} + +void rtplay(char *outbuf, int nbytes) /* put samples to DAC */ + /* N.B. This routine serves as a THROTTLE in Csound Realtime Performance, */ + /* delaying the actual writes and return until the hardware output buffer */ + /* passes a sample-specific THRESHOLD. If the I/O BLOCKING functionality */ + /* is implemented ACCURATELY by the vendor-supplied audio-library write, */ + /* that is sufficient. Otherwise, requires some kind of IOCTL from here. */ + /* This functionality is IMPORTANT when other realtime I/O is occurring, */ + /* such as when external MIDI data is being collected from a serial port. */ + /* Since Csound polls for MIDI input at the software synthesis K-rate */ + /* (the resolution of all software-synthesized events), the user can */ + /* eliminate MIDI jitter by requesting that both be made synchronous with */ + /* the above audio I/O blocks, i.e. by setting -b to some 1 or 2 K-prds. */ +{ + long sampframes = nbytes >> oshift; + /* J. Mohr 1995 Oct 17 */ + if (write(dspfd, outbuf, nbytes) < nbytes) + printf("/dev/audio: couldn't write all bytes requested\n"); + nrecs++; +} + +void rtclose(void) /* close the I/O device entirely */ +{ /* called only when both complete */ + /* J. Mohr 1995 Oct 17 */ + if (close(dspfd) == -1) + die("unable to close DSP device"); + if (O.Linein) { +#ifdef PIPES + if (O.Linename[0]=='|') _pclose(Linepipe); + else +#endif + if (strcmp(O.Linename, "stdin")!=0) close(Linefd); + } +} diff --git a/audio/csound-bath/files/rtNetBSD.h b/audio/csound-bath/files/rtNetBSD.h new file mode 100644 index 00000000000..c57ac466386 --- /dev/null +++ b/audio/csound-bath/files/rtNetBSD.h @@ -0,0 +1,20 @@ +/* rtNetBSD.h */ + +#ifndef _RTNETBSD_INCLUDED +#define _RTNETBSD_INCLUDED + +#define NETBSD_RECORD 0 +#define NETBSD_PLAY 1 +#define NETBSD_DUPLEX 2 + +#undef USE_SETSCHEDULER + +#define NETBSD_MIXER "/dev/mixer0" +#define NETBSD_SAMPLER "/dev/sound0" + +#define recopen(a,b,c,d) NetBSD_open(a,b,c,d,NETBSD_DUPLEX) +#define playopen(a,b,c,d) NetBSD_open(a,b,c,d,NETBSD_PLAY) + +extern void NetBSD_open(int, int, MYFLT, int, int); + +#endif /* _RTNETBSD_INCLUDED */ |