[PD-cvs] pd/portaudio/pa_common pa_cpuload.c,1.2,1.3 pa_cpuload.h,1.2,1.3 pa_dither.c,1.2,1.3 pa_dither.h,1.2,1.3 pa_endianness.h,1.2,1.3 pa_front.c,1.2,1.3 pa_hostapi.h,1.2,1.3 pa_process.c,1.2,1.3 pa_process.h,1.2,1.3 pa_skeleton.c,1.2,1.3 pa_stream.c,1.2,1.3 pa_stream.h,1.2,1.3 pa_trace.c,1.2,1.3 pa_trace.h,1.2,1.3 pa_util.h,1.2,1.3 portaudio.h,1.2,1.3

Miller Puckette millerpuckette at users.sourceforge.net
Mon Sep 6 22:44:41 CEST 2004


Update of /cvsroot/pure-data/pd/portaudio/pa_common
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv15364/portaudio/pa_common

Added Files:
	pa_cpuload.c pa_cpuload.h pa_dither.c pa_dither.h 
	pa_endianness.h pa_front.c pa_hostapi.h pa_process.c 
	pa_process.h pa_skeleton.c pa_stream.c pa_stream.h pa_trace.c 
	pa_trace.h pa_util.h portaudio.h 
Log Message:
... more changes to try to upload 0.38 test 5 to CVS



--- NEW FILE: pa_skeleton.c ---
/*
 * $Id: pa_skeleton.c,v 1.3 2004/09/06 20:44:38 millerpuckette Exp $
 * Portable Audio I/O Library skeleton implementation
 * demonstrates how to use the common functions to implement support
 * for a host API
 *
 * 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:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * Any person wishing to distribute modifications to the Software is
 * requested to send the modifications to the original developer so that
 * they can be incorporated into the canonical version.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/** @file
 @brief Skeleton implementation of support for a host API.

 @note This file is provided as a starting point for implementing support for
 a new host API. IMPLEMENT ME comments are used to indicate functionality
 which much be customised for each implementation.
*/


#include <string.h> /* strlen() */

#include "pa_util.h"
#include "pa_allocation.h"
#include "pa_hostapi.h"
#include "pa_stream.h"
#include "pa_cpuload.h"
#include "pa_process.h"


/* prototypes for functions declared in this file */

#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */

PaError PaSkeleton_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );

#ifdef __cplusplus
}
#endif /* __cplusplus */


static void Terminate( struct PaUtilHostApiRepresentation *hostApi );
static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
                                  const PaStreamParameters *inputParameters,
                                  const PaStreamParameters *outputParameters,
                                  double sampleRate );
static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
                           PaStream** s,
                           const PaStreamParameters *inputParameters,
                           const PaStreamParameters *outputParameters,
                           double sampleRate,
                           unsigned long framesPerBuffer,
                           PaStreamFlags streamFlags,
                           PaStreamCallback *streamCallback,
                           void *userData );
static PaError CloseStream( PaStream* stream );
static PaError StartStream( PaStream *stream );
static PaError StopStream( PaStream *stream );
static PaError AbortStream( PaStream *stream );
static PaError IsStreamStopped( PaStream *s );
static PaError IsStreamActive( PaStream *stream );
static PaTime GetStreamTime( PaStream *stream );
static double GetStreamCpuLoad( PaStream* stream );
static PaError ReadStream( PaStream* stream, void *buffer, unsigned long frames );
static PaError WriteStream( PaStream* stream, const void *buffer, unsigned long frames );
static signed long GetStreamReadAvailable( PaStream* stream );
static signed long GetStreamWriteAvailable( PaStream* stream );


/* IMPLEMENT ME: a macro like the following one should be used for reporting
 host errors */
#define PA_SKELETON_SET_LAST_HOST_ERROR( errorCode, errorText ) \
    PaUtil_SetLastHostErrorInfo( paInDevelopment, errorCode, errorText )

/* PaSkeletonHostApiRepresentation - host api datastructure specific to this implementation */

typedef struct
{
    PaUtilHostApiRepresentation inheritedHostApiRep;
    PaUtilStreamInterface callbackStreamInterface;
    PaUtilStreamInterface blockingStreamInterface;

    PaUtilAllocationGroup *allocations;

    /* implementation specific data goes here */
}
PaSkeletonHostApiRepresentation;  /* IMPLEMENT ME: rename this */


PaError PaSkeleton_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex )
{
    PaError result = paNoError;
    int i, deviceCount;
    PaSkeletonHostApiRepresentation *skeletonHostApi;
    PaDeviceInfo *deviceInfoArray;

    skeletonHostApi = (PaSkeletonHostApiRepresentation*)PaUtil_AllocateMemory( sizeof(PaSkeletonHostApiRepresentation) );
    if( !skeletonHostApi )
    {
        result = paInsufficientMemory;
        goto error;
    }

    skeletonHostApi->allocations = PaUtil_CreateAllocationGroup();
    if( !skeletonHostApi->allocations )
    {
        result = paInsufficientMemory;
        goto error;
    }

    *hostApi = &skeletonHostApi->inheritedHostApiRep;
    (*hostApi)->info.structVersion = 1;
    (*hostApi)->info.type = paInDevelopment;            /* IMPLEMENT ME: change to correct type id */
    (*hostApi)->info.name = "skeleton implementation";  /* IMPLEMENT ME: change to correct name */

    (*hostApi)->info.defaultInputDevice = paNoDevice;  /* IMPLEMENT ME */
    (*hostApi)->info.defaultOutputDevice = paNoDevice; /* IMPLEMENT ME */

    (*hostApi)->info.deviceCount = 0;  

    deviceCount = 0; /* IMPLEMENT ME */
    
    if( deviceCount > 0 )
    {
        (*hostApi)->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory(
                skeletonHostApi->allocations, sizeof(PaDeviceInfo*) * deviceCount );
        if( !(*hostApi)->deviceInfos )
        {
            result = paInsufficientMemory;
            goto error;
        }

        /* allocate all device info structs in a contiguous block */
        deviceInfoArray = (PaDeviceInfo*)PaUtil_GroupAllocateMemory(
                skeletonHostApi->allocations, sizeof(PaDeviceInfo) * deviceCount );
        if( !deviceInfoArray )
        {
            result = paInsufficientMemory;
            goto error;
        }

        for( i=0; i < deviceCount; ++i )
        {
            PaDeviceInfo *deviceInfo = &deviceInfoArray[i];
            deviceInfo->structVersion = 2;
            deviceInfo->hostApi = hostApiIndex;
            deviceInfo->name = 0; /* IMPLEMENT ME: allocate block and copy name eg:
                deviceName = (char*)PaUtil_GroupAllocateMemory( skeletonHostApi->allocations, strlen(srcName) + 1 );
                if( !deviceName )
                {
                    result = paInsufficientMemory;
                    goto error;
                }
                strcpy( deviceName, srcName );
                deviceInfo->name = deviceName;
            */

            deviceInfo->maxInputChannels = 0;  /* IMPLEMENT ME */
            deviceInfo->maxOutputChannels = 0;  /* IMPLEMENT ME */
            
            deviceInfo->defaultLowInputLatency = 0.;  /* IMPLEMENT ME */
            deviceInfo->defaultLowOutputLatency = 0.;  /* IMPLEMENT ME */
            deviceInfo->defaultHighInputLatency = 0.;  /* IMPLEMENT ME */
            deviceInfo->defaultHighOutputLatency = 0.;  /* IMPLEMENT ME */  

            deviceInfo->defaultSampleRate = 0.; /* IMPLEMENT ME */
            
            (*hostApi)->deviceInfos[i] = deviceInfo;
            ++(*hostApi)->info.deviceCount;
        }
    }

    (*hostApi)->Terminate = Terminate;
    (*hostApi)->OpenStream = OpenStream;
    (*hostApi)->IsFormatSupported = IsFormatSupported;

    PaUtil_InitializeStreamInterface( &skeletonHostApi->callbackStreamInterface, CloseStream, StartStream,
                                      StopStream, AbortStream, IsStreamStopped, IsStreamActive,
                                      GetStreamTime, GetStreamCpuLoad,
                                      PaUtil_DummyRead, PaUtil_DummyWrite,
                                      PaUtil_DummyGetReadAvailable, PaUtil_DummyGetWriteAvailable );

    PaUtil_InitializeStreamInterface( &skeletonHostApi->blockingStreamInterface, CloseStream, StartStream,
                                      StopStream, AbortStream, IsStreamStopped, IsStreamActive,
                                      GetStreamTime, PaUtil_DummyGetCpuLoad,
                                      ReadStream, WriteStream, GetStreamReadAvailable, GetStreamWriteAvailable );

    return result;

error:
    if( skeletonHostApi )
    {
        if( skeletonHostApi->allocations )
        {
            PaUtil_FreeAllAllocations( skeletonHostApi->allocations );
            PaUtil_DestroyAllocationGroup( skeletonHostApi->allocations );
        }
                
        PaUtil_FreeMemory( skeletonHostApi );
    }
    return result;
}


static void Terminate( struct PaUtilHostApiRepresentation *hostApi )
{
    PaSkeletonHostApiRepresentation *skeletonHostApi = (PaSkeletonHostApiRepresentation*)hostApi;

    /*
        IMPLEMENT ME:
            - clean up any resources not handled by the allocation group
    */

    if( skeletonHostApi->allocations )
    {
        PaUtil_FreeAllAllocations( skeletonHostApi->allocations );
        PaUtil_DestroyAllocationGroup( skeletonHostApi->allocations );
    }

    PaUtil_FreeMemory( skeletonHostApi );
}


static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
                                  const PaStreamParameters *inputParameters,
                                  const PaStreamParameters *outputParameters,
                                  double sampleRate )
{
    int inputChannelCount, outputChannelCount;
    PaSampleFormat inputSampleFormat, outputSampleFormat;
    
    if( inputParameters )
    {
        inputChannelCount = inputParameters->channelCount;
        inputSampleFormat = inputParameters->sampleFormat;

        /* all standard sample formats are supported by the buffer adapter,
            this implementation doesn't support any custom sample formats */
        if( inputSampleFormat & paCustomFormat )
            return paSampleFormatNotSupported;
            
        /* unless alternate device specification is supported, reject the use of
            paUseHostApiSpecificDeviceSpecification */

        if( inputParameters->device == paUseHostApiSpecificDeviceSpecification )
            return paInvalidDevice;

        /* check that input device can support inputChannelCount */
        if( inputChannelCount > hostApi->deviceInfos[ inputParameters->device ]->maxInputChannels )
            return paInvalidChannelCount;

        /* validate inputStreamInfo */
        if( inputParameters->hostApiSpecificStreamInfo )
            return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
    }
    else
    {
        inputChannelCount = 0;
    }

    if( outputParameters )
    {
        outputChannelCount = outputParameters->channelCount;
        outputSampleFormat = outputParameters->sampleFormat;

        /* all standard sample formats are supported by the buffer adapter,
            this implementation doesn't support any custom sample formats */
        if( outputSampleFormat & paCustomFormat )
            return paSampleFormatNotSupported;
            
        /* unless alternate device specification is supported, reject the use of
            paUseHostApiSpecificDeviceSpecification */

        if( outputParameters->device == paUseHostApiSpecificDeviceSpecification )
            return paInvalidDevice;

        /* check that output device can support outputChannelCount */
        if( outputChannelCount > hostApi->deviceInfos[ outputParameters->device ]->maxOutputChannels )
            return paInvalidChannelCount;

        /* validate outputStreamInfo */
        if( outputParameters->hostApiSpecificStreamInfo )
            return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
    }
    else
    {
        outputChannelCount = 0;
    }
    
    /*
        IMPLEMENT ME:

            - if a full duplex stream is requested, check that the combination
                of input and output parameters is supported if necessary

            - check that the device supports sampleRate

        Because the buffer adapter handles conversion between all standard
        sample formats, the following checks are only required if paCustomFormat
        is implemented, or under some other unusual conditions.

            - check that input device can support inputSampleFormat, or that
                we have the capability to convert from inputSampleFormat to
                a native format

            - check that output device can support outputSampleFormat, or that
                we have the capability to convert from outputSampleFormat to
                a native format
    */


    /* suppress unused variable warnings */
    (void) sampleRate;

    return paFormatIsSupported;
}

/* PaSkeletonStream - a stream data structure specifically for this implementation */

typedef struct PaSkeletonStream
{ /* IMPLEMENT ME: rename this */
    PaUtilStreamRepresentation streamRepresentation;
    PaUtilCpuLoadMeasurer cpuLoadMeasurer;
    PaUtilBufferProcessor bufferProcessor;

    /* IMPLEMENT ME:
            - implementation specific data goes here
    */
    unsigned long framesPerHostCallback; /* just an example */
}
PaSkeletonStream;

/* see pa_hostapi.h for a list of validity guarantees made about OpenStream parameters */

static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
                           PaStream** s,
                           const PaStreamParameters *inputParameters,
                           const PaStreamParameters *outputParameters,
                           double sampleRate,
                           unsigned long framesPerBuffer,
                           PaStreamFlags streamFlags,
                           PaStreamCallback *streamCallback,
                           void *userData )
{
    PaError result = paNoError;
    PaSkeletonHostApiRepresentation *skeletonHostApi = (PaSkeletonHostApiRepresentation*)hostApi;
    PaSkeletonStream *stream = 0;
    unsigned long framesPerHostBuffer = framesPerBuffer; /* these may not be equivalent for all implementations */
    int inputChannelCount, outputChannelCount;
    PaSampleFormat inputSampleFormat, outputSampleFormat;
    PaSampleFormat hostInputSampleFormat, hostOutputSampleFormat;


    if( inputParameters )
    {
        inputChannelCount = inputParameters->channelCount;
        inputSampleFormat = inputParameters->sampleFormat;

        /* unless alternate device specification is supported, reject the use of
            paUseHostApiSpecificDeviceSpecification */

        if( inputParameters->device == paUseHostApiSpecificDeviceSpecification )
            return paInvalidDevice;

        /* check that input device can support inputChannelCount */
        if( inputChannelCount > hostApi->deviceInfos[ inputParameters->device ]->maxInputChannels )
            return paInvalidChannelCount;

        /* validate inputStreamInfo */
        if( inputParameters->hostApiSpecificStreamInfo )
            return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */

        /* IMPLEMENT ME - establish which  host formats are available */
        hostInputSampleFormat =
            PaUtil_SelectClosestAvailableFormat( paInt16 /* native formats */, inputSampleFormat );
    }
    else
    {
        inputChannelCount = 0;
        inputSampleFormat = hostInputSampleFormat = paInt16; /* Surpress 'uninitialised var' warnings. */
    }

    if( outputParameters )
    {
        outputChannelCount = outputParameters->channelCount;
        outputSampleFormat = outputParameters->sampleFormat;
        
        /* unless alternate device specification is supported, reject the use of
            paUseHostApiSpecificDeviceSpecification */

        if( outputParameters->device == paUseHostApiSpecificDeviceSpecification )
            return paInvalidDevice;

        /* check that output device can support inputChannelCount */
        if( outputChannelCount > hostApi->deviceInfos[ outputParameters->device ]->maxOutputChannels )
            return paInvalidChannelCount;

        /* validate outputStreamInfo */
        if( outputParameters->hostApiSpecificStreamInfo )
            return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */

        /* IMPLEMENT ME - establish which  host formats are available */
        hostOutputSampleFormat =
            PaUtil_SelectClosestAvailableFormat( paInt16 /* native formats */, outputSampleFormat );
    }
    else
    {
        outputChannelCount = 0;
        outputSampleFormat = hostOutputSampleFormat = paInt16; /* Surpress 'uninitialized var' warnings. */
    }

    /*
        IMPLEMENT ME:

        ( the following two checks are taken care of by PaUtil_InitializeBufferProcessor() FIXME - checks needed? )

            - check that input device can support inputSampleFormat, or that
                we have the capability to convert from outputSampleFormat to
                a native format

            - check that output device can support outputSampleFormat, or that
                we have the capability to convert from outputSampleFormat to
                a native format

            - if a full duplex stream is requested, check that the combination
                of input and output parameters is supported

            - check that the device supports sampleRate

            - alter sampleRate to a close allowable rate if possible / necessary

            - validate suggestedInputLatency and suggestedOutputLatency parameters,
                use default values where necessary
    */




    /* validate platform specific flags */
    if( (streamFlags & paPlatformSpecificFlags) != 0 )
        return paInvalidFlag; /* unexpected platform specific flag */


    stream = (PaSkeletonStream*)PaUtil_AllocateMemory( sizeof(PaSkeletonStream) );
    if( !stream )
    {
        result = paInsufficientMemory;
        goto error;
    }

    if( streamCallback )
    {
        PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,
                                               &skeletonHostApi->callbackStreamInterface, streamCallback, userData );
    }
    else
    {
        PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,
                                               &skeletonHostApi->blockingStreamInterface, streamCallback, userData );
    }

    PaUtil_InitializeCpuLoadMeasurer( &stream->cpuLoadMeasurer, sampleRate );


    /* we assume a fixed host buffer size in this example, but the buffer processor
        can also support bounded and unknown host buffer sizes by passing 
        paUtilBoundedHostBufferSize or paUtilUnknownHostBufferSize instead of
        paUtilFixedHostBufferSize below. */
        
    result =  PaUtil_InitializeBufferProcessor( &stream->bufferProcessor,
              inputChannelCount, inputSampleFormat, hostInputSampleFormat,
              outputChannelCount, outputSampleFormat, hostOutputSampleFormat,
              sampleRate, streamFlags, framesPerBuffer,
              framesPerHostBuffer, paUtilFixedHostBufferSize,
              streamCallback, userData );
    if( result != paNoError )
        goto error;


    /*
        IMPLEMENT ME: initialise the following fields with estimated or actual
        values.
    */
    stream->streamRepresentation.streamInfo.inputLatency =
            PaUtil_GetBufferProcessorInputLatency(&stream->bufferProcessor);
    stream->streamRepresentation.streamInfo.outputLatency =
            PaUtil_GetBufferProcessorOutputLatency(&stream->bufferProcessor);
    stream->streamRepresentation.streamInfo.sampleRate = sampleRate;

    
    /*
        IMPLEMENT ME:
            - additional stream setup + opening
    */

    stream->framesPerHostCallback = framesPerHostBuffer;

    *s = (PaStream*)stream;

    return result;

error:
    if( stream )
        PaUtil_FreeMemory( stream );

    return result;
}

/*
    ExampleHostProcessingLoop() illustrates the kind of processing which may
    occur in a host implementation.
 
*/
static void ExampleHostProcessingLoop( void *inputBuffer, void *outputBuffer, void *userData )
{
    PaSkeletonStream *stream = (PaSkeletonStream*)userData;
    PaStreamCallbackTimeInfo timeInfo = {0,0,0}; /* IMPLEMENT ME */
    int callbackResult;
    unsigned long framesProcessed;
    
    PaUtil_BeginCpuLoadMeasurement( &stream->cpuLoadMeasurer );
    
    /*
        IMPLEMENT ME:
            - generate timing information
            - handle buffer slips
    */

    /*
        If you need to byte swap or shift inputBuffer to convert it into a
        portaudio format, do it here.
    */



    PaUtil_BeginBufferProcessing( &stream->bufferProcessor, &timeInfo, 0 /* IMPLEMENT ME: pass underflow/overflow flags when necessary */ );

    /*
        depending on whether the host buffers are interleaved, non-interleaved
        or a mixture, you will want to call PaUtil_SetInterleaved*Channels(),
        PaUtil_SetNonInterleaved*Channel() or PaUtil_Set*Channel() here.
    */
    
    PaUtil_SetInputFrameCount( &stream->bufferProcessor, 0 /* default to host buffer size */ );
    PaUtil_SetInterleavedInputChannels( &stream->bufferProcessor,
            0, /* first channel of inputBuffer is channel 0 */
            inputBuffer,
            0 ); /* 0 - use inputChannelCount passed to init buffer processor */

    PaUtil_SetOutputFrameCount( &stream->bufferProcessor, 0 /* default to host buffer size */ );
    PaUtil_SetInterleavedOutputChannels( &stream->bufferProcessor,
            0, /* first channel of outputBuffer is channel 0 */
            outputBuffer,
            0 ); /* 0 - use outputChannelCount passed to init buffer processor */

    /* you must pass a valid value of callback result to PaUtil_EndBufferProcessing()
        in general you would pass paContinue for normal operation, and
        paComplete to drain the buffer processor's internal output buffer.
        You can check whether the buffer processor's output buffer is empty
        using PaUtil_IsBufferProcessorOuputEmpty( bufferProcessor )
    */
    callbackResult = paContinue;
    framesProcessed = PaUtil_EndBufferProcessing( &stream->bufferProcessor, &callbackResult );

    
    /*
        If you need to byte swap or shift outputBuffer to convert it to
        host format, do it here.
    */

    PaUtil_EndCpuLoadMeasurement( &stream->cpuLoadMeasurer, framesProcessed );


    if( callbackResult == paContinue )
    {
        /* nothing special to do */
    }
    else if( callbackResult == paAbort )
    {
        /* IMPLEMENT ME - finish playback immediately  */

        /* once finished, call the finished callback */
        if( stream->streamRepresentation.streamFinishedCallback != 0 )
            stream->streamRepresentation.streamFinishedCallback( stream->streamRepresentation.userData );
    }
    else
    {
        /* User callback has asked us to stop with paComplete or other non-zero value */

        /* IMPLEMENT ME - finish playback once currently queued audio has completed  */

        /* once finished, call the finished callback */
        if( stream->streamRepresentation.streamFinishedCallback != 0 )
            stream->streamRepresentation.streamFinishedCallback( stream->streamRepresentation.userData );
    }
}


/*
    When CloseStream() is called, the multi-api layer ensures that
    the stream has already been stopped or aborted.
*/
static PaError CloseStream( PaStream* s )
{
    PaError result = paNoError;
    PaSkeletonStream *stream = (PaSkeletonStream*)s;

    /*
        IMPLEMENT ME:
            - additional stream closing + cleanup
    */

    PaUtil_TerminateBufferProcessor( &stream->bufferProcessor );
    PaUtil_TerminateStreamRepresentation( &stream->streamRepresentation );
    PaUtil_FreeMemory( stream );

    return result;
}


static PaError StartStream( PaStream *s )
{
    PaError result = paNoError;
    PaSkeletonStream *stream = (PaSkeletonStream*)s;

    PaUtil_ResetBufferProcessor( &stream->bufferProcessor );

    /* IMPLEMENT ME, see portaudio.h for required behavior */

    /* suppress unused function warning. the code in ExampleHostProcessingLoop or
       something similar should be implemented to feed samples to and from the
       host after StartStream() is called.
    */
    (void) ExampleHostProcessingLoop;

    return result;
}


static PaError StopStream( PaStream *s )
{
    PaError result = paNoError;
    PaSkeletonStream *stream = (PaSkeletonStream*)s;

    /* suppress unused variable warnings */
    (void) stream;

    /* IMPLEMENT ME, see portaudio.h for required behavior */

    return result;
}


static PaError AbortStream( PaStream *s )
{
    PaError result = paNoError;
    PaSkeletonStream *stream = (PaSkeletonStream*)s;

    /* suppress unused variable warnings */
    (void) stream;
    
    /* IMPLEMENT ME, see portaudio.h for required behavior */

    return result;
}


static PaError IsStreamStopped( PaStream *s )
{
    PaSkeletonStream *stream = (PaSkeletonStream*)s;

    /* suppress unused variable warnings */
    (void) stream;
    
    /* IMPLEMENT ME, see portaudio.h for required behavior */

    return 0;
}


static PaError IsStreamActive( PaStream *s )
{
    PaSkeletonStream *stream = (PaSkeletonStream*)s;

    /* suppress unused variable warnings */
    (void) stream;
    
    /* IMPLEMENT ME, see portaudio.h for required behavior */

    return 0;
}


static PaTime GetStreamTime( PaStream *s )
{
    PaSkeletonStream *stream = (PaSkeletonStream*)s;

    /* suppress unused variable warnings */
    (void) stream;
    
    /* IMPLEMENT ME, see portaudio.h for required behavior*/

    return 0;
}


static double GetStreamCpuLoad( PaStream* s )
{
    PaSkeletonStream *stream = (PaSkeletonStream*)s;

    return PaUtil_GetCpuLoad( &stream->cpuLoadMeasurer );
}


/*
    As separate stream interfaces are used for blocking and callback
    streams, the following functions can be guaranteed to only be called
    for blocking streams.
*/

static PaError ReadStream( PaStream* s,
                           void *buffer,
                           unsigned long frames )
{
    PaSkeletonStream *stream = (PaSkeletonStream*)s;

    /* suppress unused variable warnings */
    (void) buffer;
    (void) frames;
    (void) stream;
    
    /* IMPLEMENT ME, see portaudio.h for required behavior*/

    return paNoError;
}


static PaError WriteStream( PaStream* s,
                            const void *buffer,
                            unsigned long frames )
{
    PaSkeletonStream *stream = (PaSkeletonStream*)s;

    /* suppress unused variable warnings */
    (void) buffer;
    (void) frames;
    (void) stream;
    
    /* IMPLEMENT ME, see portaudio.h for required behavior*/

    return paNoError;
}


static signed long GetStreamReadAvailable( PaStream* s )
{
    PaSkeletonStream *stream = (PaSkeletonStream*)s;

    /* suppress unused variable warnings */
    (void) stream;
    
    /* IMPLEMENT ME, see portaudio.h for required behavior*/

    return 0;
}


static signed long GetStreamWriteAvailable( PaStream* s )
{
    PaSkeletonStream *stream = (PaSkeletonStream*)s;

    /* suppress unused variable warnings */
    (void) stream;
    
    /* IMPLEMENT ME, see portaudio.h for required behavior*/

    return 0;
}





--- NEW FILE: pa_endianness.h ---
#ifndef PA_ENDIANNESS_H
#define PA_ENDIANNESS_H
/*
 * $Id: pa_endianness.h,v 1.3 2004/09/06 20:44:38 millerpuckette Exp $
 * Portable Audio I/O Library current platform endianness macros
 *
 * Based on the Open Source API proposed by Ross Bencina
 * Copyright (c) 1999-2002 Phil Burk, Ross Bencina
 *
 * 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:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * Any person wishing to distribute modifications to the Software is
 * requested to send the modifications to the original developer so that
 * they can be incorporated into the canonical version.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/** @file
 @brief Configure endianness symbols for the target processor.

 Arrange for either the PA_LITTLE_ENDIAN or PA_BIG_ENDIAN preprocessor symbols
 to be defined. The one that is defined reflects the endianness of the target
 platform and may be used to implement conditional compilation of byte-order
 dependent code.

 If either PA_LITTLE_ENDIAN or PA_BIG_ENDIAN is defined already, then no attempt
 is made to override that setting. This may be useful if you have a better way
 of determining the platform's endianness. The autoconf mechanism uses this for
 example.

 A PA_VALIDATE_ENDIANNESS macro is provided to compare the compile time
 and runtime endiannes and raise an assertion if they don't match.
*/


#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */


#if defined(PA_LITTLE_ENDIAN) || defined(PA_BIG_ENDIAN)
    /* endianness define has been set externally, such as by autoconf */

    #if defined(PA_LITTLE_ENDIAN) && defined(PA_BIG_ENDIAN)
    #error both PA_LITTLE_ENDIAN and PA_BIG_ENDIAN have been defined externally to pa_endianness.h - only one endianness at a time please
    #endif

#else
    /* endianness define has not been set externally */

    /* set PA_LITTLE_ENDIAN or PA_BIG_ENDIAN by testing well known platform specific defines */

    #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)

    #define PA_LITTLE_ENDIAN /* win32, assume intel byte order */

    #else

#endif

    #if !defined(PA_LITTLE_ENDIAN) && !defined(PA_BIG_ENDIAN)
    /*
     If the following error is raised, you either need to modify the code above
     to automatically determine the endianness from other symbols defined on your
     platform, or define either PA_LITTLE_ENDIAN or PA_BIG_ENDIAN externally.
    */
    #error pa_endianness.h was unable to automatically determine the endianness of the target platform
    #endif
    
#endif

/* PA_VALIDATE_ENDIANNESS compares the compile time and runtime endianness,
 and raises an assertion if they don't match. <assert.h> must be included in
 the context in which this macro is used.
*/
#if defined(PA_LITTLE_ENDIAN)
    #define PA_VALIDATE_ENDIANNESS \
    { \
        const long nativeOne = 1; \
        assert( "PortAudio: compile time and runtime endianness don't match" && (((char *)&nativeOne)[0]) == 1 ); \
    }
#elif defined(PA_BIG_ENDIAN)
    #define PA_VALIDATE_ENDIANNESS \
    { \
        const long nativeOne = 1; \
        assert( "PortAudio: compile time and runtime endianness don't match" && (((char *)&nativeOne)[0]) == 0 ); \
    }
#endif


#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* PA_ENDIANNESS_H */

--- NEW FILE: portaudio.h ---
#ifndef PORTAUDIO_H
#define PORTAUDIO_H
/*
 * $Id: portaudio.h,v 1.3 2004/09/06 20:44:38 millerpuckette Exp $
 * PortAudio Portable Real-Time Audio Library
 * PortAudio API Header File
 * Latest version available at: http://www.portaudio.com/
 *
 * Copyright (c) 1999-2002 Ross Bencina and 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:
 *
 * The above copyright notice and this permission notice shall be
[...1089 lines suppressed...]
 or paSampleFormatNotSupported if the format is not supported.
*/
PaError Pa_GetSampleSize( PaSampleFormat format );


/** Put the caller to sleep for at least 'msec' milliseconds. This function is
 provided only as a convenience for authors of portable code (such as the tests
 and examples in the PortAudio distribution.)

 The function may sleep longer than requested so don't rely on this for accurate
 musical timing.
*/
void Pa_Sleep( long msec );



#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* PORTAUDIO_H */

--- NEW FILE: pa_stream.c ---
/*
 * $Id: pa_stream.c,v 1.3 2004/09/06 20:44:38 millerpuckette Exp $
 * Portable Audio I/O Library
 * 
 *
 * Based on the Open Source API proposed by Ross Bencina
 * Copyright (c) 2002 Ross Bencina
 *
 * 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:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * Any person wishing to distribute modifications to the Software is
 * requested to send the modifications to the original developer so that
 * they can be incorporated into the canonical version.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/** @file
 @brief Interface used by pa_front to virtualize functions which operate on
 streams.
*/


#include "pa_stream.h"


void PaUtil_InitializeStreamInterface( PaUtilStreamInterface *streamInterface,
                                       PaError (*Close)( PaStream* ),
                                       PaError (*Start)( PaStream* ),
                                       PaError (*Stop)( PaStream* ),
                                       PaError (*Abort)( PaStream* ),
                                       PaError (*IsStopped)( PaStream* ),
                                       PaError (*IsActive)( PaStream* ),
                                       PaTime (*GetTime)( PaStream* ),
                                       double (*GetCpuLoad)( PaStream* ),
                                       PaError (*Read)( PaStream*, void *, unsigned long ),
                                       PaError (*Write)( PaStream*, const void *, unsigned long ),
                                       signed long (*GetReadAvailable)( PaStream* ),
                                       signed long (*GetWriteAvailable)( PaStream* )  )
{
    streamInterface->Close = Close;
    streamInterface->Start = Start;
    streamInterface->Stop = Stop;
    streamInterface->Abort = Abort;
    streamInterface->IsStopped = IsStopped;
    streamInterface->IsActive = IsActive;
    streamInterface->GetTime = GetTime;
    streamInterface->GetCpuLoad = GetCpuLoad;
    streamInterface->Read = Read;
    streamInterface->Write = Write;
    streamInterface->GetReadAvailable = GetReadAvailable;
    streamInterface->GetWriteAvailable = GetWriteAvailable;
}


void PaUtil_InitializeStreamRepresentation( PaUtilStreamRepresentation *streamRepresentation,
        PaUtilStreamInterface *streamInterface,
        PaStreamCallback *streamCallback,
        void *userData )
{
    streamRepresentation->magic = PA_STREAM_MAGIC;
    streamRepresentation->nextOpenStream = 0;
    streamRepresentation->streamInterface = streamInterface;
    streamRepresentation->streamCallback = streamCallback;
    streamRepresentation->streamFinishedCallback = 0;

    streamRepresentation->userData = userData;

    streamRepresentation->streamInfo.inputLatency = 0.;
    streamRepresentation->streamInfo.outputLatency = 0.;
    streamRepresentation->streamInfo.sampleRate = 0.;
}


void PaUtil_TerminateStreamRepresentation( PaUtilStreamRepresentation *streamRepresentation )
{
    streamRepresentation->magic = 0;
}


PaError PaUtil_DummyRead( PaStream* stream,
                               void *buffer,
                               unsigned long frames )
{
    (void)stream; /* unused parameter */
    (void)buffer; /* unused parameter */
    (void)frames; /* unused parameter */

    return paCanNotReadFromACallbackStream;
}


PaError PaUtil_DummyWrite( PaStream* stream,
                               const void *buffer,
                               unsigned long frames )
{
    (void)stream; /* unused parameter */
    (void)buffer; /* unused parameter */
    (void)frames; /* unused parameter */

    return paCanNotWriteToACallbackStream;
}


signed long PaUtil_DummyGetReadAvailable( PaStream* stream )
{
    (void)stream; /* unused parameter */

    return paCanNotReadFromACallbackStream;
}


signed long PaUtil_DummyGetWriteAvailable( PaStream* stream )
{
    (void)stream; /* unused parameter */

    return paCanNotWriteToACallbackStream;
}


double PaUtil_DummyGetCpuLoad( PaStream* stream )
{
    (void)stream; /* unused parameter */

    return 0.0;
}

--- NEW FILE: pa_trace.h ---
#ifndef PA_TRACE_H
#define PA_TRACE_H
/*
 * $Id: pa_trace.h,v 1.3 2004/09/06 20:44:38 millerpuckette Exp $
 * Portable Audio I/O Library Trace Facility
 * Store trace information in real-time for later printing.
 *
 * Based on the Open Source API proposed by Ross Bencina
 * Copyright (c) 1999-2000 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:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * Any person wishing to distribute modifications to the Software is
 * requested to send the modifications to the original developer so that
 * they can be incorporated into the canonical version.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/** @file
 @brief Event trace mechanism for debugging.

 Allows data to be written to the buffer at interrupt time and dumped later.
*/


#define PA_TRACE_REALTIME_EVENTS     (0)   /* Keep log of various real-time events. */
#define PA_MAX_TRACE_RECORDS      (2048)

#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */


#if PA_TRACE_REALTIME_EVENTS

void PaUtil_ResetTraceMessages();
void PaUtil_AddTraceMessage( const char *msg, int data );
void PaUtil_DumpTraceMessages();
    
#else

#define PaUtil_ResetTraceMessages() /* noop */
#define PaUtil_AddTraceMessage(msg,data) /* noop */
#define PaUtil_DumpTraceMessages() /* noop */

#endif


#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* PA_TRACE_H */

--- NEW FILE: pa_hostapi.h ---
#ifndef PA_HOSTAPI_H
#define PA_HOSTAPI_H
/*
 * $Id: pa_hostapi.h,v 1.3 2004/09/06 20:44:38 millerpuckette Exp $
 * Portable Audio I/O Library
 * host api representation
 *
 * 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:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * Any person wishing to distribute modifications to the Software is
 * requested to send the modifications to the original developer so that
 * they can be incorporated into the canonical version.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/** @file
 @brief Interface used by pa_front to virtualize functions which operate on
 host APIs.
*/


#include "portaudio.h"

#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */


/** **FOR THE USE OF pa_front.c ONLY**
    Do NOT use fields in this structure, they my change at any time.
    Use functions defined in pa_util.h if you think you need functionality
    which can be derived from here.
*/
typedef struct PaUtilPrivatePaFrontHostApiInfo {


    unsigned long baseDeviceIndex;
}PaUtilPrivatePaFrontHostApiInfo;


/** The common header for all data structures whose pointers are passed through
 the hostApiSpecificStreamInfo field of the PaStreamParameters structure.
 Note that in order to keep the public PortAudio interface clean, this structure
 is not used explicitly when declaring hostApiSpecificStreamInfo data structures.
 However, some code in pa_front depends on the first 3 members being equivalent
 with this structure.
 @see PaStreamParameters
*/
typedef struct PaUtilHostApiSpecificStreamInfoHeader
{
    unsigned long size;             /**< size of whole structure including this header */
    PaHostApiTypeId hostApiType;    /**< host API for which this data is intended */
    unsigned long version;          /**< structure version */
} PaUtilHostApiSpecificStreamInfoHeader;



/** A structure representing the interface to a host API. Contains both
 concrete data and pointers to functions which implement the interface.
*/
typedef struct PaUtilHostApiRepresentation {
    PaUtilPrivatePaFrontHostApiInfo privatePaFrontInfo;

    /** The host api implementation should populate the info field. In the
        case of info.defaultInputDevice and info.defaultOutputDevice the
        values stored should be 0 based indices within the host api's own
        device index range (0 to deviceCount). These values will be converted
        to global device indices by pa_front after PaUtilHostApiInitializer()
        returns.
    */
    PaHostApiInfo info;

    PaDeviceInfo** deviceInfos;

    /**
        (*Terminate)() is guaranteed to be called with a valid <hostApi>
        parameter, which was previously returned from the same implementation's
        initializer.
    */
    void (*Terminate)( struct PaUtilHostApiRepresentation *hostApi );

    /**
        The inputParameters and outputParameters pointers should not be saved
        as they will not remain valid after OpenStream is called.

        
        The following guarantees are made about parameters to (*OpenStream)():

            [NOTE: the following list up to *END PA FRONT VALIDATIONS* should be
                kept in sync with the one for ValidateOpenStreamParameters and
                Pa_OpenStream in pa_front.c]
                
            PaHostApiRepresentation *hostApi
                - is valid for this implementation

            PaStream** stream
                - is non-null

            - at least one of inputParameters & outputParmeters is valid (not NULL)

            - if inputParameters & outputParmeters are both valid, that
                inputParameters->device & outputParmeters->device  both use the same host api
 
            PaDeviceIndex inputParameters->device
                - is within range (0 to Pa_CountDevices-1) Or:
                - is paUseHostApiSpecificDeviceSpecification and
                    inputParameters->hostApiSpecificStreamInfo is non-NULL and refers
                    to a valid host api

            int inputParameters->numChannels
                - if inputParameters->device is not paUseHostApiSpecificDeviceSpecification, numInputChannels is > 0
                - upper bound is NOT validated against device capabilities
 
            PaSampleFormat inputParameters->sampleFormat
                - is one of the sample formats defined in portaudio.h

            void *inputParameters->hostApiSpecificStreamInfo
                - if supplied its hostApi field matches the input device's host Api
 
            PaDeviceIndex outputParmeters->device
                - is within range (0 to Pa_CountDevices-1)
 
            int outputParmeters->numChannels
                - if inputDevice is valid, numInputChannels is > 0
                - upper bound is NOT validated against device capabilities
 
            PaSampleFormat outputParmeters->sampleFormat
                - is one of the sample formats defined in portaudio.h
        
            void *outputParmeters->hostApiSpecificStreamInfo
                - if supplied its hostApi field matches the output device's host Api
 
            double sampleRate
                - is not an 'absurd' rate (less than 1000. or greater than 200000.)
                - sampleRate is NOT validated against device capabilities
 
            PaStreamFlags streamFlags
                - unused platform neutral flags are zero
                - paNeverDropInput is only used for full-duplex callback streams
                    with variable buffer size (paFramesPerBufferUnspecified)

            [*END PA FRONT VALIDATIONS*]


        The following validations MUST be performed by (*OpenStream)():

            - check that input device can support numInputChannels
            
            - check that input device can support inputSampleFormat, or that
                we have the capability to convert from outputSampleFormat to
                a native format

            - if inputStreamInfo is supplied, validate its contents,
                or return an error if no inputStreamInfo is expected

            - check that output device can support numOutputChannels
            
            - check that output device can support outputSampleFormat, or that
                we have the capability to convert from outputSampleFormat to
                a native format

            - if outputStreamInfo is supplied, validate its contents,
                or return an error if no outputStreamInfo is expected

            - if a full duplex stream is requested, check that the combination
                of input and output parameters is supported

            - check that the device supports sampleRate

            - alter sampleRate to a close allowable rate if necessary

            - validate inputLatency and outputLatency

            - validate any platform specific flags, if flags are supplied they
                must be valid.
    */
    PaError (*OpenStream)( struct PaUtilHostApiRepresentation *hostApi,
                           PaStream** stream,
                           const PaStreamParameters *inputParameters,
                           const PaStreamParameters *outputParameters,
                           double sampleRate,
                           unsigned long framesPerCallback,
                           PaStreamFlags streamFlags,
                           PaStreamCallback *streamCallback,
                           void *userData );


    PaError (*IsFormatSupported)( struct PaUtilHostApiRepresentation *hostApi,
                                  const PaStreamParameters *inputParameters,
                                  const PaStreamParameters *outputParameters,
                                  double sampleRate );
} PaUtilHostApiRepresentation;


/** Prototype for the initialization function which must be implemented by every
 host API.
 
 @see paHostApiInitializers
*/
typedef PaError PaUtilHostApiInitializer( PaUtilHostApiRepresentation**, PaHostApiIndex );


/** paHostApiInitializers is a NULL-terminated array of host API initialization
 functions. These functions are called by pa_front to initialize the host APIs
 when the client calls Pa_Initialize().

 There is a platform specific file which defines paHostApiInitializers for that
 platform, pa_win/pa_win_hostapis.c contains the Win32 definitions for example.
*/
extern PaUtilHostApiInitializer *paHostApiInitializers[];


/** The index of the default host API in the paHostApiInitializers array.
 
 There is a platform specific file which defines paDefaultHostApiIndex for that
 platform, see pa_win/pa_win_hostapis.c for example.
*/
extern int paDefaultHostApiIndex;


#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* PA_HOSTAPI_H */

--- NEW FILE: pa_process.h ---
#ifndef PA_PROCESS_H
#define PA_PROCESS_H
/*
 * $Id: pa_process.h,v 1.3 2004/09/06 20:44:38 millerpuckette Exp $
 * Portable Audio I/O Library callback buffer processing adapters
 *
 * Based on the Open Source API proposed by Ross Bencina
 * Copyright (c) 1999-2002 Phil Burk, Ross Bencina
 *
 * 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:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * Any person wishing to distribute modifications to the Software is
 * requested to send the modifications to the original developer so that
 * they can be incorporated into the canonical version.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
 
/** @file
 @brief Buffer Processor prototypes. A Buffer Processor performs buffer length
 adaption, coordinates sample format conversion, and interleaves/deinterleaves
 channels.

 <h3>Overview</h3>

 The "Buffer Processor" (PaUtilBufferProcessor) manages conversion of audio
 data from host buffers to user buffers and back again. Where required, the
 buffer processor takes care of converting between host and user sample formats,
 interleaving and deinterleaving multichannel buffers, and adapting between host
 and user buffers with different lengths. The buffer processor may be used with
 full and half duplex streams, for both callback streams and blocking read/write
 streams.

 One of the important capabilities provided by the buffer processor is
 the ability to adapt between user and host buffer sizes of different lengths
 with minimum latency. Although this task is relatively easy to perform when
 the host buffer size is an integer multiple of the user buffer size, the
 problem is more complicated when this is not the case - especially for
 full-duplex callback streams. Where necessary the adaption is implemented by
 internally buffering some input and/or output data. The buffer adation
 algorithm used by the buffer processor was originally implemented by
 Stephan Letz for the ASIO version of PortAudio, and is described in his
 Callback_adaption_.pdf which is included in the distribution.

 The buffer processor performs sample conversion using the functions provided
 by pa_converters.c.

 The following sections provide an overview of how to use the buffer processor.
 Interested readers are advised to consult the host API implementations for
 examples of buffer processor usage.
 

 <h4>Initialization, resetting and termination</h4>

 When a stream is opened, the buffer processor should be initialized using
 PaUtil_InitializeBufferProcessor. This function initializes internal state
 and allocates temporary buffers as neccesary according to the supplied
 configuration parameters. Some of the parameters correspond to those requested
 by the user in their call to Pa_OpenStream(), others reflect the requirements
 of the host API implementation - they indicate host buffer sizes, formats,
 and the type of buffering which the Host API uses. The buffer processor should
 be initialized for callback streams and blocking read/write streams.

 Call PaUtil_ResetBufferProcessor to clear any sample data which is present
 in the buffer processor before starting to use it (for example when
 Pa_StartStream is called).

 When the buffer processor is no longer used call
 PaUtil_TerminateBufferProcessor.

 
 <h4>Using the buffer processor for a callback stream</h4>

 The buffer processor's role in a callback stream is to take host input buffers
 process them with the stream callback, and fill host output buffers. For a
 full duplex stream, the buffer processor handles input and output simultaneously
 due to the requirements of the minimum-latency buffer adation algorithm.

 When a host buffer becomes available, the implementation should call
 the buffer processor to process the buffer. The buffer processor calls the
 stream callback to consume and/or produce audio data as necessary. The buffer
 processor will convert sample formats, interleave/deinterleave channels,
 and slice or chunk the data to the appropriate buffer lengths according to
 the requirements of the stream callback and the host API.

 To process a host buffer (or a pair of host buffers for a full-duplex stream)
 use the following calling sequence:

 -# Call PaUtil_BeginBufferProcessing
 -# For a stream which takes input:
    - Call PaUtil_SetInputFrameCount with the number of frames in the host input
        buffer.
    - Call one of the following functions one or more times to tell the
        buffer processor about the host input buffer(s): PaUtil_SetInputChannel,
        PaUtil_SetInterleavedInputChannels, PaUtil_SetNonInterleavedInputChannel.
        Which function you call will depend on whether the host buffer(s) are
        interleaved or not.
    - If the available host data is split accross two buffers (for example a
        data range at the end of a circular buffer and another range at the
        beginning of the circular buffer), also call
        PaUtil_Set2ndInputFrameCount, PaUtil_Set2ndInputChannel,
        PaUtil_Set2ndInterleavedInputChannels,
        PaUtil_Set2ndNonInterleavedInputChannel as necessary to tell the buffer
        processor about the second buffer.
 -# For a stream which generates output:
    - Call PaUtil_SetOutputFrameCount with the number of frames in the host
        output buffer.
    - Call one of the following functions one or more times to tell the
        buffer processor about the host output buffer(s): PaUtil_SetOutputChannel,
        PaUtil_SetInterleavedOutputChannels, PaUtil_SetNonInterleavedOutputChannel.
        Which function you call will depend on whether the host buffer(s) are
        interleaved or not.
    - If the available host output buffer space is split accross two buffers
        (for example a data range at the end of a circular buffer and another
        range at the beginning of the circular buffer), call
        PaUtil_Set2ndOutputFrameCount, PaUtil_Set2ndOutputChannel,
        PaUtil_Set2ndInterleavedOutputChannels,
        PaUtil_Set2ndNonInterleavedOutputChannel as necessary to tell the buffer
        processor about the second buffer.
 -# Call PaUtil_EndBufferProcessing, this function performs the actual data
    conversion and processing.


 <h4>Using the buffer processor for a blocking read/write stream</h4>

 Blocking read/write streams use the buffer processor to convert and copy user
 output data to a host buffer, and to convert and copy host input data to
 the user's buffer. The buffer processor does not perform any buffer adaption.
 When using the buffer processor in a blocking read/write stream the input and
 output conversion are performed separately by the PaUtil_CopyInput and
 PaUtil_CopyOutput functions.

 To copy data from a host input buffer to the buffer(s) which the user supplies
 to Pa_ReadStream, use the following calling sequence.

 - Repeat the following three steps until the user buffer(s) have been filled
    with samples from the host input buffers:
     -# Call PaUtil_SetInputFrameCount with the number of frames in the host
        input buffer.
     -# Call one of the following functions one or more times to tell the
        buffer processor about the host input buffer(s): PaUtil_SetInputChannel,
        PaUtil_SetInterleavedInputChannels, PaUtil_SetNonInterleavedInputChannel.
        Which function you call will depend on whether the host buffer(s) are
        interleaved or not.
     -# Call PaUtil_CopyInput with the user buffer pointer (or a copy of the
        array of buffer pointers for a non-interleaved stream) passed to
        Pa_ReadStream, along with the number of frames in the user buffer(s).
        Be careful to pass a <i>copy</i> of the user buffer pointers to
        PaUtil_CopyInput because PaUtil_CopyInput advances the pointers to
        the start of the next region to copy.
 - PaUtil_CopyInput will not copy more data than is available in the
    host buffer(s), so the above steps need to be repeated until the user
    buffer(s) are full.

 
 To copy data to the host output buffer from the user buffers(s) supplied
 to Pa_WriteStream use the following calling sequence.

 - Repeat the following three steps until all frames from the user buffer(s)
    have been copied to the host API:
     -# Call PaUtil_SetOutputFrameCount with the number of frames in the host
        output buffer.
     -# Call one of the following functions one or more times to tell the
        buffer processor about the host output buffer(s): PaUtil_SetOutputChannel,
        PaUtil_SetInterleavedOutputChannels, PaUtil_SetNonInterleavedOutputChannel.
        Which function you call will depend on whether the host buffer(s) are
        interleaved or not.
     -# Call PaUtil_CopyOutput with the user buffer pointer (or a copy of the
        array of buffer pointers for a non-interleaved stream) passed to
        Pa_WriteStream, along with the number of frames in the user buffer(s).
        Be careful to pass a <i>copy</i> of the user buffer pointers to 
        PaUtil_CopyOutput because PaUtil_CopyOutput advances the pointers to
        the start of the next region to copy.
 - PaUtil_CopyOutput will not copy more data than fits in the host buffer(s),
    so the above steps need to be repeated until all user data is copied.
*/


#include "portaudio.h"
#include "pa_converters.h"
#include "pa_dither.h"

#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */


/** @brief Mode flag passed to PaUtil_InitializeBufferProcessor indicating the type
 of buffering that the host API uses.

 The mode used depends on whether the host API or the implementation manages
 the buffers, and how these buffers are used (scatter gather, circular buffer).
*/
typedef enum {
/** The host buffer size is a fixed known size. */
    paUtilFixedHostBufferSize,

/** The host buffer size may vary, but has a known maximum size. */
    paUtilBoundedHostBufferSize,

/** Nothing is known about the host buffer size. */
    paUtilUnknownHostBufferSize,

/** The host buffer size varies, and the client does not require the buffer
 processor to consume all of the input and fill all of the output buffer. This
 is useful when the implementation has access to the host API's circular buffer
 and only needs to consume/fill some of it, not necessarily all of it, with each
 call to the buffer processor. This is the only mode where
 PaUtil_EndBufferProcessing() may not consume the whole buffer.
*/
    paUtilVariableHostBufferSizePartialUsageAllowed
}PaUtilHostBufferSizeMode;


/** @brief An auxilliary data structure used internally by the buffer processor
 to represent host input and output buffers. */
typedef struct PaUtilChannelDescriptor{
    void *data;
    unsigned int stride;  /**< stride in samples, not bytes */
}PaUtilChannelDescriptor;


/** @brief The main buffer processor data structure.

 Allocate one of these, initialize it with PaUtil_InitializeBufferProcessor
 and terminate it with PaUtil_TerminateBufferProcessor.
*/
typedef struct {
    unsigned long framesPerUserBuffer;
    unsigned long framesPerHostBuffer;

    PaUtilHostBufferSizeMode hostBufferSizeMode;
    int useNonAdaptingProcess;
    unsigned long framesPerTempBuffer;

    unsigned int inputChannelCount;
    unsigned int bytesPerHostInputSample;
    unsigned int bytesPerUserInputSample;
    int userInputIsInterleaved;
    PaUtilConverter *inputConverter;
    PaUtilZeroer *inputZeroer;
    
    unsigned int outputChannelCount;
    unsigned int bytesPerHostOutputSample;
    unsigned int bytesPerUserOutputSample;
    int userOutputIsInterleaved;
    PaUtilConverter *outputConverter;
    PaUtilZeroer *outputZeroer;

    unsigned long initialFramesInTempInputBuffer;
    unsigned long initialFramesInTempOutputBuffer;

    void *tempInputBuffer;          /**< used for slips, block adaption, and conversion. */
    void **tempInputBufferPtrs;     /**< storage for non-interleaved buffer pointers, NULL for interleaved user input */
    unsigned long framesInTempInputBuffer; /**< frames remaining in input buffer from previous adaption iteration */

    void *tempOutputBuffer;         /**< used for slips, block adaption, and conversion. */
    void **tempOutputBufferPtrs;    /**< storage for non-interleaved buffer pointers, NULL for interleaved user output */
    unsigned long framesInTempOutputBuffer; /**< frames remaining in input buffer from previous adaption iteration */

    PaStreamCallbackTimeInfo *timeInfo;

    PaStreamCallbackFlags callbackStatusFlags;

    unsigned long hostInputFrameCount[2];
    PaUtilChannelDescriptor *hostInputChannels[2];
    unsigned long hostOutputFrameCount[2];
    PaUtilChannelDescriptor *hostOutputChannels[2];

    PaUtilTriangularDitherGenerator ditherGenerator;

    double samplePeriod;

    PaStreamCallback *streamCallback;
    void *userData;
} PaUtilBufferProcessor;


/** @name Initialization, termination, resetting and info */
/*@{*/

/** Initialize a buffer processor's representation stored in a
 PaUtilBufferProcessor structure. Be sure to call
 PaUtil_TerminateBufferProcessor after finishing with a buffer processor.

 @param bufferProcessor The buffer processor structure to initialize.

 @param inputChannelCount The number of input channels as passed to
 Pa_OpenStream or 0 for an output-only stream.

 @param userInputSampleFormat Format of user input samples, as passed to
 Pa_OpenStream. This parameter is ignored for ouput-only streams.
 
 @param hostInputSampleFormat Format of host input samples. This parameter is
 ignored for output-only streams. See note about host buffer interleave below.

 @param outputChannelCount The number of output channels as passed to
 Pa_OpenStream or 0 for an input-only stream.

 @param userOutputSampleFormat Format of user output samples, as passed to
 Pa_OpenStream. This parameter is ignored for input-only streams.
 
 @param hostOutputSampleFormat Format of host output samples. This parameter is
 ignored for input-only streams. See note about host buffer interleave below.

 @param sampleRate Sample rate of the stream. The more accurate this is the
 better - it is used for updating time stamps when adapting buffers.
 
 @param streamFlags Stream flags as passed to Pa_OpenStream, this parameter is
 used for selecting special sample conversion options such as clipping and
 dithering.
 
 @param framesPerUserBuffer Number of frames per user buffer, as requested
 by the framesPerBuffer parameter to Pa_OpenStream. This parameter may be
 zero to indicate that the user will accept any (and varying) buffer sizes.

 @param framesPerHostBuffer Specifies the number of frames per host buffer
 for the fixed buffer size mode, and the maximum number of frames
 per host buffer for the bounded host buffer size mode. It is ignored for
 the other modes.

 @param hostBufferSizeMode A mode flag indicating the size variability of
 host buffers that will be passed to the buffer processor. See
 PaUtilHostBufferSizeMode for further details.
 
 @param streamCallback The user stream callback passed to Pa_OpenStream.

 @param userData The user data field passed to Pa_OpenStream.
    
 @note The interleave flag is ignored for host buffer formats. Host
 interleave is determined by the use of different SetInput and SetOutput
 functions.

 @return An error code indicating whether the initialization was successful.
 If the error code is not PaNoError, the buffer processor was not initialized
 and should not be used.
 
 @see Pa_OpenStream, PaUtilHostBufferSizeMode, PaUtil_TerminateBufferProcessor
*/
PaError PaUtil_InitializeBufferProcessor( PaUtilBufferProcessor* bufferProcessor,
            int inputChannelCount, PaSampleFormat userInputSampleFormat,
            PaSampleFormat hostInputSampleFormat,
            int outputChannelCount, PaSampleFormat userOutputSampleFormat,
            PaSampleFormat hostOutputSampleFormat,
            double sampleRate,
            PaStreamFlags streamFlags,
            unsigned long framesPerUserBuffer, /* 0 indicates don't care */
            unsigned long framesPerHostBuffer,
            PaUtilHostBufferSizeMode hostBufferSizeMode,
            PaStreamCallback *streamCallback, void *userData );


/** Terminate a buffer processor's representation. Deallocates any temporary
 buffers allocated by PaUtil_InitializeBufferProcessor.
 
 @param bufferProcessor The buffer processor structure to terminate.

 @see PaUtil_InitializeBufferProcessor.
*/
void PaUtil_TerminateBufferProcessor( PaUtilBufferProcessor* bufferProcessor );


/** Clear any internally buffered data. If you call
 PaUtil_InitializeBufferProcessor in your OpenStream routine, make sure you
 call PaUtil_ResetBufferProcessor in your StartStream call.

 @param bufferProcessor The buffer processor to reset.
*/
void PaUtil_ResetBufferProcessor( PaUtilBufferProcessor* bufferProcessor );


/** Retrieve the input latency of a buffer processor.

 @param bufferProcessor The buffer processor examine.

 @return The input latency introduced by the buffer processor, in frames.

 @see PaUtil_GetBufferProcessorOutputLatency
*/
unsigned long PaUtil_GetBufferProcessorInputLatency( PaUtilBufferProcessor* bufferProcessor );

/** Retrieve the output latency of a buffer processor.

 @param bufferProcessor The buffer processor examine.

 @return The output latency introduced by the buffer processor, in frames.

 @see PaUtil_GetBufferProcessorInputLatency
*/
unsigned long PaUtil_GetBufferProcessorOutputLatency( PaUtilBufferProcessor* bufferProcessor );

/*@}*/


/** @name Host buffer pointer configuration

 Functions to set host input and output buffers, used by both callback streams
 and blocking read/write streams.
*/
/*@{*/ 


/** Set the number of frames in the input host buffer(s) specified by the
 PaUtil_Set*InputChannel functions.

 @param bufferProcessor The buffer processor.

 @param frameCount The number of host input frames. A 0 frameCount indicates to
 use the framesPerHostBuffer value passed to PaUtil_InitializeBufferProcessor.

 @see PaUtil_SetNoInput, PaUtil_SetInputChannel,
 PaUtil_SetInterleavedInputChannels, PaUtil_SetNonInterleavedInputChannel
*/
void PaUtil_SetInputFrameCount( PaUtilBufferProcessor* bufferProcessor,
        unsigned long frameCount );

        
/** Indicate that no input is avalable. This function should be used when
 priming the output of a full-duplex stream opened with the
 paPrimeOutputBuffersUsingStreamCallback flag. Note that it is not necessary
 to call this or any othe PaUtil_Set*Input* functions for ouput-only streams.

 @param bufferProcessor The buffer processor.
*/
void PaUtil_SetNoInput( PaUtilBufferProcessor* bufferProcessor );


/** Provide the buffer processor with a pointer to a host input channel.

 @param bufferProcessor The buffer processor.
 @param channel The channel number.
 @param data The buffer.
 @param stride The stride from one sample to the next, in samples. For
 interleaved host buffers, the stride will usually be the same as the number of
 channels in the buffer.
*/
void PaUtil_SetInputChannel( PaUtilBufferProcessor* bufferProcessor,
        unsigned int channel, void *data, unsigned int stride );


/** Provide the buffer processor with a pointer to an number of interleaved
 host input channels.

 @param bufferProcessor The buffer processor.
 @param firstChannel The first channel number.
 @param data The buffer.
 @param channelCount The number of interleaved channels in the buffer. If
 channelCount is zero, the number of channels specified to
 PaUtil_InitializeBufferProcessor will be used.
*/
void PaUtil_SetInterleavedInputChannels( PaUtilBufferProcessor* bufferProcessor,
        unsigned int firstChannel, void *data, unsigned int channelCount );


/** Provide the buffer processor with a pointer to one non-interleaved host
 output channel.

 @param bufferProcessor The buffer processor.
 @param channel The channel number.
 @param data The buffer.
*/
void PaUtil_SetNonInterleavedInputChannel( PaUtilBufferProcessor* bufferProcessor,
        unsigned int channel, void *data );


/** Use for the second buffer half when the input buffer is split in two halves.
 @see PaUtil_SetInputFrameCount
*/
void PaUtil_Set2ndInputFrameCount( PaUtilBufferProcessor* bufferProcessor,
        unsigned long frameCount );

/** Use for the second buffer half when the input buffer is split in two halves.
 @see PaUtil_SetInputChannel
*/
void PaUtil_Set2ndInputChannel( PaUtilBufferProcessor* bufferProcessor,
        unsigned int channel, void *data, unsigned int stride );

/** Use for the second buffer half when the input buffer is split in two halves.
 @see PaUtil_SetInterleavedInputChannels
*/
void PaUtil_Set2ndInterleavedInputChannels( PaUtilBufferProcessor* bufferProcessor,
        unsigned int firstChannel, void *data, unsigned int channelCount );

/** Use for the second buffer half when the input buffer is split in two halves.
 @see PaUtil_SetNonInterleavedInputChannel
*/
void PaUtil_Set2ndNonInterleavedInputChannel( PaUtilBufferProcessor* bufferProcessor,
        unsigned int channel, void *data );

        
/** Set the number of frames in the output host buffer(s) specified by the
 PaUtil_Set*OutputChannel functions.

 @param bufferProcessor The buffer processor.

 @param frameCount The number of host output frames. A 0 frameCount indicates to
 use the framesPerHostBuffer value passed to PaUtil_InitializeBufferProcessor.

 @see PaUtil_SetOutputChannel, PaUtil_SetInterleavedOutputChannels,
 PaUtil_SetNonInterleavedOutputChannel
*/
void PaUtil_SetOutputFrameCount( PaUtilBufferProcessor* bufferProcessor,
        unsigned long frameCount );


/** Indicate that the output will be discarded. This function should be used
 when implementing the paNeverDropInput mode for full duplex streams.

 @param bufferProcessor The buffer processor.
*/
void PaUtil_SetNoOutput( PaUtilBufferProcessor* bufferProcessor );


/** Provide the buffer processor with a pointer to a host output channel.

 @param bufferProcessor The buffer processor.
 @param channel The channel number.
 @param data The buffer.
 @param stride The stride from one sample to the next, in samples. For
 interleaved host buffers, the stride will usually be the same as the number of
 channels in the buffer.
*/
void PaUtil_SetOutputChannel( PaUtilBufferProcessor* bufferProcessor,
        unsigned int channel, void *data, unsigned int stride );


/** Provide the buffer processor with a pointer to an number of interleaved
 host output channels.

 @param bufferProcessor The buffer processor.
 @param firstChannel The first channel number.
 @param data The buffer.
 @param channelCount The number of interleaved channels in the buffer. If
 channelCount is zero, the number of channels specified to
 PaUtil_InitializeBufferProcessor will be used.
*/
void PaUtil_SetInterleavedOutputChannels( PaUtilBufferProcessor* bufferProcessor,
        unsigned int firstChannel, void *data, unsigned int channelCount );

        
/** Provide the buffer processor with a pointer to one non-interleaved host
 output channel.

 @param bufferProcessor The buffer processor.
 @param channel The channel number.
 @param data The buffer.
*/
void PaUtil_SetNonInterleavedOutputChannel( PaUtilBufferProcessor* bufferProcessor,
        unsigned int channel, void *data );


/** Use for the second buffer half when the output buffer is split in two halves.
 @see PaUtil_SetOutputFrameCount
*/
void PaUtil_Set2ndOutputFrameCount( PaUtilBufferProcessor* bufferProcessor,
        unsigned long frameCount );

/** Use for the second buffer half when the output buffer is split in two halves.
 @see PaUtil_SetOutputChannel
*/
void PaUtil_Set2ndOutputChannel( PaUtilBufferProcessor* bufferProcessor,
        unsigned int channel, void *data, unsigned int stride );

/** Use for the second buffer half when the output buffer is split in two halves.
 @see PaUtil_SetInterleavedOutputChannels
*/
void PaUtil_Set2ndInterleavedOutputChannels( PaUtilBufferProcessor* bufferProcessor,
        unsigned int firstChannel, void *data, unsigned int channelCount );

/** Use for the second buffer half when the output buffer is split in two halves.
 @see PaUtil_SetNonInterleavedOutputChannel
*/
void PaUtil_Set2ndNonInterleavedOutputChannel( PaUtilBufferProcessor* bufferProcessor,
        unsigned int channel, void *data );

/*@}*/


/** @name Buffer processing functions for callback streams
*/
/*@{*/

/** Commence processing a host buffer (or a pair of host buffers in the
 full-duplex case) for a callback stream.

 @param bufferProcessor The buffer processor.

 @param timeInfo Timing information for the first sample of the host
 buffer(s). This information may be adjusted when buffer adaption is being
 performed.

 @param callbackStatusFlags Flags indicating whether underruns and overruns
 have occurred since the last time the buffer processor was called.
*/
void PaUtil_BeginBufferProcessing( PaUtilBufferProcessor* bufferProcessor,
        PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags callbackStatusFlags );

        
/** Finish processing a host buffer (or a pair of host buffers in the
 full-duplex case) for a callback stream.

 @param bufferProcessor The buffer processor.
 
 @param callbackResult On input, indicates a previous callback result, and on
 exit, the result of the user stream callback, if it is called.
 On entry callbackResult should contain one of { paContinue, paComplete, or
 paAbort}. If paComplete is passed, the stream callback will not be called
 but any audio that was generated by previous stream callbacks will be copied
 to the output buffer(s). You can check whether the buffer processor's internal
 buffer is empty by calling PaUtil_IsBufferProcessorOuputEmpty.

 If the stream callback is called its result is stored in *callbackResult. If
 the stream callback returns paComplete or paAbort, all output buffers will be
 full of valid data - some of which may be zeros to acount for data that
 wasn't generated by the terminating callback.

 @return The number of frames processed. This usually corresponds to the
 number of frames specified by the PaUtil_Set*FrameCount functions, exept in
 the paUtilVariableHostBufferSizePartialUsageAllowed buffer size mode when a
 smaller value may be returned.
*/
unsigned long PaUtil_EndBufferProcessing( PaUtilBufferProcessor* bufferProcessor,
        int *callbackResult );


/** Determine whether any callback generated output remains in the bufffer
 processor's internal buffers. This method may be used to determine when to
 continue calling PaUtil_EndBufferProcessing() after the callback has returned
 a callbackResult of paComplete.

 @param bufferProcessor The buffer processor.
 
 @return Returns non-zero when callback generated output remains in the internal
 buffer and zero (0) when there internal buffer contains no callback generated
 data.
*/
int PaUtil_IsBufferProcessorOuputEmpty( PaUtilBufferProcessor* bufferProcessor );

/*@}*/


/** @name Buffer processing functions for blocking read/write streams
*/
/*@{*/

/** Copy samples from host input channels set up by the PaUtil_Set*InputChannels
 functions to a user supplied buffer. This function is intended for use with
 blocking read/write streams. Copies the minimum of the number of
 user frames (specified by the frameCount parameter) and the number of available
 host frames (specified in a previous call to SetInputFrameCount()).

 @param bufferProcessor The buffer processor.

 @param buffer A pointer to the user buffer pointer, or a pointer to a pointer
 to an array of user buffer pointers for a non-interleaved stream. It is
 important that this parameter points to a copy of the user buffer pointers,
 not to the actual user buffer pointers, because this function updates the
 pointers before returning.

 @param frameCount The number of frames of data in the buffer(s) pointed to by
 the buffer parameter.

 @return The number of frames copied. The buffer pointer(s) pointed to by the
 buffer parameter are advanced to point to the frame(s) following the last one
 filled.
*/
unsigned long PaUtil_CopyInput( PaUtilBufferProcessor* bufferProcessor,
        void **buffer, unsigned long frameCount );


/* Copy samples from a user supplied buffer to host output channels set up by
 the PaUtil_Set*OutputChannels functions. This function is intended for use with
 blocking read/write streams. Copies the minimum of the number of
 user frames (specified by the frameCount parameter) and the number of
 host frames (specified in a previous call to SetOutputFrameCount()).

 @param bufferProcessor The buffer processor.

 @param buffer A pointer to the user buffer pointer, or a pointer to a pointer
 to an array of user buffer pointers for a non-interleaved stream. It is
 important that this parameter points to a copy of the user buffer pointers,
 not to the actual user buffer pointers, because this function updates the
 pointers before returning.

 @param frameCount The number of frames of data in the buffer(s) pointed to by
 the buffer parameter.

 @return The number of frames copied. The buffer pointer(s) pointed to by the
 buffer parameter are advanced to point to the frame(s) following the last one
 copied.
*/
unsigned long PaUtil_CopyOutput( PaUtilBufferProcessor* bufferProcessor,
        const void ** buffer, unsigned long frameCount );


/* Zero samples in host output channels set up by the PaUtil_Set*OutputChannels
 functions. This function is useful for flushing streams.
 Zeros the minimum of frameCount and the number of host frames specified in a
 previous call to SetOutputFrameCount().

 @param bufferProcessor The buffer processor.

 @param frameCount The maximum number of frames to zero.
 
 @return The number of frames zeroed.
*/
unsigned long PaUtil_ZeroOutput( PaUtilBufferProcessor* bufferProcessor,
        unsigned long frameCount );


/*@}*/


#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* PA_PROCESS_H */

--- NEW FILE: pa_util.h ---
#ifndef PA_UTIL_H
#define PA_UTIL_H
/*
 * $Id: pa_util.h,v 1.3 2004/09/06 20:44:38 millerpuckette Exp $
 * Portable Audio I/O Library implementation utilities header
 * common implementation utilities and interfaces
 *
 * 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:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * Any person wishing to distribute modifications to the Software is
 * requested to send the modifications to the original developer so that
 * they can be incorporated into the canonical version.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/** @file
    @brief Prototypes for utility functions used by PortAudio implementations.

    @todo Document and adhere to the alignment guarantees provided by
    PaUtil_AllocateMemory().
*/


#include "portaudio.h"

#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */


struct PaUtilHostApiRepresentation;


/** Retrieve a specific host API representation. This function can be used
 by implementations to retrieve a pointer to their representation in
 host api specific extension functions which aren't passed a rep pointer
 by pa_front.c.

 @param hostApi A pointer to a host API represenation pointer. Apon success
 this will receive the requested representation pointer.

 @param type A valid host API type identifier.

 @returns An error code. If the result is PaNoError then a pointer to the
 requested host API representation will be stored in *hostApi. If the host API
 specified by type is not found, this function returns paHostApiNotFound.
*/
PaError PaUtil_GetHostApiRepresentation( struct PaUtilHostApiRepresentation **hostApi,
        PaHostApiTypeId type );


/** Convert a PortAudio device index into a host API specific device index.
 @param hostApiDevice Pointer to a device index, on success this will recieve the
 converted device index value.
 @param device The PortAudio device index to convert.
 @param hostApi The host api which the index should be converted for.

 @returns On success returns PaNoError and places the converted index in the
 hostApiDevice parameter.
*/
PaError PaUtil_DeviceIndexToHostApiDeviceIndex(
        PaDeviceIndex *hostApiDevice, PaDeviceIndex device,
        struct PaUtilHostApiRepresentation *hostApi );


/** Set the host error information returned by Pa_GetLastHostErrorInfo. This
 function and the paUnanticipatedHostError error code should be used as a
 last resort.  Implementors should use existing PA error codes where possible,
 or nominate new ones. Note that at it is always better to use
 PaUtil_SetLastHostErrorInfo() and paUnanticipatedHostError than to return an
 ambiguous or inaccurate PaError code.

 @param hostApiType  The host API which encountered the error (ie of the caller)

 @param errorCode The error code returned by the native API function.

 @param errorText A string describing the error. PaUtil_SetLastHostErrorInfo
 makes a copy of the string, so it is not necessary for the pointer to remain
 valid after the call to PaUtil_SetLastHostErrorInfo() returns.

*/
void PaUtil_SetLastHostErrorInfo( PaHostApiTypeId hostApiType, long errorCode,
        const char *errorText );


        
/** PA_DEBUG() provides a simple debug message printing facility. The macro
 passes it's argument to a printf-like function called PaUtil_DebugPrint()
 which prints to stderr and always flushes the stream after printing.
 Because preprocessor macros cannot directly accept variable length argument
 lists, calls to the macro must include an additional set of parenthesis, eg:
 PA_DEBUG(("errorno: %d", 1001 ));
*/

void PaUtil_DebugPrint( const char *format, ... );

#if (0) /* set to 1 to print debug messages */
#define PA_DEBUG(x) PaUtil_DebugPrint x ;
#else
#define PA_DEBUG(x)
#endif


/* the following functions are implemented in a platform platform specific
 .c file
*/

/** Allocate size bytes, guaranteed to be aligned to a FIXME byte boundary */
void *PaUtil_AllocateMemory( long size );


/** Realease block if non-NULL. block may be NULL */
void PaUtil_FreeMemory( void *block );


/** Return the number of currently allocated blocks. This function can be
 used for detecting memory leaks.

 @note Allocations will only be tracked if PA_TRACK_MEMORY is #defined. If
 it isn't, this function will always return 0.
*/
int PaUtil_CountCurrentlyAllocatedBlocks( void );


/** Initialize the clock used by PaUtil_GetTime(). Call this before calling
 PaUtil_GetTime.

 @see PaUtil_GetTime
*/
void PaUtil_InitializeClock( void );


/** Return the system time in seconds. Used to implement CPU load functions

 @see PaUtil_InitializeClock
*/
double PaUtil_GetTime( void );


/* void Pa_Sleep( long msec );  must also be implemented in per-platform .c file */



#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* PA_UTIL_H */

--- NEW FILE: pa_cpuload.h ---
#ifndef PA_CPULOAD_H
#define PA_CPULOAD_H
/*
 * $Id: pa_cpuload.h,v 1.3 2004/09/06 20:44:38 millerpuckette Exp $
 * Portable Audio I/O Library CPU Load measurement functions
 * Portable CPU load measurement facility.
 *
 * Based on the Open Source API proposed by Ross Bencina
 * Copyright (c) 2002 Ross Bencina
 *
 * 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:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * Any person wishing to distribute modifications to the Software is
 * requested to send the modifications to the original developer so that
 * they can be incorporated into the canonical version.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/** @file
 @brief Functions to assist in measuring the CPU utilization of a callback
 stream. Used to implement the Pa_GetStreamCpuLoad() function.
*/


#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */


typedef struct {
    double samplingPeriod;
    double measurementStartTime;
    double averageLoad;
} PaUtilCpuLoadMeasurer; /**< @todo need better name than measurer */

void PaUtil_InitializeCpuLoadMeasurer( PaUtilCpuLoadMeasurer* measurer, double sampleRate );
void PaUtil_BeginCpuLoadMeasurement( PaUtilCpuLoadMeasurer* measurer );
void PaUtil_EndCpuLoadMeasurement( PaUtilCpuLoadMeasurer* measurer, unsigned long framesProcessed );
void PaUtil_ResetCpuLoadMeasurer( PaUtilCpuLoadMeasurer* measurer );
double PaUtil_GetCpuLoad( PaUtilCpuLoadMeasurer* measurer );


#ifdef __cplusplus
}
#endif /* __cplusplus */     
#endif /* PA_CPULOAD_H */

--- NEW FILE: pa_stream.h ---
#ifndef PA_STREAM_H
#define PA_STREAM_H
/*
 * $Id: pa_stream.h,v 1.3 2004/09/06 20:44:38 millerpuckette Exp $
 * Portable Audio I/O Library
 * stream interface
 *
 * 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:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * Any person wishing to distribute modifications to the Software is
 * requested to send the modifications to the original developer so that
 * they can be incorporated into the canonical version.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/** @file
 @brief Interface used by pa_front to virtualize functions which operate on
 streams.
*/


#include "portaudio.h"

#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */


#define PA_STREAM_MAGIC (0x18273645)


/** A structure representing an (abstract) interface to a host API. Contains
 pointers to functions which implement the interface.

 All PaStreamInterface functions are guaranteed to be called with a non-null,
 valid stream parameter.
*/
typedef struct {
    PaError (*Close)( PaStream* stream );
    PaError (*Start)( PaStream *stream );
    PaError (*Stop)( PaStream *stream );
    PaError (*Abort)( PaStream *stream );
    PaError (*IsStopped)( PaStream *stream );
    PaError (*IsActive)( PaStream *stream );
    PaTime (*GetTime)( PaStream *stream );
    double (*GetCpuLoad)( PaStream* stream );
    PaError (*Read)( PaStream* stream, void *buffer, unsigned long frames );
    PaError (*Write)( PaStream* stream, const void *buffer, unsigned long frames );
    signed long (*GetReadAvailable)( PaStream* stream );
    signed long (*GetWriteAvailable)( PaStream* stream );
} PaUtilStreamInterface;


/** Initialize the fields of a PaUtilStreamInterface structure.
*/
void PaUtil_InitializeStreamInterface( PaUtilStreamInterface *streamInterface,
    PaError (*Close)( PaStream* ),
    PaError (*Start)( PaStream* ),
    PaError (*Stop)( PaStream* ),
    PaError (*Abort)( PaStream* ),
    PaError (*IsStopped)( PaStream* ),
    PaError (*IsActive)( PaStream* ),
    PaTime (*GetTime)( PaStream* ),
    double (*GetCpuLoad)( PaStream* ),
    PaError (*Read)( PaStream* stream, void *buffer, unsigned long frames ),
    PaError (*Write)( PaStream* stream, const void *buffer, unsigned long frames ),
    signed long (*GetReadAvailable)( PaStream* stream ),
    signed long (*GetWriteAvailable)( PaStream* stream ) );


/** Dummy Read function for use in interfaces to a callback based streams.
 Pass to the Read parameter of PaUtil_InitializeStreamInterface.
 @return An error code indicating that the function has no effect
 because the stream is a callback stream.
*/
PaError PaUtil_DummyRead( PaStream* stream,
                       void *buffer,
                       unsigned long frames );


/** Dummy Write function for use in an interfaces to callback based streams.
 Pass to the Write parameter of PaUtil_InitializeStreamInterface.
 @return An error code indicating that the function has no effect
 because the stream is a callback stream.
*/
PaError PaUtil_DummyWrite( PaStream* stream,
                       const void *buffer,
                       unsigned long frames );


/** Dummy GetReadAvailable function for use in interfaces to callback based
 streams. Pass to the GetReadAvailable parameter of PaUtil_InitializeStreamInterface.
 @return An error code indicating that the function has no effect
 because the stream is a callback stream.
*/
signed long PaUtil_DummyGetReadAvailable( PaStream* stream );


/** Dummy GetWriteAvailable function for use in interfaces to callback based
 streams. Pass to the GetWriteAvailable parameter of PaUtil_InitializeStreamInterface.
 @return An error code indicating that the function has no effect
 because the stream is a callback stream.
*/
signed long PaUtil_DummyGetWriteAvailable( PaStream* stream );



/** Dummy GetCpuLoad function for use in an interface to a read/write stream.
 Pass to the GetCpuLoad parameter of PaUtil_InitializeStreamInterface.
 @return Returns 0.
*/
double PaUtil_DummyGetCpuLoad( PaStream* stream );


/** Non host specific data for a stream. This data is used by pa_front to
 forward to the appropriate functions in the streamInterface structure.
*/
typedef struct PaUtilStreamRepresentation {
    unsigned long magic;    /**< set to PA_STREAM_MAGIC */
    struct PaUtilStreamRepresentation *nextOpenStream; /**< field used by multi-api code */
    PaUtilStreamInterface *streamInterface;
    PaStreamCallback *streamCallback;
    PaStreamFinishedCallback *streamFinishedCallback;
    void *userData;
    PaStreamInfo streamInfo;
} PaUtilStreamRepresentation;


/** Initialize a PaUtilStreamRepresentation structure.

 @see PaUtil_InitializeStreamRepresentation
*/
void PaUtil_InitializeStreamRepresentation(
        PaUtilStreamRepresentation *streamRepresentation,
        PaUtilStreamInterface *streamInterface,
        PaStreamCallback *streamCallback,
        void *userData );
        

/** Clean up a PaUtilStreamRepresentation structure previously initialized
 by a call to PaUtil_InitializeStreamRepresentation.

 @see PaUtil_InitializeStreamRepresentation
*/
void PaUtil_TerminateStreamRepresentation( PaUtilStreamRepresentation *streamRepresentation );


/** Check that the stream pointer is valid.

 @return Returns paNoError if the stream pointer appears to be OK, otherwise
 returns an error indicating the cause of failure.
*/
PaError PaUtil_ValidateStreamPointer( PaStream *stream );


/** Cast an opaque stream pointer into a pointer to a PaUtilStreamRepresentation.

 @see PaUtilStreamRepresentation
*/
#define PA_STREAM_REP( stream )\
    ((PaUtilStreamRepresentation*) (stream) )


/** Cast an opaque stream pointer into a pointer to a PaUtilStreamInterface.

 @see PaUtilStreamRepresentation, PaUtilStreamInterface
*/
#define PA_STREAM_INTERFACE( stream )\
    PA_STREAM_REP( (stream) )->streamInterface


    
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* PA_STREAM_H */

--- NEW FILE: pa_dither.c ---
/*
 * $Id: pa_dither.c,v 1.3 2004/09/06 20:44:38 millerpuckette Exp $
 * Portable Audio I/O Library triangular dither generator
 *
 * Based on the Open Source API proposed by Ross Bencina
 * Copyright (c) 1999-2002 Phil Burk, Ross Bencina
 *
 * 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:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * Any person wishing to distribute modifications to the Software is
 * requested to send the modifications to the original developer so that
 * they can be incorporated into the canonical version.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/** @file
 @brief Functions for generating dither noise
*/


#include "pa_dither.h"

#define PA_DITHER_BITS_   (15)


void PaUtil_InitializeTriangularDitherState( PaUtilTriangularDitherGenerator *state )
{
    state->previous = 0;
    state->randSeed1 = 22222;
    state->randSeed2 = 5555555;
}


signed long PaUtil_Generate16BitTriangularDither( PaUtilTriangularDitherGenerator *state )
{
    signed long current, highPass;

    /* Generate two random numbers. */
    state->randSeed1 = (state->randSeed1 * 196314165) + 907633515;
    state->randSeed2 = (state->randSeed2 * 196314165) + 907633515;

    /* Generate triangular distribution about 0.
     * Shift before adding to prevent overflow which would skew the distribution.
     * Also shift an extra bit for the high pass filter. 
     */
#define DITHER_SHIFT_  ((32 - PA_DITHER_BITS_) + 1)
    current = (((signed long)state->randSeed1)>>DITHER_SHIFT_) +
              (((signed long)state->randSeed2)>>DITHER_SHIFT_);

    /* High pass filter to reduce audibility. */
    highPass = current - state->previous;
    state->previous = current;
    return highPass;
}


/* Multiply by PA_FLOAT_DITHER_SCALE_ to get a float between -2.0 and +1.99999 */
#define PA_FLOAT_DITHER_SCALE_  (1.0f / ((1<<PA_DITHER_BITS_)-1))
static const float const_float_dither_scale_ = PA_FLOAT_DITHER_SCALE_;

float PaUtil_GenerateFloatTriangularDither( PaUtilTriangularDitherGenerator *state )
{
    signed long current, highPass;

    /* Generate two random numbers. */
    state->randSeed1 = (state->randSeed1 * 196314165) + 907633515;
    state->randSeed2 = (state->randSeed2 * 196314165) + 907633515;

    /* Generate triangular distribution about 0.
     * Shift before adding to prevent overflow which would skew the distribution.
     * Also shift an extra bit for the high pass filter. 
     */
#define DITHER_SHIFT_  ((32 - PA_DITHER_BITS_) + 1)
    current = (((signed long)state->randSeed1)>>DITHER_SHIFT_) +
              (((signed long)state->randSeed2)>>DITHER_SHIFT_);

    /* High pass filter to reduce audibility. */
    highPass = current - state->previous;
    state->previous = current;
    return ((float)highPass) * const_float_dither_scale_;
}


/*
The following alternate dither algorithms (from musicdsp.org) could be
considered
*/

/*Noise shaped dither  (March 2000)
-------------------

This is a simple implementation of highpass triangular-PDF dither with
2nd-order noise shaping, for use when truncating floating point audio
data to fixed point.

The noise shaping lowers the noise floor by 11dB below 5kHz (@ 44100Hz
sample rate) compared to triangular-PDF dither. The code below assumes
input data is in the range +1 to -1 and doesn't check for overloads!

To save time when generating dither for multiple channels you can do
things like this:  r3=(r1 & 0x7F)<<8; instead of calling rand() again.



  int   r1, r2;                //rectangular-PDF random numbers
  float s1, s2;                //error feedback buffers
  float s = 0.5f;              //set to 0.0f for no noise shaping
  float w = pow(2.0,bits-1);   //word length (usually bits=16)
  float wi= 1.0f/w;            
  float d = wi / RAND_MAX;     //dither amplitude (2 lsb)
  float o = wi * 0.5f;         //remove dc offset
  float in, tmp;
  int   out;


//for each sample...

  r2=r1;                               //can make HP-TRI dither by
  r1=rand();                           //subtracting previous rand()
    
  in += s * (s1 + s1 - s2);            //error feedback
  tmp = in + o + d * (float)(r1 - r2); //dc offset and dither 
  
  out = (int)(w * tmp);                //truncate downwards
  if(tmp<0.0f) out--;                  //this is faster than floor()

  s2 = s1;                            
  s1 = in - wi * (float)out;           //error



-- 
paul.kellett at maxim.abel.co.uk
http://www.maxim.abel.co.uk
*/


/*
16-to-8-bit first-order dither

Type : First order error feedforward dithering code
References : Posted by Jon Watte

Notes : 
This is about as simple a dithering algorithm as you can implement, but it's
likely to sound better than just truncating to N bits.

Note that you might not want to carry forward the full difference for infinity.
It's probably likely that the worst performance hit comes from the saturation
conditionals, which can be avoided with appropriate instructions on many DSPs
and integer SIMD type instructions, or CMOV.

Last, if sound quality is paramount (such as when going from > 16 bits to 16
bits) you probably want to use a higher-order dither function found elsewhere
on this site. 


Code : 
// This code will down-convert and dither a 16-bit signed short 
// mono signal into an 8-bit unsigned char signal, using a first 
// order forward-feeding error term dither. 

#define uchar unsigned char 

void dither_one_channel_16_to_8( short * input, uchar * output, int count, int * memory ) 
{ 
  int m = *memory; 
  while( count-- > 0 ) { 
    int i = *input++; 
    i += m; 
    int j = i + 32768 - 128; 
    uchar o; 
    if( j < 0 ) { 
      o = 0; 
    } 
    else if( j > 65535 ) { 
      o = 255; 
    } 
    else { 
      o = (uchar)((j>>8)&0xff); 
    } 
    m = ((j-32768+128)-i); 
    *output++ = o; 
  } 
  *memory = m; 
} 
*/

--- NEW FILE: pa_trace.c ---
/*
 * $Id: pa_trace.c,v 1.3 2004/09/06 20:44:38 millerpuckette Exp $
 * Portable Audio I/O Library Trace Facility
 * Store trace information in real-time for later printing.
 *
 * Based on the Open Source API proposed by Ross Bencina
 * Copyright (c) 1999-2000 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:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * Any person wishing to distribute modifications to the Software is
 * requested to send the modifications to the original developer so that
 * they can be incorporated into the canonical version.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/** @file
 @brief Event trace mechanism for debugging.
*/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "pa_trace.h"

#if PA_TRACE_REALTIME_EVENTS

static char *traceTextArray[MAX_TRACE_RECORDS];
static int traceIntArray[MAX_TRACE_RECORDS];
static int traceIndex = 0;
static int traceBlock = 0;

/*********************************************************************/
void PaUtil_ResetTraceMessages()
{
    traceIndex = 0;
}

/*********************************************************************/
void PaUtil_DumpTraceMessages()
{
    int i;
    int messageCount = (traceIndex < PA_MAX_TRACE_RECORDS) ? traceIndex : PA_MAX_TRACE_RECORDS;

    printf("DumpTraceMessages: traceIndex = %d\n", traceIndex );
    for( i=0; i<messageCount; i++ )
    {
        printf("%3d: %s = 0x%08X\n",
               i, traceTextArray[i], traceIntArray[i] );
    }
    ResetTraceMessages();
    fflush(stdout);
}

/*********************************************************************/
void PaUtil_AddTraceMessage( const char *msg, int data )
{
    if( (traceIndex == PA_MAX_TRACE_RECORDS) && (traceBlock == 0) )
    {
        traceBlock = 1;
        /*  PaUtil_DumpTraceMessages(); */
    }
    else if( traceIndex < PA_MAX_TRACE_RECORDS )
    {
        traceTextArray[traceIndex] = msg;
        traceIntArray[traceIndex] = data;
        traceIndex++;
    }
}

#endif /* TRACE_REALTIME_EVENTS */

--- NEW FILE: pa_process.c ---
/*
 * $Id: pa_process.c,v 1.3 2004/09/06 20:44:38 millerpuckette Exp $
 * Portable Audio I/O Library
 * streamCallback <-> host buffer processing adapter
 *
 * 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:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
[...1701 lines suppressed...]

    hostOutputChannels = bp->hostOutputChannels[0];
    framesToZero = PA_MIN_( bp->hostOutputFrameCount[0], frameCount );

    for( i=0; i<bp->outputChannelCount; ++i )
    {
        bp->outputZeroer(   hostOutputChannels[i].data,
                            hostOutputChannels[i].stride,
                            framesToZero );


        /* advance dest ptr for next iteration */
        hostOutputChannels[i].data = ((unsigned char*)hostOutputChannels[i].data) +
                framesToZero * hostOutputChannels[i].stride * bp->bytesPerHostOutputSample;
    }

    bp->hostOutputFrameCount[0] += framesToZero;
    
    return framesToZero;
}

--- NEW FILE: pa_dither.h ---
#ifndef PA_DITHER_H
#define PA_DITHER_H
/*
 * $Id: pa_dither.h,v 1.3 2004/09/06 20:44:38 millerpuckette Exp $
 * Portable Audio I/O Library triangular dither generator
 *
 * Based on the Open Source API proposed by Ross Bencina
 * Copyright (c) 1999-2002 Phil Burk, Ross Bencina
 *
 * 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:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * Any person wishing to distribute modifications to the Software is
 * requested to send the modifications to the original developer so that
 * they can be incorporated into the canonical version.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/** @file
 @brief Functions for generating dither noise
*/


#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */


/** @brief State needed to generate a dither signal */
typedef struct PaUtilTriangularDitherGenerator{
    unsigned long previous;
    unsigned long randSeed1;
    unsigned long randSeed2;
} PaUtilTriangularDitherGenerator;


/** @brief Initialize dither state */
void PaUtil_InitializeTriangularDitherState( PaUtilTriangularDitherGenerator *ditherState );


/**
 @brief Calculate 2 LSB dither signal with a triangular distribution.
 Ranged for adding to a 1 bit right-shifted 32 bit integer
 prior to >>15. eg:
<pre>
    signed long in = *
    signed long dither = PaUtil_Generate16BitTriangularDither( ditherState );
    signed short out = (signed short)(((in>>1) + dither) >> 15);
</pre>
 @return
 A signed long with a range of +32767 to -32768
*/
signed long PaUtil_Generate16BitTriangularDither( PaUtilTriangularDitherGenerator *ditherState );


/**
 @brief Calculate 2 LSB dither signal with a triangular distribution.
 Ranged for adding to a pre-scaled float.
<pre>
    float in = *
    float dither = PaUtil_GenerateFloatTriangularDither( ditherState );
    // use smaller scaler to prevent overflow when we add the dither
    signed short out = (signed short)(in*(32766.0f) + dither );
</pre>
 @return
 A float with a range of -2.0 to +1.99999.
*/
float PaUtil_GenerateFloatTriangularDither( PaUtilTriangularDitherGenerator *ditherState );



#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* PA_DITHER_H */

--- NEW FILE: pa_front.c ---
/*
 * $Id: pa_front.c,v 1.3 2004/09/06 20:44:38 millerpuckette Exp $
 * Portable Audio I/O Library Multi-Host API front end
 * Validate function parameters and manage multiple host APIs.
 *
 * 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:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
[...1935 lines suppressed...]
    case paInt32:
        result = 4;
        break;

    default:
        result = paSampleFormatNotSupported;
        break;
    }

#ifdef PA_LOG_API_CALLS
    PaUtil_DebugPrint("Pa_GetSampleSize returned:\n" );
    if( result > 0 )
        PaUtil_DebugPrint("\tint: %d\n\n", result );
    else
        PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
#endif

    return (PaError) result;
}


--- NEW FILE: pa_cpuload.c ---
/*
 * $Id: pa_cpuload.c,v 1.3 2004/09/06 20:44:38 millerpuckette Exp $
 * Portable Audio I/O Library CPU Load measurement functions
 * Portable CPU load measurement facility.
 *
 * Based on the Open Source API proposed by Ross Bencina
 * Copyright (c) 2002 Ross Bencina
 *
 * 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:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * Any person wishing to distribute modifications to the Software is
 * requested to send the modifications to the original developer so that
 * they can be incorporated into the canonical version.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/** @file
 @brief Functions to assist in measuring the CPU utilization of a callback
 stream. Used to implement the Pa_GetStreamCpuLoad() function.

 @todo Dynamically calculate the coefficients used to smooth the CPU Load
 Measurements over time to provide a uniform characterisation of CPU Load
 independent of rate at which PaUtil_BeginCpuLoadMeasurement /
 PaUtil_EndCpuLoadMeasurement are called.
*/


#include "pa_cpuload.h"

#include <assert.h>

#include "pa_util.h"   /* for PaUtil_GetTime() */


void PaUtil_InitializeCpuLoadMeasurer( PaUtilCpuLoadMeasurer* measurer, double sampleRate )
{
    assert( sampleRate > 0 );

    measurer->samplingPeriod = 1. / sampleRate;
    measurer->averageLoad = 0.;
}

void PaUtil_ResetCpuLoadMeasurer( PaUtilCpuLoadMeasurer* measurer )
{
    measurer->averageLoad = 0.;
}

void PaUtil_BeginCpuLoadMeasurement( PaUtilCpuLoadMeasurer* measurer )
{
    measurer->measurementStartTime = PaUtil_GetTime();
}


void PaUtil_EndCpuLoadMeasurement( PaUtilCpuLoadMeasurer* measurer, unsigned long framesProcessed )
{
    double measurementEndTime, secondsFor100Percent, measuredLoad;

    if( framesProcessed > 0 ){
        measurementEndTime = PaUtil_GetTime();

        assert( framesProcessed > 0 );
        secondsFor100Percent = framesProcessed * measurer->samplingPeriod;

        measuredLoad = (measurementEndTime - measurer->measurementStartTime) / secondsFor100Percent;

        /* Low pass filter the calculated CPU load to reduce jitter using a simple IIR low pass filter. */
        /** FIXME @todo these coefficients shouldn't be hardwired */
#define LOWPASS_COEFFICIENT_0   (0.9)
#define LOWPASS_COEFFICIENT_1   (0.99999 - LOWPASS_COEFFICIENT_0)

        measurer->averageLoad = (LOWPASS_COEFFICIENT_0 * measurer->averageLoad) +
                               (LOWPASS_COEFFICIENT_1 * measuredLoad);
    }
}


double PaUtil_GetCpuLoad( PaUtilCpuLoadMeasurer* measurer )
{
    return measurer->averageLoad;
}





More information about the Pd-cvs mailing list