Update of /cvsroot/pure-data/pd/portaudio/src/hostapi/oss In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv19525/portaudio/src/hostapi/oss
Added Files: low_latency_tip.txt pa_unix_oss.c recplay.c Log Message: CVS upload mistakes
--- NEW FILE: recplay.c --- /* * recplay.c * Phil Burk * Minimal record and playback test. * */ #include <stdio.h> #include <unistd.h> #include <stdlib.h> #ifndef __STDC__ /* #include <getopt.h> */ #endif /* __STDC__ */ #include <fcntl.h> #ifdef __STDC__ #include <string.h> #else /* __STDC__ */ #include <strings.h> #endif /* __STDC__ */ #include <sys/soundcard.h>
#define NUM_BYTES (64*1024) #define BLOCK_SIZE (4*1024)
#define AUDIO "/dev/dsp"
char buffer[NUM_BYTES];
int audioDev = 0;
main (int argc, char *argv[]) { int numLeft; char *ptr; int num; int samplesize;
/********** RECORD ********************/ /* Open audio device. */ audioDev = open (AUDIO, O_RDONLY, 0); if (audioDev == -1) { perror (AUDIO); exit (-1); }
/* Set to 16 bit samples. */ samplesize = 16; ioctl(audioDev, SNDCTL_DSP_SAMPLESIZE, &samplesize); if (samplesize != 16) { perror("Unable to set the sample size."); exit(-1); }
/* Record in blocks */ printf("Begin recording.\n"); numLeft = NUM_BYTES; ptr = buffer; while( numLeft >= BLOCK_SIZE ) { if ( (num = read (audioDev, ptr, BLOCK_SIZE)) < 0 ) { perror (AUDIO); exit (-1); } else { printf("Read %d bytes\n", num); ptr += num; numLeft -= num; } }
close( audioDev );
/********** PLAYBACK ********************/ /* Open audio device for writing. */ audioDev = open (AUDIO, O_WRONLY, 0); if (audioDev == -1) { perror (AUDIO); exit (-1); }
/* Set to 16 bit samples. */ samplesize = 16; ioctl(audioDev, SNDCTL_DSP_SAMPLESIZE, &samplesize); if (samplesize != 16) { perror("Unable to set the sample size."); exit(-1); }
/* Play in blocks */ printf("Begin playing.\n"); numLeft = NUM_BYTES; ptr = buffer; while( numLeft >= BLOCK_SIZE ) { if ( (num = write (audioDev, ptr, BLOCK_SIZE)) < 0 ) { perror (AUDIO); exit (-1); } else { printf("Wrote %d bytes\n", num); ptr += num; numLeft -= num; } }
close( audioDev ); }
--- NEW FILE: pa_unix_oss.c --- /* * $Id: pa_unix_oss.c,v 1.1 2007/08/18 23:49:33 millerpuckette Exp $ * PortAudio Portable Real-Time Audio Library * Latest Version at: http://www.portaudio.com * OSS implementation by: * Douglas Repetto * Phil Burk * Dominic Mazzoni * Arve Knudsen * * Based on the Open Source API proposed by Ross Bencina * Copyright (c) 1999-2002 Ross Bencina, 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, [...1907 lines suppressed...] audio_buf_info info;
if( ioctl( stream->capture->fd, SNDCTL_DSP_GETISPACE, &info ) < 0 ) return paUnanticipatedHostError; return info.fragments * stream->capture->hostFrames; }
/* TODO: Compute number of allocated bytes somewhere else, can we use ODELAY with capture */ static signed long GetStreamWriteAvailable( PaStream* s ) { PaOssStream *stream = (PaOssStream*)s; int delay = 0;
if( ioctl( stream->playback->fd, SNDCTL_DSP_GETODELAY, &delay ) < 0 ) return paUnanticipatedHostError;
return (PaOssStreamComponent_BufferSize( stream->playback ) - delay) / PaOssStreamComponent_FrameSize( stream->playback ); }
--- NEW FILE: low_latency_tip.txt --- From: "Benno Senoner" sbenno@gardena.net To: music-dsp@shoko.calarts.edu Subject: Re: [music-dsp] coding realtime guitar efx on a "pc" Date: Saturday, June 30, 2001 8:19 AM
Andrè, you are solving your problem the wrong way: you need to use a single threaded solution which does this:
- set the audio I/O parameters to fragnum=4 fragsize=128 bytes (=32samples) if you use stereo or fragsize=64 bytes (=32 samples) if you use mono.
(do not forget to activate fulltuplex with using the _TRIGGER_ stuff) (you need to frist deactivate audio and then start the trigger after the DAC is prefilled (see below))
This will give you a total input to output latency of 4x32 samples = 128 samples which at 44.1kHz correspond to 2.9msec latency.
now set your process to SCHED_FIFO (see man sched_setscheduler)
after the initialization your code should do more than less this:
- write() 4 x 32 samples to the audio fd in order to prefill the DAC. Without this you will get dropouts.
while(1) { read() 32 samples from ADC perform_dsp_stuff() on the 32 samples write() 32 samples to DAC }
If you use a low latency kernel and pay attention to all the stuff above, then you will get rock solid 3msec latencies (plus eventual converter latencies but these are in the 1-2msec range AFAIK).
Using multiple threads , pipes etc, only complicates your life and often makes it impossible to achieve these low latences.
Realtime/audio programming is not an easy task , this is why people often fail to get the desired results even if their hardware is low-latency capable.
The problem is that the final latency depends on the hardware you use, the application and the operating system.
cheers, Benno.
http://www.linuxaudiodev.org The Home of Linux Audio Development
On Sat, 30 Jun 2001, you wrote:
On 2001-06-29 21:38 +0200, Benno Senoner wrote:
OSS/Free refuses to use a low # of frags ?
That's a myth.
I hope it is. :-)
The fact is that ioctl(SNDCTL_DSP_SETFRAGMENT) succeeds with values as low a 0x10007 (one 128-B fragment) but the latency is still high enough to be clearly noticeable, which suggests that it's *way* above 2/3 ms. This is on an otherwise idle machine equipped with a SB PCI 128.
But maybe it's me who's doing something wrong. I've been careful to flush stdio buffers or use unbuffered I/O (write(2)) but I may have let something else through.
For example, since the signal processing and the I/O are done by two different vanilla processes communicating via pipes, it may be a scheduling granularity problem (E.G. the kernel giving the I/O process a time slice every 20 ms).
-- André Majorel amajorel@teaser.fr http://www.teaser.fr/~amajorel/
dupswapdrop -- the music-dsp mailing list and website: subscription info, FAQ, source code archive, list archive, book reviews, dsp links http://shoko.calarts.edu/musicdsp/