diff options
Diffstat (limited to 'audio/vat/files/patch-ah')
-rw-r--r-- | audio/vat/files/patch-ah | 577 |
1 files changed, 0 insertions, 577 deletions
diff --git a/audio/vat/files/patch-ah b/audio/vat/files/patch-ah deleted file mode 100644 index 596513307334..000000000000 --- a/audio/vat/files/patch-ah +++ /dev/null @@ -1,577 +0,0 @@ ---- audio-voxware.cc.orig Fri Apr 26 05:22:37 1996 -+++ audio-voxware.cc Sat May 10 00:15:51 2003 -@@ -1,4 +1,6 @@ - /* -+ * Modifications (C) 1997-1998 by Luigi Rizzo and others. -+ * - * Copyright (c) 1991-1993 Regents of the University of California. - * All rights reserved. - * -@@ -33,31 +35,43 @@ - static const char rcsid[] = - "@(#) $Header: audio-voxware.cc,v 1.10 96/04/26 05:22:05 van Exp $ (LBL)"; - --#include <string.h> --#include <sys/fcntl.h> --#include <errno.h> --#if defined(sco) || defined(__bsdi__) --#include <sys/socket.h> --#endif --#if defined(__FreeBSD__) --#include <sys/types.h> --#include <sys/uio.h> --#include <unistd.h> --#include <machine/soundcard.h> -+ -+/* -+ * Full Duplex audio module for the new sound driver and full duplex -+ * cards. Luigi Rizzo, from original sources supplied by Amancio Hasty. -+ * -+ * This includes some enhancements: -+ * - the audio device to use can be in the AUDIODEV env. variable. -+ * It can be either a unit number or a full pathname; -+ * - use whatever format is available from the card (included split -+ * format e.g. for the sb16); -+ * - limit the maximum size of the playout queue to approx 4 frames; -+ * this is necessary if the write channel is slower than expected; -+ * the fix is based on two new ioctls, AIOGCAP and AIONWRITE, -+ * but the code should compile with the old driver as well. -+ */ -+ -+#if !defined(__FreeBSD__) || (__FreeBSD__ < 4) -+#include <osfcn.h> - #else --#include <sys/soundcard.h> -+#include <fcntl.h> - #endif -+#include <sys/soundcard.h> - #include "audio.h" -+#include "mulaw.h" - #include "Tcl.h" - - #define ULAW_ZERO 0x7f -+ -+/* for use in the Voxware driver */ - #define ABUFLOG2 8 --#define ABUFLEN (1 << ABUFLOG2) - #define NFRAG 5 - --class VoxWareAudio : public Audio { -+extern const u_char lintomulawX[]; -+ -+class VoxWare : public Audio { - public: -- VoxWareAudio(); -+ VoxWare(); - virtual int FrameReady(); - virtual u_char* Read(); - virtual void Write(u_char *); -@@ -66,163 +80,415 @@ - virtual void OutputPort(int); - virtual void InputPort(int); - virtual void Obtain(); -+ virtual void Release(); - virtual void RMute(); - virtual void RUnmute(); - virtual int HalfDuplex() const; - protected: -+ int ext_fd; /* source for external file */ - -- u_char* readptr; -- u_char* readbufend; - u_char* readbuf; -+ u_short *s16_buf; -+ -+ int play_fmt ; -+ int is_half_duplex ; -+ -+ // new sound driver -+ int rec_fmt ; /* the sb16 has split format... */ -+ snd_capabilities soundcaps; - -- u_char* ubufptr; -- u_char* ubufend; -- u_char* ubuf; -- -- u_char* writeptr; -- u_char* writebufend; -- u_char* writebuf; - }; - --static class VoxWareAudioMatcher : public Matcher { -+static class VoxWareMatcher : public Matcher { - public: -- VoxWareAudioMatcher() : Matcher("audio") {} -+ VoxWareMatcher() : Matcher("audio") {} - TclObject* match(const char* fmt) { - if (strcmp(fmt, "voxware") == 0) -- return (new VoxWareAudio); -- else -+ return (new VoxWare); - return (0); - } --} voxware_audio_matcher; -+} linux_audio_matcher; - --VoxWareAudio::VoxWareAudio() -+VoxWare::VoxWare() - { -- readbuf = new u_char[ABUFLEN]; -- readptr = readbufend = readbuf + ABUFLEN; -+ readbuf = new u_char[blksize]; -+ s16_buf = new u_short[blksize]; - -- writeptr = writebuf = new u_char[ABUFLEN]; -- writebufend = writebuf + ABUFLEN; -+ memset(readbuf, ULAW_ZERO, blksize); - -- ubufptr = ubuf = new u_char[blksize]; -- ubufend = ubuf + blksize; -- memset(ubuf, ULAW_ZERO, blksize); -+ ext_fd = -1 ; /* no external audio */ -+ iports = 4; /* number of input ports */ - } - --int VoxWareAudio::HalfDuplex() const -+void -+VoxWare::Obtain() - { -- /*XXX change this if full duplex audio device available*/ -- return 1; --} -+ char *thedev; -+ char buf[64]; -+ int d = -1; - --void VoxWareAudio::Obtain() --{ - if (HaveAudio()) - abort(); -- -- fd = open("/dev/audio", O_RDWR|O_NDELAY); -+ is_half_duplex = 0 ; -+ /* -+ * variable AUDIODEV has the name of the audio device. -+ * With the new audio driver, the main device can also control -+ * the mixer, so there is no need to carry two descriptors around. -+ */ -+ thedev=getenv("AUDIODEV"); -+ if (thedev==NULL) -+ thedev="/dev/audio"; -+ else if ( thedev[0] >= '0' && thedev[0] <= '9' ) { -+ d = atoi(thedev); -+ sprintf(buf,"/dev/audio%d", d); -+ thedev = buf ; -+ } -+ fd = open(thedev, O_RDWR ); - if (fd >= 0) { -- int on = 1; -- ioctl(fd, FIONBIO, &on); -+ int i = -1 ; -+ u_long fmt = 0 ; -+ int rate = 8000 ; -+ -+ snd_chan_param pa; -+ struct snd_size sz; -+ i = ioctl(fd, AIOGCAP, &soundcaps); -+ fmt = soundcaps.formats ; /* can be invalid, check later */ -+ -+ play_fmt = AFMT_MU_LAW ; -+ rec_fmt = AFMT_MU_LAW ; -+ -+ if (i == -1 ) { /* setup code for old voxware driver */ -+ i = ioctl(fd, SNDCTL_DSP_GETFMTS, &fmt); -+ fmt &= AFMT_MU_LAW ; /* only use mu-law */ -+ fmt |= AFMT_FULLDUPLEX ; -+ if ( i < 0 ) { /* even voxware driver failed, try with pcaudio */ -+ fmt = AFMT_MU_LAW | AFMT_WEIRD ; -+ } -+ } -+ switch (soundcaps.formats & (AFMT_FULLDUPLEX | AFMT_WEIRD)) { -+ case AFMT_FULLDUPLEX : -+ /* -+ * this entry for cards with decent full duplex. Use s16 -+ * preferably (some are broken in ulaw) or ulaw or u8 otherwise. -+ */ -+ if (fmt & AFMT_S16_LE) -+ play_fmt = rec_fmt = AFMT_S16_LE ; -+ else if (soundcaps.formats & AFMT_MU_LAW) -+ play_fmt = rec_fmt = AFMT_MU_LAW ; -+ else if (soundcaps.formats & AFMT_U8) -+ play_fmt = rec_fmt = AFMT_U8 ; -+ else { -+ printf("sorry, no supported formats\n"); -+ close(fd); -+ fd = -1 ; -+ return; -+ } -+ break ; -+ case AFMT_FULLDUPLEX | AFMT_WEIRD : -+ /* this is the sb16... */ -+ if (fmt & AFMT_S16_LE) { -+ play_fmt = AFMT_U8 ; -+ rec_fmt = AFMT_S16_LE; -+ } else { -+ printf("sorry, no supported formats\n"); -+ close(fd); -+ fd = -1 ; -+ return; -+ } -+ break ; -+ default : -+ printf("sorry don't know how to deal with this card\n"); -+ close (fd); -+ fd = -1; -+ return; -+ } - -- int frag = (NFRAG << 16) | ABUFLOG2; -- ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &frag); --#ifdef fullduplex -+ pa.play_format = play_fmt ; -+ pa.rec_format = rec_fmt ; -+ pa.play_rate = pa.rec_rate = rate ; -+ ioctl(fd, AIOSFMT, &pa); /* if this fails, also AIOSSIZE will.. */ -+ sz.play_size = (play_fmt == AFMT_S16_LE) ? 2*blksize : blksize; -+ sz.rec_size = (rec_fmt == AFMT_S16_LE) ? 2*blksize : blksize; -+ i = ioctl(fd, AIOSSIZE, &sz); -+ -+ /* -+ * Set the line input level to 0 to avoid loopback if the mic -+ * is connected to the line-in port (e.g. through an echo -+ * canceller). -+ */ -+ int v = 0; -+ (void)ioctl(fd, MIXER_WRITE(SOUND_MIXER_LINE), &v); -+ // restore hardware settings in case some other vat changed them -+ InputPort(iport); -+ SetRGain(rgain); -+ SetPGain(pgain); -+ -+ if ( i < 0 ) { // if AIOSSIZE fails, maybe this is a Voxware driver -+ ioctl(fd, SNDCTL_DSP_SPEED, &rate); -+ ioctl(fd, SNDCTL_DSP_SETFMT, &play_fmt); // same for play/rec -+ d = (play_fmt == AFMT_S16_LE) ? 2*blksize : blksize; -+ ioctl(fd, SNDCTL_DSP_SETBLKSIZE, &d); -+ read(fd, &i, 1); /* dummy read to start read engine */ -+ } - Audio::Obtain(); --#else -- notify(); --#endif -+ } else { -+ fprintf(stderr, "failed to open rw...\n"); -+ fd = open(thedev, O_WRONLY ); -+ fprintf(stderr, "open wronly returns %d\n", fd); -+ is_half_duplex = 1 ; -+ play_fmt = rec_fmt = AFMT_MU_LAW ; -+ notify(); /* XXX */ - } - } - --void VoxWareAudio::Write(u_char *cp) -+/* -+ * note: HalfDuplex() uses a modified function of the new driver, -+ * which will return AFMT_FULLDUPLEX set in SNDCTL_DSP_GETFMTS -+ * for full-duplex devices. In the old driver this was 0 so -+ * the default is to use half-duplex for them. Note also that I have -+ * not tested half-duplex operation. -+ */ -+int -+VoxWare::HalfDuplex() const - { -- if (HaveAudio() && (rmute & 1) != 0) { -- register u_char *cpend = cp + blksize; -- register u_char *wbuf = writeptr; -- register u_char *wend = writebufend; -- for ( ; cp < cpend; cp += 4) { -- wbuf[0] = cp[0]; -- wbuf[1] = cp[1]; -- wbuf[2] = cp[2]; -- wbuf[3] = cp[3]; -- wbuf += 4; -- if (wbuf >= wend) { -- wbuf = writebuf; -- if (write(fd, (char*)wbuf, ABUFLEN) != ABUFLEN) -- perror("aud write"); -- } -- } -- writeptr = wbuf; -+ int i, probed_duplex = 0; -+ -+ /* newpcm style */ -+#ifdef SNDCTL_DSP_GETCAPS -+ ioctl(fd, SNDCTL_DSP_GETCAPS, &i); -+ probed_duplex |= (i & DSP_CAP_DUPLEX); -+#endif /* SNDCTL_DSP_GETCAPS */ -+ -+ /* pcm style */ -+#ifdef SNDCTL_DSP_GETFMTS -+ ioctl(fd, SNDCTL_DSP_GETFMTS, &i); -+ probed_duplex |= (i & AFMT_FULLDUPLEX); -+#endif /* SNDCTL_DSP_GETFMTS */ -+ -+ if (is_half_duplex || (probed_duplex == 0)) { -+ fprintf(stderr, "HalfDuplex returns 1\n"); -+ return 1 ; - } -+ -+ return 0; - } - --int VoxWareAudio::FrameReady() -+void VoxWare::Release() - { -- if ((rmute & 1) == 0) { -- register u_char* cp = ubufptr; -- register u_char* cpend = ubufend; -- register u_char* rbuf = readptr; -- register u_char* rend = readbufend; -- -- for ( ; cp < cpend; cp += 4) { -- if (rbuf >= rend) { -- rbuf = readbuf; -- int cc = read(fd, (char*)rbuf, ABUFLEN); -- if (cc <= 0) { -- ubufptr = cp; -- readbufend = rbuf; -- if (cc == -1 && errno != EAGAIN) { -- Release(); -- Obtain(); -- } -- return (0); -+ if (HaveAudio()) { -+ Audio::Release(); - } -- readbufend = rend = rbuf + cc; - } -- cp[0] = rbuf[0]; -- cp[1] = rbuf[1]; -- cp[2] = rbuf[2]; -- cp[3] = rbuf[3]; -- rbuf += 4; -+ -+void VoxWare::Write(u_char *cp) -+{ -+ int i = blksize, l; -+ if (play_fmt == AFMT_S16_LE) { -+ for (i=0; i< blksize; i++) -+ s16_buf[i] = mulawtolin[cp[i]] ; -+ cp = (u_char *)s16_buf; -+ i = 2 *blksize ; -+ } else if (play_fmt == AFMT_S8) { -+ for (i=0; i< blksize; i++) { -+ int x = mulawtolin[cp[i]] ; -+ x = (x >> 8 ) & 0xff; -+ cp[i] = (u_char)x ; -+ } -+ i = blksize ; -+ } else if (play_fmt == AFMT_U8) { -+ for (i=0; i< blksize; i++) { -+ int x = mulawtolin[cp[i]] ; -+ /* -+ * when translating to 8-bit formats, it would be useful to -+ * implement AGC to avoid loss of resolution in the conversion. -+ * This code is still incomplete... -+ */ -+#if 0 /* AGC -- still not complete... */ -+ static int peak = 0; -+ if (x < 0) x = -x ; -+ if (x > peak) peak = ( peak*16 + x - peak ) / 16 ; -+ else peak = ( peak*8192 + x - peak ) / 8192 ; -+ if (peak < 128) peak = 128 ; -+ /* at this point peak is in the range 128..32k -+ * samples can be scaled and clipped consequently. -+ */ -+ x = x * 32768/peak ; -+ if (x > 32767) x = 32767; -+ else if (x < -32768) x = -32768; -+#endif -+ x = (x >> 8 ) & 0xff; -+ x = (x ^ 0x80) & 0xff ; -+ cp[i] = (u_char)x ; -+ } -+ i = blksize ; -+ } -+#if 0 -+ // this code is meant to keep the queue short. -+ int r, queued; -+ r = ioctl(fd, AIONWRITE, &queued); -+ queued = soundcaps.bufsize - queued ; -+ if (play_fmt == AFMT_S16_LE) { -+ if (queued > 8*blksize) -+ i -= 8 ; -+ } else { -+ if (queued > 4*blksize) -+ i -= 4 ; - } -- readptr = rbuf; -+#endif -+ for ( ; i > 0 ; i -= l) { -+ l = write(fd, cp, i); -+ cp += l; - } -- return (1); - } - --u_char* VoxWareAudio::Read() -+u_char* VoxWare::Read() - { -- u_char* cp = ubuf; -- ubufptr = cp; -- return (cp); -+ u_char* cp; -+ int l=0, l0 = blksize, i = blksize; -+ -+ cp = readbuf; -+ -+ if (rec_fmt == AFMT_S16_LE) { -+ cp = (u_char *)s16_buf; -+ l0 = i = 2 *blksize ; -+ } -+ for ( ; i > 0 ; i -= l ) { -+ l = read(fd, cp, i); -+ if (l<0) break; -+ cp += l ; -+ } -+ if (rec_fmt == AFMT_S16_LE) { -+ for (i=0; i< blksize; i++) { -+#if 1 /* remove DC component... */ -+ static int smean = 0 ; /* smoothed mean to remove DC */ -+ int dif = ((short) s16_buf[i]) - (smean >> 13) ; -+ smean += dif ; -+ readbuf[i] = lintomulawX[ dif & 0x1ffff ] ; -+#else -+ readbuf[i] = lintomulaw[ s16_buf[i] ] ; -+#endif -+ } -+ } -+ else if (rec_fmt == AFMT_S8) { -+ for (i=0; i< blksize; i++) -+ readbuf[i] = lintomulaw[ readbuf[i]<<8 ] ; -+ } -+ else if (rec_fmt == AFMT_U8) { -+ for (i=0; i< blksize; i++) -+ readbuf[i] = lintomulaw[ (readbuf[i]<<8) ^ 0x8000 ] ; -+ } -+ if (iport == 3) { -+ l = read(ext_fd, readbuf, blksize); -+ if (l < blksize) { -+ lseek(ext_fd, (off_t) 0, 0); -+ read(ext_fd, readbuf+l, blksize - l); -+ } -+ } -+ return readbuf; - } - --void VoxWareAudio::SetRGain(int level) -+/* -+ * should check that I HaveAudio() before trying to set gain. -+ * -+ * In most mixer devices, there is only a master volume control on -+ * the capture channel, so the following code does not really work -+ * as expected. The only (partial) exception is the MIC line, where -+ * there is generally a 20dB boost which can be enabled or not -+ * depending on the type of device. -+ */ -+void VoxWare::SetRGain(int level) - { -+ double x = level; -+ level = (int) (x/2.56); -+ int foo = (level<<8) | level; -+ if (!HaveAudio()) -+ Obtain(); -+ switch (iport) { -+ case 2: -+ case 1: -+ break; -+ case 0: -+ if (ioctl(fd, MIXER_WRITE(SOUND_MIXER_MIC), &foo) == -1) -+ printf("failed to set mic volume \n"); -+ break; -+ } -+ /* IGAIN tends to be found on SB-like mixers, RECLEV on AC97 */ -+ if ((ioctl(fd, MIXER_WRITE(SOUND_MIXER_IGAIN), &foo) == -1) && -+ (ioctl(fd, MIXER_WRITE(SOUND_MIXER_RECLEV), &foo) == -1)) -+ printf("failed set input line volume \n"); - rgain = level; - } - --void VoxWareAudio::SetPGain(int level) -+void VoxWare::SetPGain(int level) - { -+ float x = level; -+ level = (int) (x/2.56); -+ int foo = (level<<8) | level; -+ if (ioctl(fd, MIXER_WRITE(SOUND_MIXER_PCM), &foo) == -1) { -+ printf("failed to output level %d \n", level); -+ } - pgain = level; - } - --void VoxWareAudio::OutputPort(int p) -+void VoxWare::OutputPort(int p) - { - oport = p; - } - --void VoxWareAudio::InputPort(int p) -+void VoxWare::InputPort(int p) - { -+ int src = 0; -+ -+ if (ext_fd >= 0 && p != 3) { -+ close(ext_fd); -+ ext_fd = -1 ; -+ } -+ -+ switch(p) { -+ case 3: -+ if (ext_fd == -1) -+ ext_fd = open(ext_fname, 0); -+ if (ext_fd != -1) -+ lseek(ext_fd, (off_t) 0, 0); -+ break; -+ case 2: -+ src = 1 << SOUND_MIXER_LINE; -+ break; -+ case 1: /* cd ... */ -+ src = 1 << SOUND_MIXER_CD; -+ break; -+ case 0 : -+ src = 1 << SOUND_MIXER_MIC; -+ break; -+ } -+ if ( ioctl(fd, SOUND_MIXER_WRITE_RECSRC, &src) == -1 ) { -+ printf("failed to select input \n"); -+ p = 0; -+ } - iport = p; - } - --void VoxWareAudio::RMute() -+void VoxWare::RMute() - { - rmute |= 1; - } - --void VoxWareAudio::RUnmute() -+void VoxWare::RUnmute() - { - rmute &=~ 1; - } -+ -+/* -+ * FrameReady must return 0 every so often, or the system will keep -+ * processing mike data and not other events. -+ */ -+int VoxWare::FrameReady() -+{ -+ int i, l = 0; -+ int lim = blksize; -+ -+ i = ioctl(fd, FIONREAD, &l ); -+ if (rec_fmt == AFMT_S16_LE) lim = 2*blksize; -+ return (l >= lim) ? 1 : 0 ; -+} -+/*** end of file ***/ |