[PD-cvs] pd/portaudio/src/hostapi/oss low_latency_tip.txt, NONE, 1.1 pa_unix_oss.c, NONE, 1.1 recplay.c, NONE, 1.1

Miller Puckette millerpuckette at users.sourceforge.net
Sun Aug 19 01:49:35 CEST 2007


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 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/

 




More information about the Pd-cvs mailing list