[PD-cvs] pd/portaudio/pa_unix_oss low_latency_tip.txt,1.2,1.3 pa_unix_oss.c,1.2,1.3 recplay.c,1.2,1.3
Miller Puckette
millerpuckette at users.sourceforge.net
Mon Sep 6 22:44:43 CEST 2004
- Previous message: [PD-cvs] pd/portaudio/pa_unix pa_unix_hostapis.c,1.2,1.3 pa_unix_util.c,1.2,1.3
- Next message: [PD-cvs] pd/portaudio/pa_win pa_win_hostapis.c,1.2,1.3 pa_win_util.c,1.2,1.3 pa_x86_plain_converters.c,1.2,1.3 pa_x86_plain_converters.h,1.2,1.3
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Update of /cvsroot/pure-data/pd/portaudio/pa_unix_oss
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv15364/portaudio/pa_unix_oss
Added Files:
low_latency_tip.txt pa_unix_oss.c recplay.c
Log Message:
... more changes to try to upload 0.38 test 5 to CVS
--- 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.3 2004/09/06 20:44:41 millerpuckette Exp $
* PortAudio Portable Real-Time Audio Library
* Latest Version at: http://www.portaudio.com
* OSS implementation by:
* Douglas Repetto
* Phil Burk
* Dominic Mazzoni
*
* 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,
* subject to the following conditions:
[...1157 lines suppressed...]
else
return 0; /* TODO: is this right for "don't know"? */
}
static signed long GetStreamWriteAvailable( PaStream* s )
{
PaOSSStream *stream = (PaOSSStream*)s;
audio_buf_info info;
if ( ioctl(stream->deviceHandle, SNDCTL_DSP_GETOSPACE, &info) == 0)
{
int bytesAvailable = info.fragments * info.fragsize;
return ( bytesAvailable / 2 / stream->outputChannelCount );
}
else
return 0; /* TODO: is this right for "don't know"? */
}
--- NEW FILE: low_latency_tip.txt ---
From: "Benno Senoner" <sbenno at gardena.net>
To: <music-dsp at 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 at 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/
--
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/
- Previous message: [PD-cvs] pd/portaudio/pa_unix pa_unix_hostapis.c,1.2,1.3 pa_unix_util.c,1.2,1.3
- Next message: [PD-cvs] pd/portaudio/pa_win pa_win_hostapis.c,1.2,1.3 pa_win_util.c,1.2,1.3 pa_x86_plain_converters.c,1.2,1.3 pa_x86_plain_converters.h,1.2,1.3
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the Pd-cvs
mailing list