/* * Copyright (c) 1999-2006, Regents of the University of California * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the University of California, Berkeley nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Automatically generated library file psys * The drivers embedded in this file may be covered by a different * license. Scroll down to see the license appearing before each * driver, or see sfront/src/lib/ directories for driver source file. */ #include "tree.h" void makepa_hosthdr(void) { int lc = 0; z[lc++]="#ifndef PA_HOST_H"; z[lc++]="#define PA_HOST_H"; z[lc++]=""; z[lc++]="/*"; z[lc++]=" * Host dependant internal API for PortAudio"; z[lc++]=" *"; z[lc++]=" * Author: Phil Burk "; z[lc++]=" *"; z[lc++]=" * PortAudio Portable Real-Time Audio Library"; z[lc++]=" * Latest Version at: http://www.softsynth.com/portaudio/"; z[lc++]=" * DirectSound and Macintosh Implementation"; z[lc++]=" * Copyright (c) 1999-2000 Phil Burk"; z[lc++]=" *"; z[lc++]=" * Permission is hereby granted, free of charge, to any person obtaining"; z[lc++]=" * a copy of this software and associated documentation files"; z[lc++]=" * (the \"Software\"), to deal in the Software without restriction,"; z[lc++]=" * including without limitation the rights to use, copy, modify, merge,"; z[lc++]=" * publish, distribute, sublicense, and/or sell copies of the Software,"; z[lc++]=" * and to permit persons to whom the Software is furnished to do so,"; z[lc++]=" * subject to the following conditions:"; z[lc++]=" *"; z[lc++]=" * The above copyright notice and this permission notice shall be"; z[lc++]=" * included in all copies or substantial portions of the Software."; z[lc++]=" *"; z[lc++]=" * Any person wishing to distribute modifications to the Software is"; z[lc++]=" * requested to send the modifications to the original developer so that"; z[lc++]=" * they can be incorporated into the canonical version."; z[lc++]=" *"; z[lc++]=" * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,"; z[lc++]=" * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF"; z[lc++]=" * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT."; z[lc++]=" * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR"; z[lc++]=" * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF"; z[lc++]=" * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION"; z[lc++]=" * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."; z[lc++]=" *"; z[lc++]=" */"; z[lc++]=""; z[lc++]="#ifdef __cplusplus"; z[lc++]="extern \"C\" {"; z[lc++]="#endif /* __cplusplus */"; z[lc++]=""; z[lc++]="#ifndef SUPPORT_AUDIO_CAPTURE"; z[lc++]="#define SUPPORT_AUDIO_CAPTURE (1)"; z[lc++]="#endif"; z[lc++]=""; z[lc++]="#ifndef int32"; z[lc++]="typedef long int32;"; z[lc++]="#endif"; z[lc++]="#ifndef uint32"; z[lc++]="typedef unsigned long uint32;"; z[lc++]="#endif"; z[lc++]="#ifndef int16"; z[lc++]="typedef short int16;"; z[lc++]="#endif"; z[lc++]="#ifndef uint16"; z[lc++]="typedef unsigned short uint16;"; z[lc++]="#endif"; z[lc++]=""; z[lc++]="#define PA_MAGIC (0x18273645)"; z[lc++]=""; z[lc++]="/************************************************************************************/"; z[lc++]="/****************** Structures ******************************************************/"; z[lc++]="/************************************************************************************/"; z[lc++]=" "; z[lc++]="typedef struct internalPortAudioStream"; z[lc++]="{"; z[lc++]=" uint32 past_Magic; /* ID for struct to catch bugs. */"; z[lc++]="/* User specified information. */"; z[lc++]=" uint32 past_FramesPerUserBuffer;"; z[lc++]=" uint32 past_NumUserBuffers;"; z[lc++]=" double past_SampleRate; /* Closest supported sample rate. */"; z[lc++]=" int past_NumInputChannels;"; z[lc++]=" int past_NumOutputChannels;"; z[lc++]=" PaDeviceID past_InputDeviceID;"; z[lc++]=" PaDeviceID past_OutputDeviceID;"; z[lc++]=" PaSampleFormat past_InputSampleFormat;"; z[lc++]=" PaSampleFormat past_OutputSampleFormat;"; z[lc++]=" void *past_DeviceData;"; z[lc++]=" PortAudioCallback *past_Callback;"; z[lc++]=" void *past_UserData;"; z[lc++]=" uint32 past_Flags;"; z[lc++]="/* Flags for communicating between foreground and background. */"; z[lc++]=" volatile int past_IsActive; /* Background is still playing. */"; z[lc++]=" volatile int past_StopSoon; /* Background should keep playing when buffers empty. */"; z[lc++]=" volatile int past_StopNow; /* Background should stop playing now. */"; z[lc++]="/* These buffers are used when the native format does not match the user format. */"; z[lc++]=" void *past_InputBuffer;"; z[lc++]=" uint32 past_InputBufferSize;"; z[lc++]=" void *past_OutputBuffer;"; z[lc++]=" uint32 past_OutputBufferSize;"; z[lc++]="/* Measurements */"; z[lc++]=" uint32 past_NumCallbacks;"; z[lc++]=" PaTimestamp past_FrameCount; /* Frames output to buffer. */"; z[lc++]="/* For measuring CPU utilization. */"; z[lc++]=" double past_AverageInsideCount;"; z[lc++]=" double past_AverageTotalCount;"; z[lc++]=" double past_Usage;"; z[lc++]=" int past_IfLastExitValid;"; z[lc++]="} internalPortAudioStream;"; z[lc++]=""; z[lc++]="/************************************************************************************/"; z[lc++]="/****************** Prototypes ******************************************************/"; z[lc++]="/************************************************************************************/"; z[lc++]=""; z[lc++]="PaError PaHost_Init( void );"; z[lc++]="PaError PaHost_Term( void );"; z[lc++]=""; z[lc++]="PaError PaHost_OpenStream( internalPortAudioStream *past );"; z[lc++]="PaError PaHost_CloseStream( internalPortAudioStream *past );"; z[lc++]=""; z[lc++]="PaError PaHost_StartOutput( internalPortAudioStream *past );"; z[lc++]="PaError PaHost_StopOutput( internalPortAudioStream *past, int abort );"; z[lc++]="PaError PaHost_StartInput( internalPortAudioStream *past );"; z[lc++]="PaError PaHost_StopInput( internalPortAudioStream *past, int abort );"; z[lc++]="PaError PaHost_StartEngine( internalPortAudioStream *past );"; z[lc++]="PaError PaHost_StopEngine( internalPortAudioStream *past, int abort );"; z[lc++]="PaError PaHost_StreamActive( internalPortAudioStream *past );"; z[lc++]=""; z[lc++]="long Pa_CallConvertInt16( internalPortAudioStream *past, "; z[lc++]=" short *nativeInputBuffer,"; z[lc++]=" short *nativeOutputBuffer );"; z[lc++]=""; z[lc++]="long Pa_CallConvertFloat32( internalPortAudioStream *past, "; z[lc++]=" float *nativeInputBuffer,"; z[lc++]=" float *nativeOutputBuffer );"; z[lc++]=""; z[lc++]="void *PaHost_AllocateFastMemory( long numBytes );"; z[lc++]="void PaHost_FreeFastMemory( void *addr, long numBytes );"; z[lc++]=""; z[lc++]="PaError PaHost_ValidateSampleRate( PaDeviceID id, double requestedFrameRate,"; z[lc++]=" double *closestFrameRatePtr );"; z[lc++]="int PaHost_FindClosestTableEntry( double allowableError, const double *rateTable,"; z[lc++]=" int numRates, double frameRate );"; z[lc++]=""; z[lc++]="#ifdef __cplusplus"; z[lc++]="}"; z[lc++]="#endif /* __cplusplus */"; z[lc++]="#endif /* PA_HOST_H */"; printlib(lc); } void makepa_porthdr(void) { int lc = 0; z[lc++]="#ifndef PORT_AUDIO_H"; z[lc++]="#define PORT_AUDIO_H"; z[lc++]=""; z[lc++]="#ifdef __cplusplus"; z[lc++]="extern \"C\" {"; z[lc++]="#endif /* __cplusplus */"; z[lc++]=""; z[lc++]="/*"; z[lc++]=" * PortAudio Portable Real-Time Audio Library"; z[lc++]=" * PortAudio API Header File"; z[lc++]=" * Latest version available at: http://www.audiomulch.com/portaudio/"; z[lc++]=" *"; z[lc++]=" * Copyright (c) 1999-2000 Ross Bencina and Phil Burk"; z[lc++]=" *"; z[lc++]=" * Permission is hereby granted, free of charge, to any person obtaining"; z[lc++]=" * a copy of this software and associated documentation files"; z[lc++]=" * (the \"Software\"), to deal in the Software without restriction,"; z[lc++]=" * including without limitation the rights to use, copy, modify, merge,"; z[lc++]=" * publish, distribute, sublicense, and/or sell copies of the Software,"; z[lc++]=" * and to permit persons to whom the Software is furnished to do so,"; z[lc++]=" * subject to the following conditions:"; z[lc++]=" *"; z[lc++]=" * The above copyright notice and this permission notice shall be"; z[lc++]=" * included in all copies or substantial portions of the Software."; z[lc++]=" *"; z[lc++]=" * Any person wishing to distribute modifications to the Software is"; z[lc++]=" * requested to send the modifications to the original developer so that"; z[lc++]=" * they can be incorporated into the canonical version."; z[lc++]=" *"; z[lc++]=" * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,"; z[lc++]=" * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF"; z[lc++]=" * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT."; z[lc++]=" * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR"; z[lc++]=" * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF"; z[lc++]=" * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION"; z[lc++]=" * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."; z[lc++]=" *"; z[lc++]=" */"; z[lc++]=""; z[lc++]="typedef int PaError;"; z[lc++]="typedef enum {"; z[lc++]=" paNoError = 0,"; z[lc++]=""; z[lc++]=" paHostError = -10000,"; z[lc++]=" paInvalidChannelCount,"; z[lc++]=" paInvalidSampleRate,"; z[lc++]=" paInvalidDeviceId,"; z[lc++]=" paInvalidFlag,"; z[lc++]=" paSampleFormatNotSupported,"; z[lc++]=" paBadIODeviceCombination,"; z[lc++]=" paInsufficientMemory,"; z[lc++]=" paBufferTooBig,"; z[lc++]=" paBufferTooSmall,"; z[lc++]=" paNullCallback,"; z[lc++]=" paBadStreamPtr,"; z[lc++]=" paTimedOut,"; z[lc++]=" paInternalError"; z[lc++]="} PaErrorNum;"; z[lc++]=""; z[lc++]="/*"; z[lc++]=" Pa_Initialize() is the library initialisation function - call this before"; z[lc++]=" using the library."; z[lc++]="*/"; z[lc++]=""; z[lc++]="PaError Pa_Initialize( void );"; z[lc++]=""; z[lc++]="/*"; z[lc++]=" Pa_Terminate() is the library termination function - call this after"; z[lc++]=" using the library."; z[lc++]="*/"; z[lc++]=""; z[lc++]="PaError Pa_Terminate( void );"; z[lc++]=""; z[lc++]="/*"; z[lc++]=" Return host specific error."; z[lc++]=" This can be called after receiving a paHostError."; z[lc++]="*/"; z[lc++]="long Pa_GetHostError( void );"; z[lc++]=""; z[lc++]="/*"; z[lc++]=" Translate the error number into a human readable message."; z[lc++]="*/"; z[lc++]="const char *Pa_GetErrorText( PaError errnum );"; z[lc++]=""; z[lc++]="/*"; z[lc++]=" Sample formats"; z[lc++]=""; z[lc++]=" These are formats used to pass sound data between the callback and the"; z[lc++]=" stream. Each device has a \"native\" format which may be used when optimum"; z[lc++]=" efficiency or control over conversion is required."; z[lc++]=""; z[lc++]=" Formats marked \"always available\" are supported (emulated) by all devices."; z[lc++]=""; z[lc++]=" The floating point representation uses +1.0 and -1.0 as the respective"; z[lc++]=" maximum and minimum."; z[lc++]=" "; z[lc++]="*/"; z[lc++]=""; z[lc++]="typedef unsigned long PaSampleFormat;"; z[lc++]="#define paFloat32 ((PaSampleFormat) (1<<0)) /*always available*/"; z[lc++]="#define paInt16 ((PaSampleFormat) (1<<1)) /*always available*/"; z[lc++]="#define paInt32 ((PaSampleFormat) (1<<2)) /*always available*/"; z[lc++]="#define paInt24 ((PaSampleFormat) (1<<3))"; z[lc++]="#define paPackedInt24 ((PaSampleFormat) (1<<4))"; z[lc++]="#define paInt8 ((PaSampleFormat) (1<<5))"; z[lc++]="#define paUInt8 ((PaSampleFormat) (1<<6)) /* unsigned 8 bit, 128 is \"ground\" */"; z[lc++]="#define paCustomFormat ((PaSampleFormat) (1<<16))"; z[lc++]=""; z[lc++]="/*"; z[lc++]=" Device enumeration mechanism."; z[lc++]=""; z[lc++]=" Device ids range from 0 to Pa_CountDevices()-1."; z[lc++]=""; z[lc++]=" Devices may support input, output or both. Device 0 is always the \"default\""; z[lc++]=" device and should support at least stereo in and out if that is available"; z[lc++]=" on the taget platform _even_ if this involves kludging an input/output"; z[lc++]=" device on platforms that usually separate input from output. Other platform"; z[lc++]=" specific devices are specified by positive device ids."; z[lc++]="*/"; z[lc++]=""; z[lc++]="typedef int PaDeviceID;"; z[lc++]="#define paNoDevice -1"; z[lc++]=""; z[lc++]="typedef struct{"; z[lc++]=" int structVersion; "; z[lc++]=" const char *name;"; z[lc++]=" int maxInputChannels;"; z[lc++]=" int maxOutputChannels;"; z[lc++]="/* Number of discrete rates, or -1 if range supported. */"; z[lc++]=" int numSampleRates;"; z[lc++]="/* Array of supported sample rates, or {min,max} if range supported. */"; z[lc++]=" const double *sampleRates;"; z[lc++]=" PaSampleFormat nativeSampleFormats;"; z[lc++]="} PaDeviceInfo;"; z[lc++]=""; z[lc++]=""; z[lc++]="int Pa_CountDevices();"; z[lc++]="/*"; z[lc++]=" Pa_GetDefaultInputDeviceID(), Pa_GetDefaultOutputDeviceID()"; z[lc++]=""; z[lc++]=" Return the default device ID or paNoDevice if there is no devices."; z[lc++]=" The result can be passed to Pa_OpenStream()."; z[lc++]=" "; z[lc++]=" On the PC, the user can specify a default device by"; z[lc++]=" setting an environment variable. For example, to use device #1."; z[lc++]=""; z[lc++]=" set PA_RECOMMENDED_OUTPUT_DEVICE=1"; z[lc++]=" "; z[lc++]=" The user should first determine the available device ID by using"; z[lc++]=" the supplied application \"pa_devs\"."; z[lc++]="*/"; z[lc++]="PaDeviceID Pa_GetDefaultInputDeviceID( void );"; z[lc++]="PaDeviceID Pa_GetDefaultOutputDeviceID( void );"; z[lc++]=""; z[lc++]="/*"; z[lc++]=" PaTimestamp is used to represent a continuous sample clock with arbitrary"; z[lc++]=" start time useful for syncronisation. The type is used in the outTime"; z[lc++]=" argument to the callback function and the result of Pa_StreamTime()"; z[lc++]="*/"; z[lc++]=""; z[lc++]="typedef double PaTimestamp;"; z[lc++]=""; z[lc++]="/*"; z[lc++]=" Pa_GetDeviceInfo() returns a pointer to an immutable PaDeviceInfo structure"; z[lc++]=" referring to the device specified by id."; z[lc++]=" If id is out of range the function returns NULL."; z[lc++]=""; z[lc++]=" The returned structure is owned by the PortAudio implementation and must"; z[lc++]=" not be manipulated or freed. The pointer is guaranteed to be valid until"; z[lc++]=" between calls to Pa_Initialize() and Pa_Terminate()."; z[lc++]="*/"; z[lc++]=""; z[lc++]="const PaDeviceInfo* Pa_GetDeviceInfo( PaDeviceID devID );"; z[lc++]=""; z[lc++]="/*"; z[lc++]=" PortAudioCallback is implemented by clients of the portable audio api."; z[lc++]=""; z[lc++]=" inputBuffer and outputBuffer are arrays of interleaved samples,"; z[lc++]=" the format, packing and number of channels used by the buffers are"; z[lc++]=" determined by parameters to Pa_OpenStream() (see below)."; z[lc++]=""; z[lc++]=" framesPerBuffer is the number of sample frames to be processed by the callback."; z[lc++]=""; z[lc++]=" outTime is the time in samples when the buffer(s) processed by"; z[lc++]=" this callback will begin being played at the audio output."; z[lc++]=" See also Pa_StreamTime()"; z[lc++]=""; z[lc++]=" userData is the value of a user supplied pointer passed to Pa_OpenStream()"; z[lc++]=" intended for storing synthesis data etc."; z[lc++]=""; z[lc++]=" return value:"; z[lc++]=" The callback can return a nonzero value to stop the stream. This may be"; z[lc++]=" useful in applications such as soundfile players where a specific duration"; z[lc++]=" of output is required. However, it is not necessary to utilise this mechanism"; z[lc++]=" as StopStream() will also terminate the stream. A callback returning a"; z[lc++]=" nonzero value must fill the entire outputBuffer."; z[lc++]=""; z[lc++]=" NOTE: None of the other stream functions may be called from within the"; z[lc++]=" callback function except for Pa_GetCPULoad()."; z[lc++]=""; z[lc++]="*/"; z[lc++]=""; z[lc++]="typedef int (PortAudioCallback)("; z[lc++]=" void *inputBuffer, void *outputBuffer,"; z[lc++]=" unsigned long framesPerBuffer,"; z[lc++]=" PaTimestamp outTime, void *userData );"; z[lc++]=""; z[lc++]=""; z[lc++]="/*"; z[lc++]=" Stream flags"; z[lc++]=""; z[lc++]=" These flags may be supplied (ored together) in the streamFlags argument to"; z[lc++]=" the Pa_OpenStream() function."; z[lc++]=""; z[lc++]=" [ suggestions? ]"; z[lc++]="*/"; z[lc++]=""; z[lc++]="#define paNoFlag (0)"; z[lc++]="#define paClipOff (1<<0) /* disable defult clipping of out of range samples */"; z[lc++]="#define paDitherOff (1<<1) /* disable default dithering */"; z[lc++]="#define paPlatformSpecificFlags (0x00010000)"; z[lc++]="typedef unsigned long PaStreamFlags;"; z[lc++]=""; z[lc++]="/*"; z[lc++]=" A single PortAudioStream provides multiple channels of real-time"; z[lc++]=" input and output audio streaming to a client application."; z[lc++]=" Pointers to PortAudioStream objects are passed between PortAudio functions."; z[lc++]="*/"; z[lc++]=""; z[lc++]="typedef void PortAudioStream;"; z[lc++]="#define PaStream PortAudioStream"; z[lc++]=""; z[lc++]="/*"; z[lc++]=" Pa_OpenStream() opens a stream for either input, output or both."; z[lc++]=""; z[lc++]=" stream is the address of a PortAudioStream pointer which will receive"; z[lc++]=" a pointer to the newly opened stream."; z[lc++]=""; z[lc++]=" inputDevice is the id of the device used for input (see PaDeviceID above.)"; z[lc++]=" inputDevice may be paNoDevice to indicate that an input device is not required."; z[lc++]=""; z[lc++]=" numInputChannels is the number of channels of sound to be delivered to the"; z[lc++]=" callback. It can range from 1 to the value of maxInputChannels in the"; z[lc++]=" device input record for the device specified in the inputDevice parameter."; z[lc++]=" If inputDevice is paNoDevice numInputChannels is ignored."; z[lc++]=""; z[lc++]=" inputSampleFormat is the format of inputBuffer provided to the callback"; z[lc++]=" function. inputSampleFormat may be any of the formats described by the"; z[lc++]=" PaSampleFormat enumeration (see above). PortAudio guarantees support for"; z[lc++]=" the sound devices native formats (nativeSampleFormats in the device info"; z[lc++]=" record) and additionally 16 and 32 bit integer and 32 bit floating point"; z[lc++]=" formats. Support for other formats is implementation defined."; z[lc++]=""; z[lc++]=" inputDriverInfo is a pointer to an optional driver specific data structure"; z[lc++]=" containing additional information for device setup or stream processing."; z[lc++]=" inputDriverInfo is never required for correct operation. If not used"; z[lc++]=" inputDriverInfo should be NULL."; z[lc++]=""; z[lc++]=" outputDevice is the id of the device used for output (see PaDeviceID above.)"; z[lc++]=" outputDevice may be paNoDevice to indicate that an output device is not required."; z[lc++]=""; z[lc++]=" numOutputChannels is the number of channels of sound to be supplied by the"; z[lc++]=" callback. See the definition of numInputChannels above for more details."; z[lc++]=""; z[lc++]=" outputSampleFormat is the sample format of the outputBuffer filled by the"; z[lc++]=" callback function. See the definition of inputSampleFormat above for more"; z[lc++]=" details."; z[lc++]=""; z[lc++]=" outputDriverInfo is a pointer to an optional driver specific data structure"; z[lc++]=" containing additional information for device setup or stream processing."; z[lc++]=" outputDriverInfo is never required for correct operation. If not used"; z[lc++]=" outputDriverInfo should be NULL."; z[lc++]=""; z[lc++]=" sampleRate is the desired sampleRate for input and output"; z[lc++]=""; z[lc++]=" framesPerBuffer is the length in sample frames of all internal sample buffers"; z[lc++]=" used for communication with platform specific audio routines. Wherever"; z[lc++]=" possible this corresponds to the framesPerBuffer parameter passed to the"; z[lc++]=" callback function."; z[lc++]=""; z[lc++]=" numberOfBuffers is the number of buffers used for multibuffered"; z[lc++]=" communication with the platform specific audio routines. This parameter is"; z[lc++]=" provided only as a guide - and does not imply that an implementation must"; z[lc++]=" use multibuffered i/o when reliable double buffering is available (such as"; z[lc++]=" SndPlayDoubleBuffer() on the Macintosh.)"; z[lc++]=""; z[lc++]=" streamFlags may contain a combination of flags ORed together."; z[lc++]=" These flags modify the behavior of the"; z[lc++]=" streaming process. Some flags may only be relevant to certain buffer formats."; z[lc++]=""; z[lc++]=" callback is a pointer to a client supplied function that is responsible"; z[lc++]=" for processing and filling input and output buffers (see above for details.)"; z[lc++]=""; z[lc++]=" userData is a client supplied pointer which is passed to the callback"; z[lc++]=" function. It could for example, contain a pointer to instance data necessary"; z[lc++]=" for processing the audio buffers."; z[lc++]=""; z[lc++]=" return value:"; z[lc++]=" Apon success Pa_OpenStream() returns PaNoError and places a pointer to a"; z[lc++]=" valid PortAudioStream in the stream argument. The stream is inactive (stopped)."; z[lc++]=" If a call to Pa_OpenStream() fails a nonzero error code is returned (see"; z[lc++]=" PAError above) and the value of stream is invalid."; z[lc++]=""; z[lc++]="*/"; z[lc++]=""; z[lc++]="PaError Pa_OpenStream( PortAudioStream** stream,"; z[lc++]=" PaDeviceID inputDevice,"; z[lc++]=" int numInputChannels,"; z[lc++]=" PaSampleFormat inputSampleFormat,"; z[lc++]=" void *inputDriverInfo,"; z[lc++]=" PaDeviceID outputDevice,"; z[lc++]=" int numOutputChannels,"; z[lc++]=" PaSampleFormat outputSampleFormat,"; z[lc++]=" void *outputDriverInfo,"; z[lc++]=" double sampleRate,"; z[lc++]=" unsigned long framesPerBuffer,"; z[lc++]=" unsigned long numberOfBuffers,"; z[lc++]=" PaStreamFlags streamFlags,"; z[lc++]=" PortAudioCallback *callback,"; z[lc++]=" void *userData );"; z[lc++]=""; z[lc++]=""; z[lc++]="/*"; z[lc++]=" Pa_OpenDefaultStream() is a simplified version of Pa_OpenStream() that"; z[lc++]=" opens the default input and/or ouput devices. Most parameters have"; z[lc++]=" identical meaning to their Pa_OpenStream() counterparts, with the following"; z[lc++]=" exceptions:"; z[lc++]=""; z[lc++]=" If either numInputChannels or numOutputChannels is 0 the respective device"; z[lc++]=" is not opened (same as passing paNoDevice in the device arguments to Pa_OpenStream() )"; z[lc++]=""; z[lc++]=" sampleFormat applies to both the input and output buffers."; z[lc++]="*/"; z[lc++]=""; z[lc++]="PaError Pa_OpenDefaultStream( PortAudioStream** stream,"; z[lc++]=" int numInputChannels,"; z[lc++]=" int numOutputChannels,"; z[lc++]=" PaSampleFormat sampleFormat,"; z[lc++]=" double sampleRate,"; z[lc++]=" unsigned long framesPerBuffer,"; z[lc++]=" unsigned long numberOfBuffers,"; z[lc++]=" PortAudioCallback *callback,"; z[lc++]=" void *userData );"; z[lc++]=" "; z[lc++]="/*"; z[lc++]=" Pa_CloseStream() closes an audio stream, flushing any pending buffers."; z[lc++]="*/"; z[lc++]=""; z[lc++]="PaError Pa_CloseStream( PortAudioStream* );"; z[lc++]=""; z[lc++]="/*"; z[lc++]=" Pa_StartStream() and Pa_StopStream() begin and terminate audio processing."; z[lc++]=" Pa_StopStream() waits until all pending audio buffers have been played."; z[lc++]=" Pa_AbortStream() stops playing immediately without waiting for pending"; z[lc++]=" buffers to complete."; z[lc++]="*/"; z[lc++]=""; z[lc++]="PaError Pa_StartStream( PortAudioStream *stream );"; z[lc++]=""; z[lc++]="PaError Pa_StopStream( PortAudioStream *stream );"; z[lc++]=""; z[lc++]="PaError Pa_AbortStream( PortAudioStream *stream );"; z[lc++]=""; z[lc++]="/*"; z[lc++]=" Pa_StreamActive() returns one when the stream is playing audio,"; z[lc++]=" zero when not playing, or a negative error number if the"; z[lc++]=" stream is invalid."; z[lc++]=" The stream is active between calls to Pa_StartStream() and Pa_StopStream(),"; z[lc++]=" but may also become inactive if the callback returns a non-zero value."; z[lc++]=" In the latter case, the stream is considered inactive after the last"; z[lc++]=" buffer has finished playing."; z[lc++]="*/"; z[lc++]=""; z[lc++]="PaError Pa_StreamActive( PortAudioStream *stream );"; z[lc++]=""; z[lc++]="/*"; z[lc++]=" Pa_StreamTime() returns the current output time for the stream in samples."; z[lc++]=" This time may be used as a time reference (for example syncronising audio to"; z[lc++]=" MIDI)."; z[lc++]="*/"; z[lc++]=""; z[lc++]="PaTimestamp Pa_StreamTime( PortAudioStream *stream );"; z[lc++]=""; z[lc++]="/*"; z[lc++]=" The \"CPU Load\" is a fraction of total CPU time consumed by the"; z[lc++]=" stream's audio processing."; z[lc++]=" A value of 0.5 would imply that PortAudio and the sound generating"; z[lc++]=" callback was consuming roughly 50% of the available CPU time."; z[lc++]=" This function may be called from the callback function or the application."; z[lc++]="*/"; z[lc++]="double Pa_GetCPULoad( PortAudioStream* stream );"; z[lc++]=""; z[lc++]="/*"; z[lc++]=" Use Pa_GetMinNumBuffers() to determine minimum number of buffers required for"; z[lc++]=" the current host based on minimum latency. "; z[lc++]=" On the PC, for the DirectSound implementation, latency can be optionally set"; z[lc++]=" by user by setting an environment variable."; z[lc++]=" For example, to set latency to 200 msec, put:"; z[lc++]=" "; z[lc++]=" set PA_MIN_LATENCY_MSEC=200"; z[lc++]=" "; z[lc++]=" in the AUTOEXEC.BAT file and reboot."; z[lc++]=" If the environment variable is not set, then the latency will be determined"; z[lc++]=" based on the OS. Windows NT has higher latency than Win95."; z[lc++]="*/"; z[lc++]=""; z[lc++]="int Pa_GetMinNumBuffers( int framesPerBuffer, double sampleRate );"; z[lc++]=""; z[lc++]="/*"; z[lc++]=" Sleep for at least 'msec' milliseconds."; z[lc++]=" You may sleep longer than the requested time so don't rely"; z[lc++]=" on this for accurate musical timing."; z[lc++]="*/"; z[lc++]="void Pa_Sleep( long msec );"; z[lc++]=""; z[lc++]="/*"; z[lc++]=" Return size in bytes of a single sample in a given PaSampleFormat"; z[lc++]=" or paSampleFormatNotSupported. "; z[lc++]="*/"; z[lc++]="PaError Pa_GetSampleSize( PaSampleFormat format );"; z[lc++]=""; z[lc++]="#ifdef __cplusplus"; z[lc++]="}"; z[lc++]="#endif /* __cplusplus */"; z[lc++]="#endif /* PORT_AUDIO_H */"; printlib(lc); } void makepa_tracehdr(void) { int lc = 0; z[lc++]="#ifndef PA_TRACE_H"; z[lc++]="#define PA_TRACE_H"; z[lc++]="/*"; z[lc++]=" * Portable Audio I/O Library Trace Facility"; z[lc++]=" * Store trace information in real-time for later printing."; z[lc++]=" *"; z[lc++]=" * Based on the Open Source API proposed by Ross Bencina"; z[lc++]=" * Copyright (c) 1999-2000 Phil Burk"; z[lc++]=" *"; z[lc++]=" * Permission is hereby granted, free of charge, to any person obtaining"; z[lc++]=" * a copy of this software and associated documentation files"; z[lc++]=" * (the \"Software\"), to deal in the Software without restriction,"; z[lc++]=" * including without limitation the rights to use, copy, modify, merge,"; z[lc++]=" * publish, distribute, sublicense, and/or sell copies of the Software,"; z[lc++]=" * and to permit persons to whom the Software is furnished to do so,"; z[lc++]=" * subject to the following conditions:"; z[lc++]=" *"; z[lc++]=" * The above copyright notice and this permission notice shall be"; z[lc++]=" * included in all copies or substantial portions of the Software."; z[lc++]=" *"; z[lc++]=" * Any person wishing to distribute modifications to the Software is"; z[lc++]=" * requested to send the modifications to the original developer so that"; z[lc++]=" * they can be incorporated into the canonical version."; z[lc++]=" *"; z[lc++]=" * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,"; z[lc++]=" * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF"; z[lc++]=" * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT."; z[lc++]=" * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR"; z[lc++]=" * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF"; z[lc++]=" * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION"; z[lc++]=" * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."; z[lc++]=" */"; z[lc++]=""; z[lc++]=""; z[lc++]="#define TRACE_REALTIME_EVENTS (0) /* Keep log of various real-time events. */"; z[lc++]="#define MAX_TRACE_RECORDS (2048)"; z[lc++]=""; z[lc++]="#ifdef __cplusplus"; z[lc++]="extern \"C\" {"; z[lc++]="#endif /* __cplusplus */"; z[lc++]=""; z[lc++]=""; z[lc++]="/************************************************************************************/"; z[lc++]="/****************** Prototypes ******************************************************/"; z[lc++]="/************************************************************************************/"; z[lc++]=""; z[lc++]="#if TRACE_REALTIME_EVENTS"; z[lc++]=""; z[lc++]="void DumpTraceMessages();"; z[lc++]="void ResetTraceMessages();"; z[lc++]="void AddTraceMessage( char *msg, int data );"; z[lc++]=""; z[lc++]="#else"; z[lc++]=""; z[lc++]="#define AddTraceMessage(msg,data) /* noop */"; z[lc++]="#define ResetTraceMessages() /* noop */"; z[lc++]="#define DumpTraceMessages() /* noop */"; z[lc++]=""; z[lc++]="#endif"; z[lc++]=""; z[lc++]="#ifdef __cplusplus"; z[lc++]="}"; z[lc++]="#endif /* __cplusplus */"; z[lc++]=""; z[lc++]="#endif /* PA_TRACE_H */"; printlib(lc); } void makepa_lib(void) { int lc = 0; z[lc++]="/*"; z[lc++]=" * Portable Audio I/O Library"; z[lc++]=" * Host Independant Layer"; z[lc++]=" *"; z[lc++]=" * Based on the Open Source API proposed by Ross Bencina"; z[lc++]=" * Copyright (c) 1999-2000 Phil Burk"; z[lc++]=" *"; z[lc++]=" * Permission is hereby granted, free of charge, to any person obtaining"; z[lc++]=" * a copy of this software and associated documentation files"; z[lc++]=" * (the \"Software\"), to deal in the Software without restriction,"; z[lc++]=" * including without limitation the rights to use, copy, modify, merge,"; z[lc++]=" * publish, distribute, sublicense, and/or sell copies of the Software,"; z[lc++]=" * and to permit persons to whom the Software is furnished to do so,"; z[lc++]=" * subject to the following conditions:"; z[lc++]=" *"; z[lc++]=" * The above copyright notice and this permission notice shall be"; z[lc++]=" * included in all copies or substantial portions of the Software."; z[lc++]=" *"; z[lc++]=" * Any person wishing to distribute modifications to the Software is"; z[lc++]=" * requested to send the modifications to the original developer so that"; z[lc++]=" * they can be incorporated into the canonical version."; z[lc++]=" *"; z[lc++]=" * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,"; z[lc++]=" * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF"; z[lc++]=" * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT."; z[lc++]=" * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR"; z[lc++]=" * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF"; z[lc++]=" * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION"; z[lc++]=" * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."; z[lc++]=" *"; z[lc++]=" */"; z[lc++]=""; z[lc++]="/* Modification History:"; z[lc++]=" PLB20010422 - apply Mike Berry's changes for CodeWarrior on PC"; z[lc++]=" PLB20010820 - fix dither and shift for recording PaUInt8 format "; z[lc++]="*/"; z[lc++]=""; z[lc++]="#include "; z[lc++]="#include "; z[lc++]="#include "; z[lc++]="#include "; z[lc++]=""; z[lc++]="/* PLB20010422 - \"memory.h\" doesn't work on CodeWarrior for PC. Thanks Mike Berry for the mod. */"; z[lc++]="#ifdef _WIN32"; z[lc++]="#ifndef __MWERKS__"; z[lc++]="#include "; z[lc++]="#endif /* __MWERKS__ */"; z[lc++]="#else /* !_WIN32 */"; z[lc++]="#include "; z[lc++]="#endif /* _WIN32 */"; z[lc++]=""; z[lc++]="#if 0"; z[lc++]="#include \"portaudio.h\""; z[lc++]="#include \"pa_host.h\""; z[lc++]="#include \"pa_trace.h\""; z[lc++]="#endif"; z[lc++]=""; z[lc++]="/* The reason we might NOT want to validate the rate before opening the stream"; z[lc++]=" * is because many DirectSound drivers lie about the rates they actually support."; z[lc++]=" */"; z[lc++]="#define PA_VALIDATE_RATE (0) /* If true validate sample rate against driver info. */"; z[lc++]=""; z[lc++]="/*"; z[lc++]="O- maybe not allocate past_InputBuffer and past_OutputBuffer if not needed for conversion"; z[lc++]="*/"; z[lc++]=""; z[lc++]="#ifndef FALSE"; z[lc++]=" #define FALSE (0)"; z[lc++]=" #define TRUE (!FALSE)"; z[lc++]="#endif"; z[lc++]=""; z[lc++]="#define PRINT(x) { printf x; fflush(stdout); }"; z[lc++]="#define ERR_RPT(x) PRINT(x)"; z[lc++]="#define DBUG(x) /* PRINT(x) */"; z[lc++]="#define DBUGX(x) /* PRINT(x) */"; z[lc++]=""; z[lc++]="static int gInitCount = 0; /* Count number of times Pa_Initialize() called to allow nesting and overlapping. */"; z[lc++]=""; z[lc++]="static PaError Pa_KillStream( PortAudioStream *stream, int abort );"; z[lc++]=""; z[lc++]="/***********************************************************************/"; z[lc++]="int PaHost_FindClosestTableEntry( double allowableError, const double *rateTable, int numRates, double frameRate )"; z[lc++]="{"; z[lc++]=" double err, minErr = allowableError;"; z[lc++]=" int i, bestFit = -1;"; z[lc++]=" "; z[lc++]=" for( i=0; ipad_DeviceName ));"; z[lc++]=" testResult = Pa_QueryDevice( pad->pad_DeviceName, pad );"; z[lc++]=" DBUG((\"Pa_QueryDevice returned %d\\n\", testResult ));"; z[lc++]=" if( testResult != paNoError )"; z[lc++]=" {"; z[lc++]=" if( lastPad == NULL )"; z[lc++]=" {"; z[lc++]=" result = testResult; /* No good devices! */"; z[lc++]=" }"; z[lc++]=" go = 0;"; z[lc++]=" PaHost_FreeFastMemory( pad, sizeof(internalPortAudioDevice) );"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" numDevices += 1;"; z[lc++]=" /* Add to linked list of devices. */"; z[lc++]=" if( lastPad )"; z[lc++]=" {"; z[lc++]=" lastPad->pad_Next = pad;"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" sDeviceList = pad; /* First element in linked list. */"; z[lc++]=" }"; z[lc++]=" lastPad = pad;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" "; z[lc++]=" return result;"; z[lc++]=" "; z[lc++]="}"; z[lc++]=""; z[lc++]="/*************************************************************************/"; z[lc++]="int Pa_CountDevices()"; z[lc++]="{"; z[lc++]=" int numDevices = 0;"; z[lc++]=" internalPortAudioDevice *pad;"; z[lc++]=" "; z[lc++]=" if( sDeviceList == NULL ) Pa_Initialize();"; z[lc++]="/* Count devices in list. */"; z[lc++]=" pad = sDeviceList;"; z[lc++]=" while( pad != NULL )"; z[lc++]=" {"; z[lc++]=" pad = pad->pad_Next;"; z[lc++]=" numDevices++;"; z[lc++]=" }"; z[lc++]=" "; z[lc++]=" return numDevices;"; z[lc++]="}"; z[lc++]=""; z[lc++]="static internalPortAudioDevice *Pa_GetInternalDevice( PaDeviceID id )"; z[lc++]="{"; z[lc++]=" internalPortAudioDevice *pad;"; z[lc++]=" if( (id < 0) || ( id >= Pa_CountDevices()) ) return NULL;"; z[lc++]=" pad = sDeviceList;"; z[lc++]=" while( id > 0 )"; z[lc++]=" {"; z[lc++]=" pad = pad->pad_Next;"; z[lc++]=" id--;"; z[lc++]=" }"; z[lc++]=" return pad;"; z[lc++]="}"; z[lc++]=""; z[lc++]="/*************************************************************************/"; z[lc++]="const PaDeviceInfo* Pa_GetDeviceInfo( PaDeviceID id )"; z[lc++]="{"; z[lc++]=" internalPortAudioDevice *pad;"; z[lc++]=" if( (id < 0) || ( id >= Pa_CountDevices()) ) return NULL;"; z[lc++]=" pad = Pa_GetInternalDevice( id );"; z[lc++]=" return &pad->pad_Info ;"; z[lc++]="}"; z[lc++]=""; z[lc++]="static PaError Pa_MaybeQueryDevices( void )"; z[lc++]="{"; z[lc++]=" if( sDeviceList == NULL )"; z[lc++]=" {"; z[lc++]=" return Pa_QueryDevices();"; z[lc++]=" }"; z[lc++]=" return 0;"; z[lc++]="}"; z[lc++]=""; z[lc++]="PaDeviceID Pa_GetDefaultInputDeviceID( void )"; z[lc++]="{"; z[lc++]=" /* return paNoDevice; */"; z[lc++]=" return 0;"; z[lc++]="}"; z[lc++]=""; z[lc++]="PaDeviceID Pa_GetDefaultOutputDeviceID( void )"; z[lc++]="{"; z[lc++]=" return 0;"; z[lc++]="}"; z[lc++]=""; z[lc++]="/**********************************************************************"; z[lc++]="** Make sure that we have queried the device capabilities."; z[lc++]="*/"; z[lc++]=""; z[lc++]="PaError PaHost_Init( void )"; z[lc++]="{"; z[lc++]=" return Pa_MaybeQueryDevices();"; z[lc++]="}"; z[lc++]=""; z[lc++]="/*******************************************************************************************/"; z[lc++]="static PaError Pa_AudioThreadProc( internalPortAudioStream *past )"; z[lc++]="{"; z[lc++]=" PaError result = 0;"; z[lc++]=" PaHostSoundControl *pahsc;"; z[lc++]=" short bytes_read = 0;"; z[lc++]=" "; z[lc++]="#ifdef GNUSTEP"; z[lc++]=" GSRegisterCurrentThread(); /* SB20010904 */"; z[lc++]="#endif"; z[lc++]=" "; z[lc++]=" pahsc = (PaHostSoundControl *) past->past_DeviceData;"; z[lc++]=" if( pahsc == NULL ) return paInternalError;"; z[lc++]=""; z[lc++]=" past->past_IsActive = 1;"; z[lc++]=" DBUG((\"entering thread.\\n\"));"; z[lc++]=" "; z[lc++]=" while( (past->past_StopNow == 0) && (past->past_StopSoon == 0) )"; z[lc++]=" {"; z[lc++]=""; z[lc++]=" DBUG((\"go!\\n\"));"; z[lc++]=" /* Read data from device */"; z[lc++]=" if(pahsc->pahsc_NativeInputBuffer)"; z[lc++]=" {"; z[lc++]=" bytes_read = read(pahsc->pahsc_InputHandle,"; z[lc++]=" (void *)pahsc->pahsc_NativeInputBuffer,"; z[lc++]=" pahsc->pahsc_BytesPerInputBuffer); "; z[lc++]=" "; z[lc++]=" DBUG((\"bytes_read: %d\\n\", bytes_read));"; z[lc++]=" }"; z[lc++]=" "; z[lc++]=" /* Convert 16 bit native data to user data and call user routine. */"; z[lc++]=" DBUG((\"converting...\\n\"));"; z[lc++]=" Pa_StartUsageCalculation( past );"; z[lc++]=" result = Pa_CallConvertInt16( past,"; z[lc++]=" pahsc->pahsc_NativeInputBuffer,"; z[lc++]=" pahsc->pahsc_NativeOutputBuffer );"; z[lc++]=" Pa_EndUsageCalculation( past );"; z[lc++]=" if( result != 0) "; z[lc++]=" {"; z[lc++]=" DBUG((\"hmm, Pa_CallConvertInt16() says: %d. i'm bailing.\\n\","; z[lc++]=" result));"; z[lc++]=" break;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" /* Write data to device. */"; z[lc++]=" if( pahsc->pahsc_NativeOutputBuffer )"; z[lc++]=" {"; z[lc++]=""; z[lc++]=" write(pahsc->pahsc_OutputHandle,"; z[lc++]=" (void *)pahsc->pahsc_NativeOutputBuffer,"; z[lc++]=" pahsc->pahsc_BytesPerOutputBuffer); "; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" past->past_IsActive = 0;"; z[lc++]=" DBUG((\"leaving thread.\\n\"));"; z[lc++]=" "; z[lc++]="#ifdef GNUSTEP"; z[lc++]=" GSUnregisterCurrentThread(); /* SB20010904 */"; z[lc++]="#endif"; z[lc++]=" return 0;"; z[lc++]="}"; z[lc++]=""; z[lc++]="/*******************************************************************************************/"; z[lc++]="static PaError Pa_SetupDeviceFormat( int devHandle, int numChannels, int sampleRate )"; z[lc++]="{"; z[lc++]=" PaError result = paNoError;"; z[lc++]=" int tmp;"; z[lc++]=""; z[lc++]="/* Set format, channels, and rate in this order to keep OSS happy. */"; z[lc++]="/* Set data format. FIXME - handle more native formats. */"; z[lc++]=" tmp = AFMT_S16_NE; "; z[lc++]=" if( ioctl(devHandle,SNDCTL_DSP_SETFMT,&tmp) == -1)"; z[lc++]=" {"; z[lc++]=" ERR_RPT((\"Pa_SetupDeviceFormat: could not SNDCTL_DSP_SETFMT\\n\" ));"; z[lc++]=" return paHostError;"; z[lc++]=" }"; z[lc++]=" if( tmp != AFMT_S16_NE)"; z[lc++]=" {"; z[lc++]=" ERR_RPT((\"Pa_SetupDeviceFormat: HW does not support AFMT_S16_NE\\n\" ));"; z[lc++]=" return paHostError;"; z[lc++]=" }"; z[lc++]=" "; z[lc++]=""; z[lc++]="/* Set number of channels. */"; z[lc++]=" tmp = numChannels;"; z[lc++]=" if (ioctl(devHandle, SNDCTL_DSP_CHANNELS, &numChannels) == -1)"; z[lc++]=" {"; z[lc++]=" ERR_RPT((\"Pa_SetupDeviceFormat: could not SNDCTL_DSP_CHANNELS\\n\" ));"; z[lc++]=" return paHostError;"; z[lc++]=" }"; z[lc++]=" if( tmp != numChannels)"; z[lc++]=" {"; z[lc++]=" ERR_RPT((\"Pa_SetupDeviceFormat: HW does not support %d channels\\n\", numChannels ));"; z[lc++]=" return paHostError;"; z[lc++]=" }"; z[lc++]=" "; z[lc++]="/* Set playing frequency. 44100, 22050 and 11025 are safe bets. */"; z[lc++]=" tmp = sampleRate;"; z[lc++]=" if( ioctl(devHandle,SNDCTL_DSP_SPEED,&tmp) == -1)"; z[lc++]=" {"; z[lc++]=" ERR_RPT((\"Pa_SetupDeviceFormat: could not SNDCTL_DSP_SPEED\\n\" ));"; z[lc++]=" return paHostError;"; z[lc++]=" }"; z[lc++]=" if( tmp != sampleRate)"; z[lc++]=" {"; z[lc++]=" ERR_RPT((\"Pa_SetupDeviceFormat: HW does not support %d Hz sample rate\\n\",sampleRate ));"; z[lc++]=" return paHostError;"; z[lc++]=" }"; z[lc++]=" "; z[lc++]=" return result;"; z[lc++]="} "; z[lc++]=""; z[lc++]="static int CalcHigherLogTwo( int n )"; z[lc++]="{"; z[lc++]=" int log2 = 0;"; z[lc++]=" while( (1<pahsc_MinFramesPerHostBuffer )); */"; z[lc++]=" minNumBuffers = Pa_GetMinNumBuffers( past->past_FramesPerUserBuffer, past->past_SampleRate );"; z[lc++]=" past->past_NumUserBuffers = ( minNumBuffers > past->past_NumUserBuffers ) ? minNumBuffers : past->past_NumUserBuffers;"; z[lc++]=""; z[lc++]=" pahsc->pahsc_InverseMicrosPerBuffer = past->past_SampleRate / (1000000.0 * past->past_FramesPerUserBuffer);"; z[lc++]=" DBUG((\"pahsc_InverseMicrosPerBuffer = %g\\n\", pahsc->pahsc_InverseMicrosPerBuffer ));"; z[lc++]=" "; z[lc++]="/* ------------------------- OPEN DEVICE -----------------------*/"; z[lc++]=" "; z[lc++]=" /* just output */"; z[lc++]=" if (past->past_OutputDeviceID == past->past_InputDeviceID)"; z[lc++]=" {"; z[lc++]=" "; z[lc++]=" if ((past->past_NumOutputChannels > 0) && (past->past_NumInputChannels > 0) )"; z[lc++]=" {"; z[lc++]=" pad = Pa_GetInternalDevice( past->past_OutputDeviceID );"; z[lc++]=" DBUG((\"PaHost_OpenStream: attempt to open %s for O_RDWR\\n\", pad->pad_DeviceName ));"; z[lc++]=" pahsc->pahsc_OutputHandle = pahsc->pahsc_InputHandle ="; z[lc++]=" open(pad->pad_DeviceName,O_RDWR); "; z[lc++]=" if(pahsc->pahsc_InputHandle==-1)"; z[lc++]=" {"; z[lc++]=" ERR_RPT((\"PaHost_OpenStream: could not open %s for O_RDWR\\n\", pad->pad_DeviceName ));"; z[lc++]=" result = paHostError;"; z[lc++]=" goto error;"; z[lc++]=" } "; z[lc++]=" Pa_SetLatency( pahsc->pahsc_OutputHandle,"; z[lc++]=" past->past_NumUserBuffers, past->past_FramesPerUserBuffer,"; z[lc++]=" past->past_NumOutputChannels );"; z[lc++]=" result = Pa_SetupDeviceFormat( pahsc->pahsc_OutputHandle,"; z[lc++]=" past->past_NumOutputChannels, (int)past->past_SampleRate );"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if (past->past_NumOutputChannels > 0)"; z[lc++]=" { "; z[lc++]=" pad = Pa_GetInternalDevice( past->past_OutputDeviceID );"; z[lc++]=" DBUG((\"PaHost_OpenStream: attempt to open %s for O_WRONLY\\n\", pad->pad_DeviceName ));"; z[lc++]=" pahsc->pahsc_OutputHandle = open(pad->pad_DeviceName,O_WRONLY); "; z[lc++]=" if(pahsc->pahsc_OutputHandle==-1)"; z[lc++]=" {"; z[lc++]=" ERR_RPT((\"PaHost_OpenStream: could not open %s for O_WRONLY\\n\", pad->pad_DeviceName ));"; z[lc++]=" result = paHostError;"; z[lc++]=" goto error;"; z[lc++]=" } "; z[lc++]=" Pa_SetLatency( pahsc->pahsc_OutputHandle,"; z[lc++]=" past->past_NumUserBuffers, past->past_FramesPerUserBuffer,"; z[lc++]=" past->past_NumOutputChannels );"; z[lc++]=" result = Pa_SetupDeviceFormat( pahsc->pahsc_OutputHandle,"; z[lc++]=" past->past_NumOutputChannels, (int)past->past_SampleRate );"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" if (past->past_NumInputChannels > 0)"; z[lc++]=" { "; z[lc++]=" pad = Pa_GetInternalDevice( past->past_InputDeviceID );"; z[lc++]=" DBUG((\"PaHost_OpenStream: attempt to open %s for O_RDONLY\\n\", pad->pad_DeviceName ));"; z[lc++]=" pahsc->pahsc_InputHandle = open(pad->pad_DeviceName,O_RDONLY); "; z[lc++]=" if(pahsc->pahsc_InputHandle==-1)"; z[lc++]=" {"; z[lc++]=" ERR_RPT((\"PaHost_OpenStream: could not open %s for O_RDONLY\\n\", pad->pad_DeviceName ));"; z[lc++]=" result = paHostError;"; z[lc++]=" goto error;"; z[lc++]=" } "; z[lc++]=" Pa_SetLatency( pahsc->pahsc_OutputHandle,"; z[lc++]=" past->past_NumUserBuffers, past->past_FramesPerUserBuffer,"; z[lc++]=" past->past_NumInputChannels );"; z[lc++]=" result = Pa_SetupDeviceFormat( pahsc->pahsc_InputHandle,"; z[lc++]=" past->past_NumInputChannels, (int)past->past_SampleRate );"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" "; z[lc++]=" "; z[lc++]=" DBUG((\"PaHost_OpenStream: SUCCESS - result = %d\\n\", result ));"; z[lc++]=" return result;"; z[lc++]=" "; z[lc++]="error:"; z[lc++]=" ERR_RPT((\"PaHost_OpenStream: ERROR - result = %d\\n\", result ));"; z[lc++]=" PaHost_CloseStream( past );"; z[lc++]=" return result;"; z[lc++]="}"; z[lc++]=""; z[lc++]="/*************************************************************************/"; z[lc++]="PaError PaHost_StartOutput( internalPortAudioStream *past )"; z[lc++]="{"; z[lc++]=" return paNoError;"; z[lc++]="}"; z[lc++]=""; z[lc++]="/*************************************************************************/"; z[lc++]="PaError PaHost_StartInput( internalPortAudioStream *past )"; z[lc++]="{"; z[lc++]=" return paNoError;"; z[lc++]="}"; z[lc++]=""; z[lc++]="/*************************************************************************/"; z[lc++]="PaError PaHost_StartEngine( internalPortAudioStream *past )"; z[lc++]="{"; z[lc++]=" PaHostSoundControl *pahsc;"; z[lc++]=" PaError result = paNoError;"; z[lc++]=" int hres;"; z[lc++]=" "; z[lc++]=" pahsc = (PaHostSoundControl *) past->past_DeviceData;"; z[lc++]=""; z[lc++]=" past->past_StopSoon = 0;"; z[lc++]=" past->past_StopNow = 0;"; z[lc++]=" past->past_IsActive = 1; "; z[lc++]=""; z[lc++]="/* Use pthread_create() instead of __clone() because:"; z[lc++]=" * - pthread_create also works for other UNIX systems like Solaris,"; z[lc++]=" * - the Java HotSpot VM crashes in pthread_setcanceltype() when using __clone()"; z[lc++]=" */"; z[lc++]=" hres = pthread_create(&(pahsc->pahsc_ThreadPID),"; z[lc++]=" NULL /*pthread_attr_t * attr*/,"; z[lc++]=" (void*)Pa_AudioThreadProc, past);"; z[lc++]=" if( hres != 0 )"; z[lc++]=" {"; z[lc++]=" result = paHostError;"; z[lc++]=" sPaHostError = hres;"; z[lc++]=" goto error;"; z[lc++]=" }"; z[lc++]=""; z[lc++]="error:"; z[lc++]=" return result;"; z[lc++]="}"; z[lc++]=""; z[lc++]="/*************************************************************************/"; z[lc++]="PaError PaHost_StopEngine( internalPortAudioStream *past, int abort )"; z[lc++]="{"; z[lc++]=" int hres;"; z[lc++]=" long timeOut;"; z[lc++]=" PaError result = paNoError;"; z[lc++]=" PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData;"; z[lc++]=" "; z[lc++]=" if( pahsc == NULL ) return paNoError;"; z[lc++]=" "; z[lc++]="/* Tell background thread to stop generating more data and to let current data play out. */"; z[lc++]=" past->past_StopSoon = 1;"; z[lc++]="/* If aborting, tell background thread to stop NOW! */"; z[lc++]=" if( abort ) past->past_StopNow = 1;"; z[lc++]=""; z[lc++]="/* Join thread to recover memory resources. */"; z[lc++]=" if( pahsc->pahsc_ThreadPID != -1 )"; z[lc++]=" {"; z[lc++]=" /* This check is needed for GNUSTEP - SB20010904 */"; z[lc++]=" if ( !pthread_equal( pahsc->pahsc_ThreadPID, pthread_self() ) )"; z[lc++]=" {"; z[lc++]=" hres = pthread_join( pahsc->pahsc_ThreadPID, NULL );"; z[lc++]=" }"; z[lc++]=" else {"; z[lc++]=" DBUG((\"Play thread was stopped from itself - can't do pthread_join()\\n\"));"; z[lc++]=" hres = 0;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" if( hres != 0 )"; z[lc++]=" {"; z[lc++]=" result = paHostError;"; z[lc++]=" sPaHostError = hres;"; z[lc++]=" }"; z[lc++]=" pahsc->pahsc_ThreadPID = -1;"; z[lc++]=" }"; z[lc++]=" "; z[lc++]=" past->past_IsActive = 0; "; z[lc++]=""; z[lc++]=" return result;"; z[lc++]="}"; z[lc++]=""; z[lc++]="/*************************************************************************/"; z[lc++]="PaError PaHost_StopInput( internalPortAudioStream *past, int abort )"; z[lc++]="{"; z[lc++]=" return paNoError;"; z[lc++]="}"; z[lc++]=""; z[lc++]="/*************************************************************************/"; z[lc++]="PaError PaHost_StopOutput( internalPortAudioStream *past, int abort )"; z[lc++]="{"; z[lc++]=" return paNoError;"; z[lc++]="}"; z[lc++]=""; z[lc++]="/*******************************************************************/"; z[lc++]="PaError PaHost_CloseStream( internalPortAudioStream *past )"; z[lc++]="{"; z[lc++]=" PaHostSoundControl *pahsc;"; z[lc++]=" if( past == NULL ) return paBadStreamPtr;"; z[lc++]=" pahsc = (PaHostSoundControl *) past->past_DeviceData;"; z[lc++]=" if( pahsc == NULL ) return paNoError;"; z[lc++]=""; z[lc++]=" if( pahsc->pahsc_OutputHandle != BAD_DEVICE_ID )"; z[lc++]=" {"; z[lc++]=" int err;"; z[lc++]=" DBUG((\"PaHost_CloseStream: attempt to close output device handle = %d\\n\","; z[lc++]=" pahsc->pahsc_OutputHandle ));"; z[lc++]=" err = close(pahsc->pahsc_OutputHandle);"; z[lc++]=" if( err < 0 )"; z[lc++]=" {"; z[lc++]=" ERR_RPT((\"PaHost_CloseStream: warning, closing output device failed.\\n\"));"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" "; z[lc++]=" if( (pahsc->pahsc_InputHandle != BAD_DEVICE_ID) &&"; z[lc++]=" (pahsc->pahsc_InputHandle != pahsc->pahsc_OutputHandle) )"; z[lc++]=" {"; z[lc++]=" int err;"; z[lc++]=" DBUG((\"PaHost_CloseStream: attempt to close input device handle = %d\\n\","; z[lc++]=" pahsc->pahsc_InputHandle ));"; z[lc++]=" err = close(pahsc->pahsc_InputHandle);"; z[lc++]=" if( err < 0 )"; z[lc++]=" {"; z[lc++]=" ERR_RPT((\"PaHost_CloseStream: warning, closing input device failed.\\n\"));"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" pahsc->pahsc_OutputHandle = BAD_DEVICE_ID;"; z[lc++]=" pahsc->pahsc_InputHandle = BAD_DEVICE_ID;"; z[lc++]=" "; z[lc++]=" if( pahsc->pahsc_NativeInputBuffer )"; z[lc++]=" {"; z[lc++]=" free( pahsc->pahsc_NativeInputBuffer );"; z[lc++]=" pahsc->pahsc_NativeInputBuffer = NULL;"; z[lc++]=" }"; z[lc++]=" if( pahsc->pahsc_NativeOutputBuffer )"; z[lc++]=" {"; z[lc++]=" free( pahsc->pahsc_NativeOutputBuffer );"; z[lc++]=" pahsc->pahsc_NativeOutputBuffer = NULL;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" free( pahsc );"; z[lc++]=" past->past_DeviceData = NULL;"; z[lc++]=" return paNoError;"; z[lc++]="}"; z[lc++]=""; z[lc++]="/*************************************************************************/"; z[lc++]="PaError PaHost_Term( void )"; z[lc++]="{"; z[lc++]="/* Free all of the linked devices. */"; z[lc++]=" internalPortAudioDevice *pad, *nextPad;"; z[lc++]=" pad = sDeviceList;"; z[lc++]=" while( pad != NULL )"; z[lc++]=" {"; z[lc++]=" nextPad = pad->pad_Next;"; z[lc++]=" DBUG((\"PaHost_Term: freeing %s\\n\", pad->pad_DeviceName ));"; z[lc++]=" PaHost_FreeFastMemory( pad, sizeof(internalPortAudioDevice) );"; z[lc++]=" pad = nextPad;"; z[lc++]=" }"; z[lc++]=" sDeviceList = NULL;"; z[lc++]=" return 0;"; z[lc++]="}"; z[lc++]=""; z[lc++]="/*************************************************************************"; z[lc++]=" * Sleep for the requested number of milliseconds."; z[lc++]=" */"; z[lc++]="void Pa_Sleep( long msec )"; z[lc++]="{"; z[lc++]="#if 0"; z[lc++]=" struct timeval timeout;"; z[lc++]=" timeout.tv_sec = msec / 1000;"; z[lc++]=" timeout.tv_usec = (msec % 1000) * 1000;"; z[lc++]=" select( 0, NULL, NULL, NULL, &timeout );"; z[lc++]="#else"; z[lc++]=" long usecs = msec * 1000;"; z[lc++]=" usleep( usecs );"; z[lc++]="#endif"; z[lc++]="}"; z[lc++]=""; z[lc++]="/*************************************************************************"; z[lc++]=" * Allocate memory that can be accessed in real-time."; z[lc++]=" * This may need to be held in physical memory so that it is not"; z[lc++]=" * paged to virtual memory."; z[lc++]=" * This call MUST be balanced with a call to PaHost_FreeFastMemory()."; z[lc++]=" */"; z[lc++]="void *PaHost_AllocateFastMemory( long numBytes )"; z[lc++]="{"; z[lc++]=" void *addr = malloc( numBytes ); /* FIXME - do we need physical memory? */"; z[lc++]=" if( addr != NULL ) memset( addr, 0, numBytes );"; z[lc++]=" return addr;"; z[lc++]="}"; z[lc++]=""; z[lc++]="/*************************************************************************"; z[lc++]=" * Free memory that could be accessed in real-time."; z[lc++]=" * This call MUST be balanced with a call to PaHost_AllocateFastMemory()."; z[lc++]=" */"; z[lc++]="void PaHost_FreeFastMemory( void *addr, long numBytes )"; z[lc++]="{"; z[lc++]=" if( addr != NULL ) free( addr );"; z[lc++]="}"; z[lc++]=""; z[lc++]=""; z[lc++]="/***********************************************************************/"; z[lc++]="PaError PaHost_StreamActive( internalPortAudioStream *past )"; z[lc++]="{"; z[lc++]=" PaHostSoundControl *pahsc;"; z[lc++]=" if( past == NULL ) return paBadStreamPtr;"; z[lc++]=" pahsc = (PaHostSoundControl *) past->past_DeviceData;"; z[lc++]=" if( pahsc == NULL ) return paInternalError;"; z[lc++]=" return (PaError) (past->past_IsActive != 0);"; z[lc++]="}"; z[lc++]=""; z[lc++]="/***********************************************************************/"; z[lc++]="PaTimestamp Pa_StreamTime( PortAudioStream *stream )"; z[lc++]="{"; z[lc++]=" internalPortAudioStream *past = (internalPortAudioStream *) stream; "; z[lc++]="/* FIXME - return actual frames played, not frames generated."; z[lc++]="** Need to query the output device somehow."; z[lc++]="*/"; z[lc++]=" if( past == NULL ) return paBadStreamPtr;"; z[lc++]=" return past->past_FrameCount;"; z[lc++]="}"; z[lc++]=""; z[lc++]="/***********************************************************************/"; z[lc++]="long Pa_GetHostError( void )"; z[lc++]="{"; z[lc++]=" return (long) sPaHostError;"; z[lc++]="}"; printlib(lc); } void makepa_win_wmme(void) { int lc = 0; z[lc++]="/*"; z[lc++]=" * pa_win_wmme.c"; z[lc++]=" * Implementation of PortAudio for Windows MultiMedia Extensions (WMME)"; z[lc++]=" *"; z[lc++]=" * PortAudio Portable Real-Time Audio Library"; z[lc++]=" * Latest Version at: http://www.portaudio.com"; z[lc++]=" *"; z[lc++]=" * Authors: Ross Bencina and Phil Burk"; z[lc++]=" * Copyright (c) 1999-2000 Ross Bencina and Phil Burk"; z[lc++]=" *"; z[lc++]=" * Permission is hereby granted, free of charge, to any person obtainingF"; z[lc++]=" * a copy of this software and associated documentation files"; z[lc++]=" * (the \"Software\"), to deal in the Software without restriction,"; z[lc++]=" * including without limitation the rights to use, copy, modify, merge,"; z[lc++]=" * publish, distribute, sublicense, and/or sell copies of the Software,"; z[lc++]=" * and to permit persons to whom the Software is furnished to do so,"; z[lc++]=" * subject to the following conditions:"; z[lc++]=" *"; z[lc++]=" * The above copyright notice and this permission notice shall be"; z[lc++]=" * included in all copies or substantial portions of the Software."; z[lc++]=" *"; z[lc++]=" * Any person wishing to distribute modifications to the Software is"; z[lc++]=" * requested to send the modifications to the original developer so that"; z[lc++]=" * they can be incorporated into the canonical version."; z[lc++]=" *"; z[lc++]=" * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,"; z[lc++]=" * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF"; z[lc++]=" * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT."; z[lc++]=" * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR"; z[lc++]=" * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF"; z[lc++]=" * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION"; z[lc++]=" * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."; z[lc++]=" *"; z[lc++]=" */"; z[lc++]="/*"; z[lc++]=" All memory allocations and frees are marked with MEM for quick review."; z[lc++]="*/"; z[lc++]="/* Modification History:"; z[lc++]=" PLB = Phil Burk"; z[lc++]=" PLB20010402 - sDevicePtrs now allocates based on sizeof(pointer)"; z[lc++]=" PLB20010413 - check for excessive numbers of channels"; z[lc++]=" PLB20010422 - apply Mike Berry's changes for CodeWarrior on PC"; z[lc++]=" including condition including of memory.h,"; z[lc++]=" and explicit typecasting on memory allocation"; z[lc++]=" PLB20010802 - use GlobalAlloc for sDevicesPtr instead of PaHost_AllocFastMemory"; z[lc++]=" PLB20010816 - pass process instead of thread to SetPriorityClass()"; z[lc++]=" PLB20010927 - use number of frames instead of real-time for CPULoad calculation."; z[lc++]="*/"; z[lc++]="#include "; z[lc++]="#include "; z[lc++]="#include "; z[lc++]="#include "; z[lc++]="#include "; z[lc++]="#include "; z[lc++]="/* PLB20010422 - \"memory.h\" doesn't work on CodeWarrior for PC. Thanks Mike Berry for the mod. */"; z[lc++]="#ifndef __MWERKS__"; z[lc++]="#include "; z[lc++]="#include "; z[lc++]="#endif /* __MWERKS__ */"; z[lc++]=""; z[lc++]="#if 0"; z[lc++]="#include \"portaudio.h\""; z[lc++]="#include \"pa_host.h\""; z[lc++]="#include \"pa_trace.h\""; z[lc++]="#endif"; z[lc++]=""; z[lc++]="/************************************************* Constants ********/"; z[lc++]="#define PA_USE_TIMER_CALLBACK (0) /* Select between two options for background task. 0=thread, 1=timer */"; z[lc++]="#define PA_USE_HIGH_LATENCY (0) /* For debugging glitches. */"; z[lc++]="/* Switches for debugging. */"; z[lc++]="#define PA_SIMULATE_UNDERFLOW (0) /* Set to one to force an underflow of the output buffer. */"; z[lc++]="/* To trace program, enable TRACE_REALTIME_EVENTS in pa_trace.h */"; z[lc++]="#define PA_TRACE_RUN (0)"; z[lc++]="#define PA_TRACE_START_STOP (1)"; z[lc++]="#if PA_USE_HIGH_LATENCY"; z[lc++]=" #define PA_MIN_MSEC_PER_HOST_BUFFER (100)"; z[lc++]=" #define PA_MAX_MSEC_PER_HOST_BUFFER (300) /* Do not exceed unless user buffer exceeds */"; z[lc++]=" #define PA_MIN_NUM_HOST_BUFFERS (4)"; z[lc++]=" #define PA_MAX_NUM_HOST_BUFFERS (16) /* OK to exceed if necessary */"; z[lc++]=" #define PA_WIN_9X_LATENCY (400)"; z[lc++]="#else"; z[lc++]=" #define PA_MIN_MSEC_PER_HOST_BUFFER (10)"; z[lc++]=" #define PA_MAX_MSEC_PER_HOST_BUFFER (100) /* Do not exceed unless user buffer exceeds */"; z[lc++]=" #define PA_MIN_NUM_HOST_BUFFERS (3)"; z[lc++]=" #define PA_MAX_NUM_HOST_BUFFERS (16) /* OK to exceed if necessary */"; z[lc++]=" #define PA_WIN_9X_LATENCY (200)"; z[lc++]="#endif"; z[lc++]="#define MIN_TIMEOUT_MSEC (1000)"; z[lc++]="/*"; z[lc++]="** Use higher latency for NT because it is even worse at real-time"; z[lc++]="** operation than Win9x."; z[lc++]="*/"; z[lc++]="#define PA_WIN_NT_LATENCY (PA_WIN_9X_LATENCY * 2)"; z[lc++]="#if PA_SIMULATE_UNDERFLOW"; z[lc++]="static gUnderCallbackCounter = 0;"; z[lc++]="#define UNDER_SLEEP_AT (40)"; z[lc++]="#define UNDER_SLEEP_FOR (500)"; z[lc++]="#endif"; z[lc++]="#define PRINT(x) { printf x; fflush(stdout); }"; z[lc++]="#define ERR_RPT(x) PRINT(x)"; z[lc++]="#define DBUG(x) /* PRINT(x) */"; z[lc++]="#define DBUGX(x) /* PRINT(x) */"; z[lc++]="/************************************************* Definitions ********/"; z[lc++]="/**************************************************************"; z[lc++]=" * Structure for internal host specific stream data."; z[lc++]=" * This is allocated on a per stream basis."; z[lc++]=" */"; z[lc++]="typedef struct PaHostSoundControl"; z[lc++]="{"; z[lc++]="/* Input -------------- */"; z[lc++]=" HWAVEIN pahsc_HWaveIn;"; z[lc++]=" WAVEHDR *pahsc_InputBuffers;"; z[lc++]=" int pahsc_CurrentInputBuffer;"; z[lc++]=" int pahsc_BytesPerHostInputBuffer;"; z[lc++]=" int pahsc_BytesPerUserInputBuffer; /* native buffer size in bytes */"; z[lc++]="/* Output -------------- */ "; z[lc++]=" HWAVEOUT pahsc_HWaveOut;"; z[lc++]=" WAVEHDR *pahsc_OutputBuffers;"; z[lc++]=" int pahsc_CurrentOutputBuffer;"; z[lc++]=" int pahsc_BytesPerHostOutputBuffer;"; z[lc++]=" int pahsc_BytesPerUserOutputBuffer; /* native buffer size in bytes */"; z[lc++]="/* Run Time -------------- */ "; z[lc++]=" PaTimestamp pahsc_FramesPlayed;"; z[lc++]=" long pahsc_LastPosition; /* used to track frames played. */"; z[lc++]="/* For measuring CPU utilization. */"; z[lc++]=" LARGE_INTEGER pahsc_EntryCount;"; z[lc++]=" double pahsc_InverseTicksPerHostBuffer;"; z[lc++]="/* Init Time -------------- */ "; z[lc++]=" int pahsc_NumHostBuffers;"; z[lc++]=" int pahsc_FramesPerHostBuffer;"; z[lc++]=" int pahsc_UserBuffersPerHostBuffer;"; z[lc++]=" CRITICAL_SECTION pahsc_StreamLock; /* Mutext to prevent threads from colliding. */"; z[lc++]=" INT pahsc_StreamLockInited;"; z[lc++]="#if PA_USE_TIMER_CALLBACK"; z[lc++]=" BOOL pahsc_IfInsideCallback; /* Test for reentrancy. */"; z[lc++]=" MMRESULT pahsc_TimerID;"; z[lc++]="#else"; z[lc++]=" HANDLE pahsc_AbortEvent;"; z[lc++]=" int pahsc_AbortEventInited;"; z[lc++]=" HANDLE pahsc_BufferEvent;"; z[lc++]=" int pahsc_BufferEventInited;"; z[lc++]=" HANDLE pahsc_EngineThread;"; z[lc++]=" DWORD pahsc_EngineThreadID;"; z[lc++]="#endif"; z[lc++]="} PaHostSoundControl;"; z[lc++]="/************************************************* Shared Data ********/"; z[lc++]="/* FIXME - put Mutex around this shared data. */"; z[lc++]="static int sNumInputDevices = 0;"; z[lc++]="static int sNumOutputDevices = 0;"; z[lc++]="static int sNumDevices = 0;"; z[lc++]="static PaDeviceInfo **sDevicePtrs = NULL;"; z[lc++]="static int sDefaultInputDeviceID = paNoDevice;"; z[lc++]="static int sDefaultOutputDeviceID = paNoDevice;"; z[lc++]="static int sPaHostError = 0;"; z[lc++]="static const char sMapperSuffixInput[] = \" - Input\";"; z[lc++]="static const char sMapperSuffixOutput[] = \" - Output\";"; z[lc++]="/************************************************* Macros ********/"; z[lc++]="/* Convert external PA ID to an internal ID that includes WAVE_MAPPER */"; z[lc++]="#define PaDeviceIdToWinId(id) (((id) < sNumInputDevices) ? (id - 1) : (id - sNumInputDevices - 1))"; z[lc++]="/************************************************* Prototypes **********/"; z[lc++]="static Pa_QueryDevices( void );"; z[lc++]="static void CALLBACK Pa_TimerCallback(UINT uID, UINT uMsg,"; z[lc++]=" DWORD dwUser, DWORD dw1, DWORD dw2);"; z[lc++]="PaError PaHost_GetTotalBufferFrames( internalPortAudioStream *past );"; z[lc++]="static PaError PaHost_UpdateStreamTime( PaHostSoundControl *pahsc );"; z[lc++]="static PaError PaHost_BackgroundManager( internalPortAudioStream *past );"; z[lc++]="/********************************* BEGIN CPU UTILIZATION MEASUREMENT ****/"; z[lc++]="static void Pa_StartUsageCalculation( internalPortAudioStream *past )"; z[lc++]="{"; z[lc++]=" PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData;"; z[lc++]=" if( pahsc == NULL ) return;"; z[lc++]="/* Query system timer for usage analysis and to prevent overuse of CPU. */"; z[lc++]=" QueryPerformanceCounter( &pahsc->pahsc_EntryCount );"; z[lc++]="}"; z[lc++]="static void Pa_EndUsageCalculation( internalPortAudioStream *past )"; z[lc++]="{"; z[lc++]=" LARGE_INTEGER CurrentCount = { 0, 0 };"; z[lc++]=" PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData;"; z[lc++]=" if( pahsc == NULL ) return;"; z[lc++]="/*"; z[lc++]="** Measure CPU utilization during this callback. Note that this calculation"; z[lc++]="** assumes that we had the processor the whole time."; z[lc++]="*/"; z[lc++]="#define LOWPASS_COEFFICIENT_0 (0.9)"; z[lc++]="#define LOWPASS_COEFFICIENT_1 (0.99999 - LOWPASS_COEFFICIENT_0)"; z[lc++]=" if( QueryPerformanceCounter( &CurrentCount ) )"; z[lc++]=" {"; z[lc++]=" LONGLONG InsideCount = CurrentCount.QuadPart - pahsc->pahsc_EntryCount.QuadPart; "; z[lc++]=" double newUsage = InsideCount * pahsc->pahsc_InverseTicksPerHostBuffer;"; z[lc++]=" past->past_Usage = (LOWPASS_COEFFICIENT_0 * past->past_Usage) +"; z[lc++]=" (LOWPASS_COEFFICIENT_1 * newUsage);"; z[lc++]=" }"; z[lc++]="}"; z[lc++]="/****************************************** END CPU UTILIZATION *******/"; z[lc++]="static PaError Pa_QueryDevices( void )"; z[lc++]="{"; z[lc++]=" int numBytes;"; z[lc++]="/* Count the devices and add one extra for the WAVE_MAPPER */"; z[lc++]=" sNumInputDevices = waveInGetNumDevs() + 1;"; z[lc++]=" sDefaultInputDeviceID = 0;"; z[lc++]=" sNumOutputDevices = waveOutGetNumDevs() + 1;"; z[lc++]=" sDefaultOutputDeviceID = sNumInputDevices;"; z[lc++]=" sNumDevices = sNumInputDevices + sNumOutputDevices;"; z[lc++]="/* Allocate structures to hold device info. */"; z[lc++]="/* PLB20010402 - was allocating too much memory. */"; z[lc++]="/* numBytes = sNumDevices * sizeof(PaDeviceInfo); // PLB20010402 */"; z[lc++]=" numBytes = sNumDevices * sizeof(PaDeviceInfo *); /* PLB20010402 */"; z[lc++]=" sDevicePtrs = (PaDeviceInfo **) GlobalAlloc( GPTR, numBytes ); /* MEM */"; z[lc++]=" if( sDevicePtrs == NULL ) return paInsufficientMemory;"; z[lc++]=" return paNoError;"; z[lc++]="}"; z[lc++]="/************************************************************************************/"; z[lc++]="long Pa_GetHostError()"; z[lc++]="{"; z[lc++]=" return sPaHostError;"; z[lc++]="}"; z[lc++]="/*************************************************************************/"; z[lc++]="int Pa_CountDevices()"; z[lc++]="{"; z[lc++]=" if( sNumDevices <= 0 ) Pa_Initialize();"; z[lc++]=" return sNumDevices;"; z[lc++]="}"; z[lc++]="/*************************************************************************"; z[lc++]="** If a PaDeviceInfo structure has not already been created,"; z[lc++]="** then allocate one and fill it in for the selected device."; z[lc++]="**"; z[lc++]="** We create one extra input and one extra output device for the WAVE_MAPPER."; z[lc++]="** [Does anyone know how to query the default device and get its name?]"; z[lc++]="*/"; z[lc++]="const PaDeviceInfo* Pa_GetDeviceInfo( PaDeviceID id )"; z[lc++]="{ "; z[lc++]="#define NUM_STANDARDSAMPLINGRATES 3 /* 11.025, 22.05, 44.1 */"; z[lc++]="#define NUM_CUSTOMSAMPLINGRATES 5 /* must be the same number of elements as in the array below */"; z[lc++]="#define MAX_NUMSAMPLINGRATES (NUM_STANDARDSAMPLINGRATES+NUM_CUSTOMSAMPLINGRATES)"; z[lc++]=" static DWORD customSamplingRates[] = { 32000, 48000, 64000, 88200, 96000 };"; z[lc++]=" PaDeviceInfo *deviceInfo;"; z[lc++]=" double *sampleRates; /* non-const ptr */"; z[lc++]=" int i;"; z[lc++]=" char *s;"; z[lc++]=" "; z[lc++]=" if( id < 0 || id >= sNumDevices )"; z[lc++]=" return NULL;"; z[lc++]=" if( sDevicePtrs[ id ] != NULL )"; z[lc++]=" {"; z[lc++]=" return sDevicePtrs[ id ];"; z[lc++]=" }"; z[lc++]=" deviceInfo = (PaDeviceInfo *)GlobalAlloc( GPTR, sizeof(PaDeviceInfo) ); /* MEM */"; z[lc++]=" if( deviceInfo == NULL ) return NULL;"; z[lc++]=" deviceInfo->structVersion = 1;"; z[lc++]=" deviceInfo->maxInputChannels = 0;"; z[lc++]=" deviceInfo->maxOutputChannels = 0;"; z[lc++]=" deviceInfo->numSampleRates = 0;"; z[lc++]=" sampleRates = (double*)GlobalAlloc( GPTR, MAX_NUMSAMPLINGRATES * sizeof(double) ); /* MEM */"; z[lc++]=" deviceInfo->sampleRates = sampleRates;"; z[lc++]=" deviceInfo->nativeSampleFormats = paInt16; /* should query for higher bit depths below */"; z[lc++]=" if( id < sNumInputDevices )"; z[lc++]=" {"; z[lc++]=" /* input device */"; z[lc++]=" int inputMmID = id - 1; /* WAVE_MAPPER is -1 so we start with WAVE_MAPPER */"; z[lc++]=" WAVEINCAPS wic;"; z[lc++]=" if( waveInGetDevCaps( inputMmID, &wic, sizeof( WAVEINCAPS ) ) != MMSYSERR_NOERROR )"; z[lc++]=" goto error;"; z[lc++]=" "; z[lc++]=" /* Append I/O suffix to WAVE_MAPPER device. */"; z[lc++]=" if( inputMmID == WAVE_MAPPER )"; z[lc++]=" {"; z[lc++]=" s = (char *) GlobalAlloc( GMEM_FIXED, strlen( wic.szPname ) + 1 + sizeof(sMapperSuffixInput) ); /* MEM */"; z[lc++]=" strcpy( s, wic.szPname );"; z[lc++]=" strcat( s, sMapperSuffixInput );"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" s = (char *) GlobalAlloc( GMEM_FIXED, strlen( wic.szPname ) + 1 ); /* MEM */"; z[lc++]=" strcpy( s, wic.szPname );"; z[lc++]=" }"; z[lc++]=" deviceInfo->name = s;"; z[lc++]=" deviceInfo->maxInputChannels = wic.wChannels;"; z[lc++]=" /* Sometimes a device can return a rediculously large number of channels."; z[lc++]=" ** This happened with an SBLive card on a Windows ME box."; z[lc++]=" ** If that happens, then force it to 2 channels. PLB20010413"; z[lc++]=" */"; z[lc++]=" if( (deviceInfo->maxInputChannels < 1) || (deviceInfo->maxInputChannels > 256) )"; z[lc++]=" {"; z[lc++]=" ERR_RPT((\"Pa_GetDeviceInfo: Num input channels reported as %d! Changed to 2.\\n\", deviceInfo->maxOutputChannels ));"; z[lc++]=" deviceInfo->maxInputChannels = 2;"; z[lc++]=" }"; z[lc++]=" /* Add a sample rate to the list if we can do stereo 16 bit at that rate"; z[lc++]=" * based on the format flags. */"; z[lc++]=" if( wic.dwFormats & WAVE_FORMAT_1M16 ||wic.dwFormats & WAVE_FORMAT_1S16 )"; z[lc++]=" sampleRates[ deviceInfo->numSampleRates++ ] = 11025.;"; z[lc++]=" if( wic.dwFormats & WAVE_FORMAT_2M16 ||wic.dwFormats & WAVE_FORMAT_2S16 )"; z[lc++]=" sampleRates[ deviceInfo->numSampleRates++ ] = 22050.;"; z[lc++]=" if( wic.dwFormats & WAVE_FORMAT_4M16 ||wic.dwFormats & WAVE_FORMAT_4S16 )"; z[lc++]=" sampleRates[ deviceInfo->numSampleRates++ ] = 44100.;"; z[lc++]=" /* Add a sample rate to the list if we can do stereo 16 bit at that rate"; z[lc++]=" * based on opening the device successfully. */"; z[lc++]=" for( i=0; i < NUM_CUSTOMSAMPLINGRATES; i++ ){"; z[lc++]=" WAVEFORMATEX wfx;"; z[lc++]=" wfx.wFormatTag = WAVE_FORMAT_PCM;"; z[lc++]=" wfx.nSamplesPerSec = customSamplingRates[i];"; z[lc++]=" wfx.wBitsPerSample = 16;"; z[lc++]=" wfx.cbSize = 0; /* ignored */"; z[lc++]=" wfx.nChannels = (WORD)deviceInfo->maxInputChannels;"; z[lc++]=" wfx.nAvgBytesPerSec = wfx.nChannels * wfx.nSamplesPerSec * sizeof(short);"; z[lc++]=" wfx.nBlockAlign = (WORD)(wfx.nChannels * sizeof(short));"; z[lc++]=" if( waveInOpen( NULL, inputMmID, &wfx, 0, 0, WAVE_FORMAT_QUERY ) == MMSYSERR_NOERROR )"; z[lc++]=" {"; z[lc++]=" sampleRates[ deviceInfo->numSampleRates++ ] = customSamplingRates[i];"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" "; z[lc++]=" }"; z[lc++]=" else if( id - sNumInputDevices < sNumOutputDevices )"; z[lc++]=" {"; z[lc++]=" /* output device */"; z[lc++]=" int outputMmID = id - sNumInputDevices - 1;"; z[lc++]=" WAVEOUTCAPS woc;"; z[lc++]=" if( waveOutGetDevCaps( outputMmID, &woc, sizeof( WAVEOUTCAPS ) ) != MMSYSERR_NOERROR )"; z[lc++]=" goto error;"; z[lc++]=" /* Append I/O suffix to WAVE_MAPPER device. */"; z[lc++]=" if( outputMmID == WAVE_MAPPER )"; z[lc++]=" {"; z[lc++]=" s = (char *) GlobalAlloc( GMEM_FIXED, strlen( woc.szPname ) + 1 + sizeof(sMapperSuffixOutput) ); /* MEM */"; z[lc++]=" strcpy( s, woc.szPname );"; z[lc++]=" strcat( s, sMapperSuffixOutput );"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" s = (char *) GlobalAlloc( GMEM_FIXED, strlen( woc.szPname ) + 1 ); /* MEM */"; z[lc++]=" strcpy( s, woc.szPname );"; z[lc++]=" }"; z[lc++]=" deviceInfo->name = s;"; z[lc++]=" deviceInfo->maxOutputChannels = woc.wChannels;"; z[lc++]=" /* Sometimes a device can return a rediculously large number of channels."; z[lc++]=" ** This happened with an SBLive card on a Windows ME box."; z[lc++]=" ** If that happens, then force it to 2 channels. PLB20010413"; z[lc++]=" */"; z[lc++]=" if( (deviceInfo->maxOutputChannels < 1) || (deviceInfo->maxOutputChannels > 256) )"; z[lc++]=" {"; z[lc++]=" ERR_RPT((\"Pa_GetDeviceInfo: Num output channels reported as %d! Changed to 2.\\n\", deviceInfo->maxOutputChannels ));"; z[lc++]=" deviceInfo->maxOutputChannels = 2;"; z[lc++]=" }"; z[lc++]=" /* Add a sample rate to the list if we can do stereo 16 bit at that rate"; z[lc++]=" * based on the format flags. */"; z[lc++]=" if( woc.dwFormats & WAVE_FORMAT_1M16 ||woc.dwFormats & WAVE_FORMAT_1S16 )"; z[lc++]=" sampleRates[ deviceInfo->numSampleRates++ ] = 11025.;"; z[lc++]=" if( woc.dwFormats & WAVE_FORMAT_2M16 ||woc.dwFormats & WAVE_FORMAT_2S16 )"; z[lc++]=" sampleRates[ deviceInfo->numSampleRates++ ] = 22050.;"; z[lc++]=" if( woc.dwFormats & WAVE_FORMAT_4M16 ||woc.dwFormats & WAVE_FORMAT_4S16 )"; z[lc++]=" sampleRates[ deviceInfo->numSampleRates++ ] = 44100.;"; z[lc++]=" /* Add a sample rate to the list if we can do stereo 16 bit at that rate"; z[lc++]=" * based on opening the device successfully. */"; z[lc++]=" for( i=0; i < NUM_CUSTOMSAMPLINGRATES; i++ )"; z[lc++]=" {"; z[lc++]=" WAVEFORMATEX wfx;"; z[lc++]=" wfx.wFormatTag = WAVE_FORMAT_PCM;"; z[lc++]=" wfx.nSamplesPerSec = customSamplingRates[i];"; z[lc++]=" wfx.wBitsPerSample = 16;"; z[lc++]=" wfx.cbSize = 0; /* ignored */"; z[lc++]=" wfx.nChannels = (WORD)deviceInfo->maxOutputChannels;"; z[lc++]=" wfx.nAvgBytesPerSec = wfx.nChannels * wfx.nSamplesPerSec * sizeof(short);"; z[lc++]=" wfx.nBlockAlign = (WORD)(wfx.nChannels * sizeof(short));"; z[lc++]=" if( waveOutOpen( NULL, outputMmID, &wfx, 0, 0, WAVE_FORMAT_QUERY ) == MMSYSERR_NOERROR ){"; z[lc++]=" sampleRates[ deviceInfo->numSampleRates++ ] = customSamplingRates[i];"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" sDevicePtrs[ id ] = deviceInfo;"; z[lc++]=" return deviceInfo;"; z[lc++]="error:"; z[lc++]=" GlobalFree( sampleRates ); /* MEM */"; z[lc++]=" GlobalFree( deviceInfo ); /* MEM */"; z[lc++]=" "; z[lc++]=" return NULL;"; z[lc++]="}"; z[lc++]="/*************************************************************************"; z[lc++]="** Returns recommended device ID."; z[lc++]="** On the PC, the recommended device can be specified by the user by"; z[lc++]="** setting an environment variable. For example, to use device #1."; z[lc++]="**"; z[lc++]="** set PA_RECOMMENDED_OUTPUT_DEVICE=1"; z[lc++]="**"; z[lc++]="** The user should first determine the available device ID by using"; z[lc++]="** the supplied application \"pa_devs\"."; z[lc++]="*/"; z[lc++]="#define PA_ENV_BUF_SIZE (32)"; z[lc++]="#define PA_REC_IN_DEV_ENV_NAME (\"PA_RECOMMENDED_INPUT_DEVICE\")"; z[lc++]="#define PA_REC_OUT_DEV_ENV_NAME (\"PA_RECOMMENDED_OUTPUT_DEVICE\")"; z[lc++]="static PaDeviceID PaHost_GetEnvDefaultDeviceID( char *envName )"; z[lc++]="{"; z[lc++]=" DWORD hresult;"; z[lc++]=" char envbuf[PA_ENV_BUF_SIZE];"; z[lc++]=" PaDeviceID recommendedID = paNoDevice;"; z[lc++]="/* Let user determine default device by setting environment variable. */"; z[lc++]=" hresult = GetEnvironmentVariable( envName, envbuf, PA_ENV_BUF_SIZE );"; z[lc++]=" if( (hresult > 0) && (hresult < PA_ENV_BUF_SIZE) )"; z[lc++]=" {"; z[lc++]=" recommendedID = atoi( envbuf );"; z[lc++]=" }"; z[lc++]=" return recommendedID;"; z[lc++]="}"; z[lc++]="static PaError Pa_MaybeQueryDevices( void )"; z[lc++]="{"; z[lc++]=" if( sNumDevices == 0 )"; z[lc++]=" {"; z[lc++]=" return Pa_QueryDevices();"; z[lc++]=" }"; z[lc++]=" return 0;"; z[lc++]="}"; z[lc++]="/**********************************************************************"; z[lc++]="** Check for environment variable, else query devices and use result."; z[lc++]="*/"; z[lc++]="PaDeviceID Pa_GetDefaultInputDeviceID( void )"; z[lc++]="{"; z[lc++]=" PaError result;"; z[lc++]=" result = PaHost_GetEnvDefaultDeviceID( PA_REC_IN_DEV_ENV_NAME );"; z[lc++]=" if( result < 0 )"; z[lc++]=" {"; z[lc++]=" result = Pa_MaybeQueryDevices();"; z[lc++]=" if( result < 0 ) return result;"; z[lc++]=" result = sDefaultInputDeviceID;"; z[lc++]=" }"; z[lc++]=" return result;"; z[lc++]="}"; z[lc++]="PaDeviceID Pa_GetDefaultOutputDeviceID( void )"; z[lc++]="{"; z[lc++]=" PaError result;"; z[lc++]=" result = PaHost_GetEnvDefaultDeviceID( PA_REC_OUT_DEV_ENV_NAME );"; z[lc++]=" if( result < 0 )"; z[lc++]=" {"; z[lc++]=" result = Pa_MaybeQueryDevices();"; z[lc++]=" if( result < 0 ) return result;"; z[lc++]=" result = sDefaultOutputDeviceID;"; z[lc++]=" }"; z[lc++]=" return result;"; z[lc++]="}"; z[lc++]="/**********************************************************************"; z[lc++]="** Initialize Host dependant part of API."; z[lc++]="*/"; z[lc++]="PaError PaHost_Init( void )"; z[lc++]="{"; z[lc++]="#if PA_SIMULATE_UNDERFLOW"; z[lc++]=" PRINT((\"WARNING - Underflow Simulation Enabled - Expect a Big Glitch!!!\\n\"));"; z[lc++]="#endif"; z[lc++]=" return Pa_MaybeQueryDevices();"; z[lc++]="}"; z[lc++]="/**********************************************************************"; z[lc++]="** Check WAVE buffers to see if they are done."; z[lc++]="** Fill any available output buffers and use any available"; z[lc++]="** input buffers by calling user callback."; z[lc++]="*/"; z[lc++]="static PaError Pa_TimeSlice( internalPortAudioStream *past )"; z[lc++]="{"; z[lc++]=" PaError result = 0;"; z[lc++]=" long bytesEmpty = 0;"; z[lc++]=" long bytesFilled = 0;"; z[lc++]=" long buffersEmpty = 0;"; z[lc++]=" MMRESULT mresult;"; z[lc++]=" char *inBufPtr;"; z[lc++]=" char *outBufPtr;"; z[lc++]=" int gotInput = 0;"; z[lc++]=" int gotOutput = 0;"; z[lc++]=" int i;"; z[lc++]=" int buffersProcessed = 0;"; z[lc++]=" int done = 0;"; z[lc++]=" PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData;"; z[lc++]=" if( pahsc == NULL ) return paInternalError;"; z[lc++]=" past->past_NumCallbacks += 1;"; z[lc++]="#if PA_SIMULATE_UNDERFLOW"; z[lc++]=" if(gUnderCallbackCounter++ == UNDER_SLEEP_AT)"; z[lc++]=" {"; z[lc++]=" Sleep(UNDER_SLEEP_FOR);"; z[lc++]=" }"; z[lc++]="#endif"; z[lc++]="#if PA_TRACE_RUN"; z[lc++]=" AddTraceMessage(\"Pa_TimeSlice: past_NumCallbacks \", past->past_NumCallbacks );"; z[lc++]="#endif"; z[lc++]=" while(!done)"; z[lc++]=" {"; z[lc++]="/* If we are using output, then we need an empty output buffer. */"; z[lc++]=" gotOutput = 0;"; z[lc++]=" outBufPtr = NULL;"; z[lc++]=" if( past->past_NumOutputChannels > 0 )"; z[lc++]=" {"; z[lc++]=" if((pahsc->pahsc_OutputBuffers[ pahsc->pahsc_CurrentOutputBuffer ].dwFlags & WHDR_DONE) == 0)"; z[lc++]=" { "; z[lc++]=" break; /* If none empty then bail and try again later. */"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" outBufPtr = pahsc->pahsc_OutputBuffers[ pahsc->pahsc_CurrentOutputBuffer ].lpData;"; z[lc++]=" gotOutput = 1;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]="/* Use an input buffer if one is available. */"; z[lc++]=" gotInput = 0;"; z[lc++]=" inBufPtr = NULL;"; z[lc++]=" if( ( past->past_NumInputChannels > 0 ) &&"; z[lc++]=" (pahsc->pahsc_InputBuffers[ pahsc->pahsc_CurrentInputBuffer ].dwFlags & WHDR_DONE) )"; z[lc++]=" {"; z[lc++]=" inBufPtr = pahsc->pahsc_InputBuffers[ pahsc->pahsc_CurrentInputBuffer ].lpData;"; z[lc++]=" gotInput = 1;"; z[lc++]="#if PA_TRACE_RUN"; z[lc++]=" AddTraceMessage(\"Pa_TimeSlice: got input buffer at \", (int)inBufPtr );"; z[lc++]=" AddTraceMessage(\"Pa_TimeSlice: got input buffer # \", pahsc->pahsc_CurrentInputBuffer );"; z[lc++]="#endif"; z[lc++]=" }"; z[lc++]="/* If we can't do anything then bail out. */"; z[lc++]=" if( !gotInput && !gotOutput ) break;"; z[lc++]=" buffersProcessed += 1;"; z[lc++]="/* Each Wave buffer contains multiple user buffers so do them all now. */"; z[lc++]="/* Base Usage on time it took to process one host buffer. */"; z[lc++]=" Pa_StartUsageCalculation( past );"; z[lc++]=" for( i=0; ipahsc_UserBuffersPerHostBuffer; i++ )"; z[lc++]=" {"; z[lc++]=" if( done )"; z[lc++]=" {"; z[lc++]=" if( gotOutput )"; z[lc++]=" {"; z[lc++]=" /* Clear remainder of wave buffer if we are waiting for stop. */"; z[lc++]=" AddTraceMessage(\"Pa_TimeSlice: zero rest of wave buffer \", i );"; z[lc++]=" memset( outBufPtr, 0, pahsc->pahsc_BytesPerUserOutputBuffer );"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" /* Convert 16 bit native data to user data and call user routine. */"; z[lc++]=" result = Pa_CallConvertInt16( past, (short *) inBufPtr, (short *) outBufPtr );"; z[lc++]=" if( result != 0) done = 1;"; z[lc++]=" }"; z[lc++]=" if( gotInput ) inBufPtr += pahsc->pahsc_BytesPerUserInputBuffer;"; z[lc++]=" if( gotOutput) outBufPtr += pahsc->pahsc_BytesPerUserOutputBuffer;"; z[lc++]=" }"; z[lc++]=" Pa_EndUsageCalculation( past );"; z[lc++]="/* Send WAVE buffer to Wave Device to be refilled. */"; z[lc++]=" if( gotInput )"; z[lc++]=" {"; z[lc++]=" mresult = waveInAddBuffer( pahsc->pahsc_HWaveIn,"; z[lc++]=" &pahsc->pahsc_InputBuffers[ pahsc->pahsc_CurrentInputBuffer ],"; z[lc++]=" sizeof(WAVEHDR) );"; z[lc++]=" if( mresult != MMSYSERR_NOERROR )"; z[lc++]=" {"; z[lc++]=" sPaHostError = mresult;"; z[lc++]=" result = paHostError;"; z[lc++]=" break;"; z[lc++]=" }"; z[lc++]=" pahsc->pahsc_CurrentInputBuffer = (pahsc->pahsc_CurrentInputBuffer+1 >= pahsc->pahsc_NumHostBuffers) ?"; z[lc++]=" 0 : pahsc->pahsc_CurrentInputBuffer+1;"; z[lc++]=" }"; z[lc++]="/* Write WAVE buffer to Wave Device. */"; z[lc++]=" if( gotOutput )"; z[lc++]=" {"; z[lc++]="#if PA_TRACE_START_STOP"; z[lc++]=" AddTraceMessage( \"Pa_TimeSlice: writing buffer \", pahsc->pahsc_CurrentOutputBuffer );"; z[lc++]="#endif"; z[lc++]=" mresult = waveOutWrite( pahsc->pahsc_HWaveOut,"; z[lc++]=" &pahsc->pahsc_OutputBuffers[ pahsc->pahsc_CurrentOutputBuffer ],"; z[lc++]=" sizeof(WAVEHDR) );"; z[lc++]=" if( mresult != MMSYSERR_NOERROR )"; z[lc++]=" {"; z[lc++]=" sPaHostError = mresult;"; z[lc++]=" result = paHostError;"; z[lc++]=" break;"; z[lc++]=" }"; z[lc++]=" pahsc->pahsc_CurrentOutputBuffer = (pahsc->pahsc_CurrentOutputBuffer+1 >= pahsc->pahsc_NumHostBuffers) ?"; z[lc++]=" 0 : pahsc->pahsc_CurrentOutputBuffer+1;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" "; z[lc++]="#if PA_TRACE_RUN"; z[lc++]=" AddTraceMessage(\"Pa_TimeSlice: buffersProcessed \", buffersProcessed );"; z[lc++]="#endif"; z[lc++]=" return (result != 0) ? result : done;"; z[lc++]="}"; z[lc++]="/*******************************************************************/"; z[lc++]="static PaError PaHost_BackgroundManager( internalPortAudioStream *past )"; z[lc++]="{"; z[lc++]=" PaError result = 0;"; z[lc++]=" int i;"; z[lc++]=" int numQueuedOutputBuffers = 0;"; z[lc++]=" PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData;"; z[lc++]="/* Has someone asked us to abort by calling Pa_AbortStream()? */"; z[lc++]=" if( past->past_StopNow )"; z[lc++]=" {"; z[lc++]=" past->past_IsActive = 0; /* Will cause thread to return. */"; z[lc++]=" }"; z[lc++]="/* Has someone asked us to stop by calling Pa_StopStream()"; z[lc++]=" * OR has a user callback returned '1' to indicate finished."; z[lc++]=" */"; z[lc++]=" else if( past->past_StopSoon )"; z[lc++]=" {"; z[lc++]="/* Poll buffer and when all have played then exit thread. */"; z[lc++]="/* Count how many output buffers are queued. */"; z[lc++]=" numQueuedOutputBuffers = 0;"; z[lc++]=" if( past->past_NumOutputChannels > 0 )"; z[lc++]=" {"; z[lc++]=" for( i=0; ipahsc_NumHostBuffers; i++ )"; z[lc++]=" {"; z[lc++]=" if( !( pahsc->pahsc_OutputBuffers[ i ].dwFlags & WHDR_DONE) )"; z[lc++]=" {"; z[lc++]="#if PA_TRACE_START_STOP"; z[lc++]="AddTraceMessage( \"WinMMPa_OutputThreadProc: waiting for buffer \", i );"; z[lc++]="#endif"; z[lc++]=" numQueuedOutputBuffers++;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]="#if PA_TRACE_START_STOP"; z[lc++]="AddTraceMessage( \"WinMMPa_OutputThreadProc: numQueuedOutputBuffers \", numQueuedOutputBuffers );"; z[lc++]="#endif"; z[lc++]=" if( numQueuedOutputBuffers == 0 )"; z[lc++]=" {"; z[lc++]=" past->past_IsActive = 0; /* Will cause thread to return. */"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]="/* Process full input buffer and fill up empty output buffers. */"; z[lc++]=" if( (result = Pa_TimeSlice( past )) != 0) "; z[lc++]=" {"; z[lc++]=" /* User callback has asked us to stop. */"; z[lc++]="#if PA_TRACE_START_STOP"; z[lc++]="AddTraceMessage( \"WinMMPa_OutputThreadProc: TimeSlice() returned \", result );"; z[lc++]="#endif"; z[lc++]=" past->past_StopSoon = 1; /* Request that audio play out then stop. */"; z[lc++]=" result = paNoError;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" "; z[lc++]=" PaHost_UpdateStreamTime( pahsc );"; z[lc++]=" return result;"; z[lc++]="}"; z[lc++]="#if PA_USE_TIMER_CALLBACK"; z[lc++]="/*******************************************************************/"; z[lc++]="static void CALLBACK Pa_TimerCallback(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)"; z[lc++]="{"; z[lc++]=" internalPortAudioStream *past;"; z[lc++]=" PaHostSoundControl *pahsc;"; z[lc++]=" PaError result;"; z[lc++]=" past = (internalPortAudioStream *) dwUser;"; z[lc++]=" if( past == NULL ) return;"; z[lc++]=" pahsc = (PaHostSoundControl *) past->past_DeviceData;"; z[lc++]=" if( pahsc == NULL ) return;"; z[lc++]=" if( pahsc->pahsc_IfInsideCallback )"; z[lc++]=" {"; z[lc++]=" if( pahsc->pahsc_TimerID != 0 )"; z[lc++]=" {"; z[lc++]=" timeKillEvent(pahsc->pahsc_TimerID); /* Stop callback timer. */"; z[lc++]=" pahsc->pahsc_TimerID = 0;"; z[lc++]=" }"; z[lc++]=" return;"; z[lc++]=" }"; z[lc++]=" pahsc->pahsc_IfInsideCallback = 1;"; z[lc++]="/* Manage flags and audio processing. */"; z[lc++]=" result = PaHost_BackgroundManager( past );"; z[lc++]=" if( result != paNoError )"; z[lc++]=" {"; z[lc++]=" past->past_IsActive = 0;"; z[lc++]=" }"; z[lc++]=" pahsc->pahsc_IfInsideCallback = 0;"; z[lc++]="}"; z[lc++]="#else /* PA_USE_TIMER_CALLBACK */"; z[lc++]="/*******************************************************************/"; z[lc++]="static DWORD WINAPI WinMMPa_OutputThreadProc( void *pArg )"; z[lc++]="{"; z[lc++]=" internalPortAudioStream *past;"; z[lc++]=" PaHostSoundControl *pahsc;"; z[lc++]=" void *inputBuffer=NULL;"; z[lc++]=" HANDLE events[2];"; z[lc++]=" int numEvents = 0;"; z[lc++]=" DWORD result = 0;"; z[lc++]=" DWORD waitResult;"; z[lc++]=" DWORD numTimeouts = 0;"; z[lc++]=" DWORD timeOut;"; z[lc++]=" past = (internalPortAudioStream *) pArg;"; z[lc++]=" pahsc = (PaHostSoundControl *) past->past_DeviceData;"; z[lc++]="#if PA_TRACE_START_STOP"; z[lc++]=" AddTraceMessage( \"WinMMPa_OutputThreadProc: timeoutPeriod\", timeoutPeriod );"; z[lc++]=" AddTraceMessage( \"WinMMPa_OutputThreadProc: past_NumUserBuffers\", past->past_NumUserBuffers );"; z[lc++]="#endif"; z[lc++]="/* Calculate timeOut as half the time it would take to play all buffers. */"; z[lc++]=" timeOut = (DWORD) (500.0 * PaHost_GetTotalBufferFrames( past ) / past->past_SampleRate);"; z[lc++]="/* Get event(s) ready for wait. */"; z[lc++]=" events[numEvents++] = pahsc->pahsc_BufferEvent;"; z[lc++]=" if( pahsc->pahsc_AbortEventInited ) events[numEvents++] = pahsc->pahsc_AbortEvent;"; z[lc++]="/* Stay in this thread as long as we are \"active\". */"; z[lc++]=" while( past->past_IsActive )"; z[lc++]=" {"; z[lc++]="/*******************************************************************/"; z[lc++]="/******** WAIT here for an event from WMME or PA *******************/"; z[lc++]="/*******************************************************************/"; z[lc++]=" waitResult = WaitForMultipleObjects( numEvents, events, FALSE, timeOut );"; z[lc++]=" /* Error? */"; z[lc++]=" if( waitResult == WAIT_FAILED )"; z[lc++]=" {"; z[lc++]=" sPaHostError = GetLastError();"; z[lc++]=" result = paHostError;"; z[lc++]=" past->past_IsActive = 0;"; z[lc++]=" }"; z[lc++]=" /* Timeout? Don't stop. Just keep polling for DONE.*/"; z[lc++]=" else if( waitResult == WAIT_TIMEOUT )"; z[lc++]=" {"; z[lc++]="#if PA_TRACE_START_STOP"; z[lc++]=" AddTraceMessage( \"WinMMPa_OutputThreadProc: timed out \", numQueuedOutputBuffers );"; z[lc++]="#endif"; z[lc++]=" numTimeouts += 1;"; z[lc++]=" }"; z[lc++]=" /* Manage flags and audio processing. */"; z[lc++]=" result = PaHost_BackgroundManager( past );"; z[lc++]=" if( result != paNoError )"; z[lc++]=" {"; z[lc++]=" past->past_IsActive = 0;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" return result;"; z[lc++]="}"; z[lc++]="#endif"; z[lc++]="/*******************************************************************/"; z[lc++]="PaError PaHost_OpenInputStream( internalPortAudioStream *past )"; z[lc++]="{"; z[lc++]=" MMRESULT mr;"; z[lc++]=" PaError result = paNoError;"; z[lc++]=" PaHostSoundControl *pahsc;"; z[lc++]=" int i;"; z[lc++]=" int inputMmId;"; z[lc++]=" int bytesPerInputFrame;"; z[lc++]=" WAVEFORMATEX wfx;"; z[lc++]=" const PaDeviceInfo *pad;"; z[lc++]=" pahsc = (PaHostSoundControl *) past->past_DeviceData;"; z[lc++]=" DBUG((\"PaHost_OpenStream: deviceID = 0x%x\\n\", past->past_InputDeviceID));"; z[lc++]=" pad = Pa_GetDeviceInfo( past->past_InputDeviceID );"; z[lc++]=" if( pad == NULL ) return paInternalError;"; z[lc++]=" switch( pad->nativeSampleFormats )"; z[lc++]=" {"; z[lc++]=" case paInt32:"; z[lc++]=" case paFloat32:"; z[lc++]=" bytesPerInputFrame = sizeof(float) * past->past_NumInputChannels;"; z[lc++]=" break;"; z[lc++]=" default:"; z[lc++]=" bytesPerInputFrame = sizeof(short) * past->past_NumInputChannels;"; z[lc++]=" break;"; z[lc++]=" }"; z[lc++]=" wfx.wFormatTag = WAVE_FORMAT_PCM;"; z[lc++]=" wfx.nChannels = (WORD) past->past_NumInputChannels;"; z[lc++]=" wfx.nSamplesPerSec = (DWORD) past->past_SampleRate;"; z[lc++]=" wfx.nAvgBytesPerSec = (DWORD)(bytesPerInputFrame * past->past_SampleRate);"; z[lc++]=" wfx.nBlockAlign = (WORD)bytesPerInputFrame;"; z[lc++]=" wfx.wBitsPerSample = (WORD)((bytesPerInputFrame/past->past_NumInputChannels) * 8);"; z[lc++]=" wfx.cbSize = 0;"; z[lc++]=" inputMmId = PaDeviceIdToWinId( past->past_InputDeviceID );"; z[lc++]="#if PA_USE_TIMER_CALLBACK"; z[lc++]=" mr = waveInOpen( &pahsc->pahsc_HWaveIn, inputMmId, &wfx,"; z[lc++]=" 0, 0, CALLBACK_NULL );"; z[lc++]="#else"; z[lc++]=" mr = waveInOpen( &pahsc->pahsc_HWaveIn, inputMmId, &wfx,"; z[lc++]=" (DWORD)pahsc->pahsc_BufferEvent, (DWORD) past, CALLBACK_EVENT );"; z[lc++]="#endif"; z[lc++]=" if( mr != MMSYSERR_NOERROR )"; z[lc++]=" {"; z[lc++]=" ERR_RPT((\"PortAudio: PaHost_OpenInputStream() failed!\\n\"));"; z[lc++]=" result = paHostError;"; z[lc++]=" sPaHostError = mr;"; z[lc++]=" goto error;"; z[lc++]=" }"; z[lc++]="/* Allocate an array to hold the buffer pointers. */"; z[lc++]=" pahsc->pahsc_InputBuffers = (WAVEHDR *) GlobalAlloc( GMEM_FIXED | GMEM_ZEROINIT, sizeof(WAVEHDR)*pahsc->pahsc_NumHostBuffers ); /* MEM */"; z[lc++]=" if( pahsc->pahsc_InputBuffers == NULL )"; z[lc++]=" {"; z[lc++]=" result = paInsufficientMemory;"; z[lc++]=" goto error;"; z[lc++]=" }"; z[lc++]="/* Allocate each buffer. */"; z[lc++]=" for( i=0; ipahsc_NumHostBuffers; i++ )"; z[lc++]=" {"; z[lc++]=" pahsc->pahsc_InputBuffers[i].lpData = (char *)GlobalAlloc( GMEM_FIXED, pahsc->pahsc_BytesPerHostInputBuffer ); /* MEM */"; z[lc++]=" if( pahsc->pahsc_InputBuffers[i].lpData == NULL )"; z[lc++]=" {"; z[lc++]=" result = paInsufficientMemory;"; z[lc++]=" goto error;"; z[lc++]=" }"; z[lc++]=" pahsc->pahsc_InputBuffers[i].dwBufferLength = pahsc->pahsc_BytesPerHostInputBuffer;"; z[lc++]=" pahsc->pahsc_InputBuffers[i].dwUser = i;"; z[lc++]=" if( ( mr = waveInPrepareHeader( pahsc->pahsc_HWaveIn, &pahsc->pahsc_InputBuffers[i], sizeof(WAVEHDR) )) != MMSYSERR_NOERROR )"; z[lc++]=" {"; z[lc++]=" result = paHostError;"; z[lc++]=" sPaHostError = mr;"; z[lc++]=" goto error;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" return result;"; z[lc++]="error:"; z[lc++]=" return result;"; z[lc++]="}"; z[lc++]="/*******************************************************************/"; z[lc++]="PaError PaHost_OpenOutputStream( internalPortAudioStream *past )"; z[lc++]="{"; z[lc++]=" MMRESULT mr;"; z[lc++]=" PaError result = paNoError;"; z[lc++]=" PaHostSoundControl *pahsc;"; z[lc++]=" int i;"; z[lc++]=" int outputMmID;"; z[lc++]=" int bytesPerOutputFrame;"; z[lc++]=" WAVEFORMATEX wfx;"; z[lc++]=" const PaDeviceInfo *pad;"; z[lc++]=" pahsc = (PaHostSoundControl *) past->past_DeviceData;"; z[lc++]=" DBUG((\"PaHost_OpenStream: deviceID = 0x%x\\n\", past->past_OutputDeviceID));"; z[lc++]=" pad = Pa_GetDeviceInfo( past->past_OutputDeviceID );"; z[lc++]=" if( pad == NULL ) return paInternalError;"; z[lc++]=" switch( pad->nativeSampleFormats )"; z[lc++]=" {"; z[lc++]=" case paInt32:"; z[lc++]=" case paFloat32:"; z[lc++]=" bytesPerOutputFrame = sizeof(float) * past->past_NumOutputChannels;"; z[lc++]=" break;"; z[lc++]=" default:"; z[lc++]=" bytesPerOutputFrame = sizeof(short) * past->past_NumOutputChannels;"; z[lc++]=" break;"; z[lc++]=" }"; z[lc++]=" wfx.wFormatTag = WAVE_FORMAT_PCM;"; z[lc++]=" wfx.nChannels = (WORD) past->past_NumOutputChannels;"; z[lc++]=" wfx.nSamplesPerSec = (DWORD) past->past_SampleRate;"; z[lc++]=" wfx.nAvgBytesPerSec = (DWORD)(bytesPerOutputFrame * past->past_SampleRate);"; z[lc++]=" wfx.nBlockAlign = (WORD)bytesPerOutputFrame;"; z[lc++]=" wfx.wBitsPerSample = (WORD)((bytesPerOutputFrame/past->past_NumOutputChannels) * 8);"; z[lc++]=" wfx.cbSize = 0;"; z[lc++]=" outputMmID = PaDeviceIdToWinId( past->past_OutputDeviceID );"; z[lc++]="#if PA_USE_TIMER_CALLBACK"; z[lc++]=" mr = waveOutOpen( &pahsc->pahsc_HWaveOut, outputMmID, &wfx,"; z[lc++]=" 0, 0, CALLBACK_NULL );"; z[lc++]="#else"; z[lc++]=" "; z[lc++]=" pahsc->pahsc_AbortEvent = CreateEvent( NULL, TRUE, FALSE, NULL );"; z[lc++]=" if( pahsc->pahsc_AbortEvent == NULL )"; z[lc++]=" {"; z[lc++]=" result = paHostError;"; z[lc++]=" sPaHostError = GetLastError();"; z[lc++]=" goto error;"; z[lc++]=" }"; z[lc++]=" pahsc->pahsc_AbortEventInited = 1;"; z[lc++]=" mr = waveOutOpen( &pahsc->pahsc_HWaveOut, outputMmID, &wfx,"; z[lc++]=" (DWORD)pahsc->pahsc_BufferEvent, (DWORD) past, CALLBACK_EVENT );"; z[lc++]="#endif"; z[lc++]=" if( mr != MMSYSERR_NOERROR )"; z[lc++]=" {"; z[lc++]=" ERR_RPT((\"PortAudio: PaHost_OpenOutputStream() failed!\\n\"));"; z[lc++]=" result = paHostError;"; z[lc++]=" sPaHostError = mr;"; z[lc++]=" goto error;"; z[lc++]=" }"; z[lc++]="/* Allocate an array to hold the buffer pointers. */"; z[lc++]=" pahsc->pahsc_OutputBuffers = (WAVEHDR *) GlobalAlloc( GMEM_FIXED | GMEM_ZEROINIT, sizeof(WAVEHDR)*pahsc->pahsc_NumHostBuffers ); /* MEM */"; z[lc++]=" if( pahsc->pahsc_OutputBuffers == NULL )"; z[lc++]=" {"; z[lc++]=" result = paInsufficientMemory;"; z[lc++]=" goto error;"; z[lc++]=" }"; z[lc++]="/* Allocate each buffer. */"; z[lc++]=" for( i=0; ipahsc_NumHostBuffers; i++ )"; z[lc++]=" {"; z[lc++]=" pahsc->pahsc_OutputBuffers[i].lpData = (char *) GlobalAlloc( GMEM_FIXED, pahsc->pahsc_BytesPerHostOutputBuffer ); /* MEM */"; z[lc++]=" if( pahsc->pahsc_OutputBuffers[i].lpData == NULL )"; z[lc++]=" {"; z[lc++]=" result = paInsufficientMemory;"; z[lc++]=" goto error;"; z[lc++]=" }"; z[lc++]=" pahsc->pahsc_OutputBuffers[i].dwBufferLength = pahsc->pahsc_BytesPerHostOutputBuffer;"; z[lc++]=" pahsc->pahsc_OutputBuffers[i].dwUser = i;"; z[lc++]=" if( (mr = waveOutPrepareHeader( pahsc->pahsc_HWaveOut, &pahsc->pahsc_OutputBuffers[i], sizeof(WAVEHDR) )) != MMSYSERR_NOERROR )"; z[lc++]=" {"; z[lc++]=" result = paHostError;"; z[lc++]=" sPaHostError = mr;"; z[lc++]=" goto error;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" return result;"; z[lc++]="error:"; z[lc++]=" return result;"; z[lc++]="}"; z[lc++]="/*******************************************************************/"; z[lc++]="PaError PaHost_GetTotalBufferFrames( internalPortAudioStream *past )"; z[lc++]="{"; z[lc++]=" PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData;"; z[lc++]=" return pahsc->pahsc_NumHostBuffers * pahsc->pahsc_FramesPerHostBuffer;"; z[lc++]="}"; z[lc++]="/*******************************************************************"; z[lc++]="* Determine number of WAVE Buffers"; z[lc++]="* and how many User Buffers we can put into each WAVE buffer."; z[lc++]="*/"; z[lc++]="static void PaHost_CalcNumHostBuffers( internalPortAudioStream *past )"; z[lc++]="{"; z[lc++]=" PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData;"; z[lc++]=" unsigned int minNumBuffers;"; z[lc++]=" int minFramesPerHostBuffer;"; z[lc++]=" int maxFramesPerHostBuffer;"; z[lc++]=" int minTotalFrames;"; z[lc++]=" int userBuffersPerHostBuffer;"; z[lc++]=" int framesPerHostBuffer;"; z[lc++]=" int numHostBuffers;"; z[lc++]="/* Calculate minimum and maximum sizes based on timing and sample rate. */"; z[lc++]=" minFramesPerHostBuffer = (int) (PA_MIN_MSEC_PER_HOST_BUFFER * past->past_SampleRate / 1000.0);"; z[lc++]=" minFramesPerHostBuffer = (minFramesPerHostBuffer + 7) & ~7;"; z[lc++]=" DBUG((\"PaHost_CalcNumHostBuffers: minFramesPerHostBuffer = %d\\n\", minFramesPerHostBuffer ));"; z[lc++]=" maxFramesPerHostBuffer = (int) (PA_MAX_MSEC_PER_HOST_BUFFER * past->past_SampleRate / 1000.0);"; z[lc++]=" maxFramesPerHostBuffer = (maxFramesPerHostBuffer + 7) & ~7;"; z[lc++]=" DBUG((\"PaHost_CalcNumHostBuffers: maxFramesPerHostBuffer = %d\\n\", maxFramesPerHostBuffer ));"; z[lc++]="/* Determine number of user buffers based on minimum latency. */"; z[lc++]=" minNumBuffers = Pa_GetMinNumBuffers( past->past_FramesPerUserBuffer, past->past_SampleRate );"; z[lc++]=" past->past_NumUserBuffers = ( minNumBuffers > past->past_NumUserBuffers ) ? minNumBuffers : past->past_NumUserBuffers;"; z[lc++]=" DBUG((\"PaHost_CalcNumHostBuffers: min past_NumUserBuffers = %d\\n\", past->past_NumUserBuffers ));"; z[lc++]=" minTotalFrames = past->past_NumUserBuffers * past->past_FramesPerUserBuffer;"; z[lc++]="/* We cannot make the WAVE buffers too small because they may not get serviced quickly enough. */"; z[lc++]=" if( (int) past->past_FramesPerUserBuffer < minFramesPerHostBuffer )"; z[lc++]=" {"; z[lc++]=" userBuffersPerHostBuffer ="; z[lc++]=" (minFramesPerHostBuffer + past->past_FramesPerUserBuffer - 1) /"; z[lc++]=" past->past_FramesPerUserBuffer;"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" userBuffersPerHostBuffer = 1;"; z[lc++]=" }"; z[lc++]=" framesPerHostBuffer = past->past_FramesPerUserBuffer * userBuffersPerHostBuffer;"; z[lc++]="/* Calculate number of WAVE buffers needed. Round up to cover minTotalFrames. */"; z[lc++]=" numHostBuffers = (minTotalFrames + framesPerHostBuffer - 1) / framesPerHostBuffer;"; z[lc++]="/* Make sure we have anough WAVE buffers. */"; z[lc++]=" if( numHostBuffers < PA_MIN_NUM_HOST_BUFFERS)"; z[lc++]=" {"; z[lc++]=" numHostBuffers = PA_MIN_NUM_HOST_BUFFERS;"; z[lc++]=" }"; z[lc++]=" else if( (numHostBuffers > PA_MAX_NUM_HOST_BUFFERS) && "; z[lc++]=" ((int) past->past_FramesPerUserBuffer < (maxFramesPerHostBuffer/2) ) )"; z[lc++]=" {"; z[lc++]="/* If we have too many WAVE buffers, try to put more user buffers in a wave buffer. */"; z[lc++]=" while(numHostBuffers > PA_MAX_NUM_HOST_BUFFERS)"; z[lc++]=" {"; z[lc++]=" userBuffersPerHostBuffer += 1;"; z[lc++]=" framesPerHostBuffer = past->past_FramesPerUserBuffer * userBuffersPerHostBuffer;"; z[lc++]=" numHostBuffers = (minTotalFrames + framesPerHostBuffer - 1) / framesPerHostBuffer;"; z[lc++]=" /* If we have gone too far, back up one. */"; z[lc++]=" if( (framesPerHostBuffer > maxFramesPerHostBuffer) ||"; z[lc++]=" (numHostBuffers < PA_MAX_NUM_HOST_BUFFERS) )"; z[lc++]=" {"; z[lc++]=" userBuffersPerHostBuffer -= 1;"; z[lc++]=" framesPerHostBuffer = past->past_FramesPerUserBuffer * userBuffersPerHostBuffer;"; z[lc++]=" numHostBuffers = (minTotalFrames + framesPerHostBuffer - 1) / framesPerHostBuffer;"; z[lc++]=" break;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" "; z[lc++]=" pahsc->pahsc_UserBuffersPerHostBuffer = userBuffersPerHostBuffer;"; z[lc++]=" pahsc->pahsc_FramesPerHostBuffer = framesPerHostBuffer;"; z[lc++]=" pahsc->pahsc_NumHostBuffers = numHostBuffers;"; z[lc++]=" DBUG((\"PaHost_CalcNumHostBuffers: pahsc_UserBuffersPerHostBuffer = %d\\n\", pahsc->pahsc_UserBuffersPerHostBuffer ));"; z[lc++]=" DBUG((\"PaHost_CalcNumHostBuffers: pahsc_NumHostBuffers = %d\\n\", pahsc->pahsc_NumHostBuffers ));"; z[lc++]=" DBUG((\"PaHost_CalcNumHostBuffers: pahsc_FramesPerHostBuffer = %d\\n\", pahsc->pahsc_FramesPerHostBuffer ));"; z[lc++]=" DBUG((\"PaHost_CalcNumHostBuffers: past_NumUserBuffers = %d\\n\", past->past_NumUserBuffers ));"; z[lc++]="}"; z[lc++]="/*******************************************************************/"; z[lc++]="PaError PaHost_OpenStream( internalPortAudioStream *past )"; z[lc++]="{"; z[lc++]=" PaError result = paNoError;"; z[lc++]=" PaHostSoundControl *pahsc;"; z[lc++]="/* Allocate and initialize host data. */"; z[lc++]=" pahsc = (PaHostSoundControl *) PaHost_AllocateFastMemory(sizeof(PaHostSoundControl)); /* MEM */"; z[lc++]=" if( pahsc == NULL )"; z[lc++]=" {"; z[lc++]=" result = paInsufficientMemory;"; z[lc++]=" goto error;"; z[lc++]=" }"; z[lc++]=" memset( pahsc, 0, sizeof(PaHostSoundControl) );"; z[lc++]=" past->past_DeviceData = (void *) pahsc;"; z[lc++]="/* Figure out how user buffers fit into WAVE buffers. */"; z[lc++]=" PaHost_CalcNumHostBuffers( past );"; z[lc++]=" {"; z[lc++]=" int msecLatency = (int) ((PaHost_GetTotalBufferFrames(past) * 1000) / past->past_SampleRate);"; z[lc++]=" DBUG((\"PortAudio on WMME - Latency = %d frames, %d msec\\n\", PaHost_GetTotalBufferFrames(past), msecLatency ));"; z[lc++]=" }"; z[lc++]=" InitializeCriticalSection( &pahsc->pahsc_StreamLock );"; z[lc++]=" pahsc->pahsc_StreamLockInited = 1;"; z[lc++]=" "; z[lc++]="#if (PA_USE_TIMER_CALLBACK == 0)"; z[lc++]=" pahsc->pahsc_BufferEventInited = 0;"; z[lc++]=" pahsc->pahsc_BufferEvent = CreateEvent( NULL, FALSE, FALSE, NULL );"; z[lc++]=" if( pahsc->pahsc_BufferEvent == NULL ){"; z[lc++]=" result = paHostError;"; z[lc++]=" sPaHostError = GetLastError();"; z[lc++]=" goto error;"; z[lc++]=" }"; z[lc++]=" pahsc->pahsc_BufferEventInited = 1;"; z[lc++]="#endif /* (PA_USE_TIMER_CALLBACK == 0) */"; z[lc++]="/* ------------------ OUTPUT */"; z[lc++]=" pahsc->pahsc_BytesPerUserOutputBuffer = past->past_FramesPerUserBuffer * past->past_NumOutputChannels * sizeof(short);"; z[lc++]=" pahsc->pahsc_BytesPerHostOutputBuffer = pahsc->pahsc_UserBuffersPerHostBuffer * pahsc->pahsc_BytesPerUserOutputBuffer;"; z[lc++]=" if( (past->past_OutputDeviceID != paNoDevice) && (past->past_NumOutputChannels > 0) )"; z[lc++]=" {"; z[lc++]=" result = PaHost_OpenOutputStream( past );"; z[lc++]=" if( result < 0 ) goto error;"; z[lc++]=" }"; z[lc++]="/* ------------------ INPUT */"; z[lc++]=" pahsc->pahsc_BytesPerUserInputBuffer = past->past_FramesPerUserBuffer * past->past_NumInputChannels * sizeof(short);"; z[lc++]=" pahsc->pahsc_BytesPerHostInputBuffer = pahsc->pahsc_UserBuffersPerHostBuffer * pahsc->pahsc_BytesPerUserInputBuffer;"; z[lc++]=" if( (past->past_InputDeviceID != paNoDevice) && (past->past_NumInputChannels > 0) )"; z[lc++]=" {"; z[lc++]=" result = PaHost_OpenInputStream( past );"; z[lc++]=" if( result < 0 ) goto error;"; z[lc++]=" }"; z[lc++]="/* Calculate scalar used in CPULoad calculation. */ "; z[lc++]=" {"; z[lc++]=" LARGE_INTEGER frequency;"; z[lc++]=" if( QueryPerformanceFrequency( &frequency ) == 0 )"; z[lc++]=" {"; z[lc++]=" pahsc->pahsc_InverseTicksPerHostBuffer = 0.0;"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" pahsc->pahsc_InverseTicksPerHostBuffer = past->past_SampleRate /"; z[lc++]=" ( (double)frequency.QuadPart * past->past_FramesPerUserBuffer * pahsc->pahsc_UserBuffersPerHostBuffer );"; z[lc++]=" DBUG((\"pahsc_InverseTicksPerHostBuffer = %g\\n\", pahsc->pahsc_InverseTicksPerHostBuffer ));"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" return result;"; z[lc++]="error:"; z[lc++]=" PaHost_CloseStream( past );"; z[lc++]=" return result;"; z[lc++]="}"; z[lc++]="/*************************************************************************/"; z[lc++]="PaError PaHost_StartOutput( internalPortAudioStream *past )"; z[lc++]="{"; z[lc++]=" MMRESULT mr;"; z[lc++]=" PaHostSoundControl *pahsc;"; z[lc++]=" PaError result = paNoError;"; z[lc++]=" int i;"; z[lc++]=" pahsc = (PaHostSoundControl *) past->past_DeviceData;"; z[lc++]=" if( past->past_OutputDeviceID != paNoDevice )"; z[lc++]=" {"; z[lc++]=" if( (mr = waveOutPause( pahsc->pahsc_HWaveOut )) != MMSYSERR_NOERROR )"; z[lc++]=" {"; z[lc++]=" result = paHostError;"; z[lc++]=" sPaHostError = mr;"; z[lc++]=" goto error;"; z[lc++]=" }"; z[lc++]=" for( i=0; ipahsc_NumHostBuffers; i++ )"; z[lc++]=" {"; z[lc++]=" ZeroMemory( pahsc->pahsc_OutputBuffers[i].lpData, pahsc->pahsc_OutputBuffers[i].dwBufferLength );"; z[lc++]=" mr = waveOutWrite( pahsc->pahsc_HWaveOut, &pahsc->pahsc_OutputBuffers[i], sizeof(WAVEHDR) );"; z[lc++]=" if( mr != MMSYSERR_NOERROR )"; z[lc++]=" {"; z[lc++]=" result = paHostError;"; z[lc++]=" sPaHostError = mr;"; z[lc++]=" goto error;"; z[lc++]=" }"; z[lc++]=" past->past_FrameCount += pahsc->pahsc_FramesPerHostBuffer;"; z[lc++]=" }"; z[lc++]=" pahsc->pahsc_CurrentOutputBuffer = 0;"; z[lc++]=" if( (mr = waveOutRestart( pahsc->pahsc_HWaveOut )) != MMSYSERR_NOERROR )"; z[lc++]=" {"; z[lc++]=" result = paHostError;"; z[lc++]=" sPaHostError = mr;"; z[lc++]=" goto error;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" DBUG((\"PaHost_StartOutput: DSW_StartOutput returned = 0x%X.\\n\", hr));"; z[lc++]="error:"; z[lc++]=" return result;"; z[lc++]="}"; z[lc++]="/*************************************************************************/"; z[lc++]="PaError PaHost_StartInput( internalPortAudioStream *past )"; z[lc++]="{"; z[lc++]=" PaError result = paNoError;"; z[lc++]=" MMRESULT mr;"; z[lc++]=" int i;"; z[lc++]=" PaHostSoundControl *pahsc;"; z[lc++]=" pahsc = (PaHostSoundControl *) past->past_DeviceData;"; z[lc++]=" if( past->past_InputDeviceID != paNoDevice )"; z[lc++]=" {"; z[lc++]=" for( i=0; ipahsc_NumHostBuffers; i++ )"; z[lc++]=" {"; z[lc++]=" mr = waveInAddBuffer( pahsc->pahsc_HWaveIn, &pahsc->pahsc_InputBuffers[i], sizeof(WAVEHDR) );"; z[lc++]=" if( mr != MMSYSERR_NOERROR )"; z[lc++]=" {"; z[lc++]=" result = paHostError;"; z[lc++]=" sPaHostError = mr;"; z[lc++]=" goto error;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" pahsc->pahsc_CurrentInputBuffer = 0;"; z[lc++]=" mr = waveInStart( pahsc->pahsc_HWaveIn );"; z[lc++]=" DBUG((\"Pa_StartStream: waveInStart returned = 0x%X.\\n\", hr));"; z[lc++]=" if( mr != MMSYSERR_NOERROR )"; z[lc++]=" {"; z[lc++]=" result = paHostError;"; z[lc++]=" sPaHostError = mr;"; z[lc++]=" goto error;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]="error:"; z[lc++]=" return result;"; z[lc++]="}"; z[lc++]="/*************************************************************************/"; z[lc++]="PaError PaHost_StartEngine( internalPortAudioStream *past )"; z[lc++]="{"; z[lc++]=" PaError result = paNoError;"; z[lc++]=" PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData;"; z[lc++]="#if PA_USE_TIMER_CALLBACK"; z[lc++]=" int resolution;"; z[lc++]=" int bufsPerTimerCallback;"; z[lc++]=" int msecPerBuffer;"; z[lc++]="#endif /* PA_USE_TIMER_CALLBACK */"; z[lc++]=" "; z[lc++]=" past->past_StopSoon = 0;"; z[lc++]=" past->past_StopNow = 0;"; z[lc++]=" past->past_IsActive = 1;"; z[lc++]=" pahsc->pahsc_FramesPlayed = 0.0;"; z[lc++]=" pahsc->pahsc_LastPosition = 0;"; z[lc++]="#if PA_TRACE_START_STOP"; z[lc++]=" AddTraceMessage( \"PaHost_StartEngine: TimeSlice() returned \", result );"; z[lc++]="#endif"; z[lc++]="#if PA_USE_TIMER_CALLBACK"; z[lc++]="/* Create timer that will wake us up so we can fill the DSound buffer. */"; z[lc++]=" bufsPerTimerCallback = pahsc->pahsc_NumHostBuffers/4;"; z[lc++]=" if( bufsPerTimerCallback < 1 ) bufsPerTimerCallback = 1;"; z[lc++]=" if( bufsPerTimerCallback < 1 ) bufsPerTimerCallback = 1;"; z[lc++]=" msecPerBuffer = (1000 * bufsPerTimerCallback *"; z[lc++]=" pahsc->pahsc_UserBuffersPerHostBuffer *"; z[lc++]=" past->past_FramesPerUserBuffer ) / (int) past->past_SampleRate;"; z[lc++]=" if( msecPerBuffer < 10 ) msecPerBuffer = 10;"; z[lc++]=" else if( msecPerBuffer > 100 ) msecPerBuffer = 100;"; z[lc++]=" resolution = msecPerBuffer/4;"; z[lc++]=" pahsc->pahsc_TimerID = timeSetEvent( msecPerBuffer, resolution,"; z[lc++]=" (LPTIMECALLBACK) Pa_TimerCallback,"; z[lc++]=" (DWORD) past, TIME_PERIODIC );"; z[lc++]=" if( pahsc->pahsc_TimerID == 0 )"; z[lc++]=" {"; z[lc++]=" result = paHostError;"; z[lc++]=" sPaHostError = GetLastError();;"; z[lc++]=" goto error;"; z[lc++]=" }"; z[lc++]="#else /* PA_USE_TIMER_CALLBACK */"; z[lc++]=" ResetEvent( pahsc->pahsc_AbortEvent );"; z[lc++]="/* Create thread that waits for audio buffers to be ready for processing. */"; z[lc++]=" pahsc->pahsc_EngineThread = CreateThread( 0, 0, WinMMPa_OutputThreadProc, past, 0, &pahsc->pahsc_EngineThreadID );"; z[lc++]=" if( pahsc->pahsc_EngineThread == NULL )"; z[lc++]=" {"; z[lc++]=" result = paHostError;"; z[lc++]=" sPaHostError = GetLastError();;"; z[lc++]=" goto error;"; z[lc++]=" }"; z[lc++]="#if PA_TRACE_START_STOP"; z[lc++]=" AddTraceMessage( \"PaHost_StartEngine: thread \", (int) pahsc->pahsc_EngineThread );"; z[lc++]="#endif"; z[lc++]="/* I used to pass the thread which was failing. I now pass GetCurrentProcess()."; z[lc++]="** This fix could improve latency for some applications. It could also result in CPU"; z[lc++]="** starvation if the callback did too much processing."; z[lc++]="** I also added result checks, so we might see more failures at initialization."; z[lc++]="** Thanks to Alberto di Bene for spotting this."; z[lc++]="*/"; z[lc++]=" if( !SetPriorityClass( GetCurrentProcess(), HIGH_PRIORITY_CLASS ) ) /* PLB20010816 */"; z[lc++]=" {"; z[lc++]=" result = paHostError;"; z[lc++]=" sPaHostError = GetLastError();;"; z[lc++]=" goto error;"; z[lc++]=" }"; z[lc++]=" if( !SetThreadPriority( pahsc->pahsc_EngineThread, THREAD_PRIORITY_HIGHEST ) )"; z[lc++]=" {"; z[lc++]=" result = paHostError;"; z[lc++]=" sPaHostError = GetLastError();;"; z[lc++]=" goto error;"; z[lc++]=" }"; z[lc++]="#endif"; z[lc++]="error:"; z[lc++]=" return result;"; z[lc++]="}"; z[lc++]="/*************************************************************************/"; z[lc++]="PaError PaHost_StopEngine( internalPortAudioStream *past, int abort )"; z[lc++]="{"; z[lc++]=" int timeOut;"; z[lc++]=" PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData;"; z[lc++]=" if( pahsc == NULL ) return paNoError;"; z[lc++]="/* Tell background thread to stop generating more data and to let current data play out. */"; z[lc++]=" past->past_StopSoon = 1;"; z[lc++]="/* If aborting, tell background thread to stop NOW! */"; z[lc++]=" if( abort ) past->past_StopNow = 1;"; z[lc++]="/* Calculate timeOut longer than longest time it could take to play all buffers. */"; z[lc++]=" timeOut = (DWORD) (1500.0 * PaHost_GetTotalBufferFrames( past ) / past->past_SampleRate);"; z[lc++]=" if( timeOut < MIN_TIMEOUT_MSEC ) timeOut = MIN_TIMEOUT_MSEC;"; z[lc++]="#if PA_USE_TIMER_CALLBACK"; z[lc++]=" if( (past->past_OutputDeviceID != paNoDevice) &&"; z[lc++]=" past->past_IsActive &&"; z[lc++]=" (pahsc->pahsc_TimerID != 0) )"; z[lc++]=" {"; z[lc++]=" /* Wait for IsActive to drop. */"; z[lc++]=" while( (past->past_IsActive) && (timeOut > 0) )"; z[lc++]=" {"; z[lc++]=" Sleep(10);"; z[lc++]=" timeOut -= 10;"; z[lc++]=" }"; z[lc++]=" timeKillEvent(pahsc->pahsc_TimerID); /* Stop callback timer. */"; z[lc++]=" pahsc->pahsc_TimerID = 0;"; z[lc++]=" }"; z[lc++]="#else /* PA_USE_TIMER_CALLBACK */"; z[lc++]="#if PA_TRACE_START_STOP"; z[lc++]=" AddTraceMessage( \"PaHost_StopEngine: thread \", (int) pahsc->pahsc_EngineThread );"; z[lc++]="#endif"; z[lc++]=" if( (past->past_OutputDeviceID != paNoDevice) &&"; z[lc++]=" (past->past_IsActive) &&"; z[lc++]=" (pahsc->pahsc_EngineThread != NULL) )"; z[lc++]=" {"; z[lc++]=" DWORD got;"; z[lc++]="/* Tell background thread to stop generating more data and to let current data play out. */"; z[lc++]=" DBUG((\"PaHost_StopEngine: waiting for background thread.\\n\"));"; z[lc++]=" got = WaitForSingleObject( pahsc->pahsc_EngineThread, timeOut );"; z[lc++]=" if( got == WAIT_TIMEOUT )"; z[lc++]=" {"; z[lc++]=" ERR_RPT((\"PaHost_StopEngine: timed out while waiting for background thread.\\n\"));"; z[lc++]=" return paTimedOut;"; z[lc++]=" }"; z[lc++]=" CloseHandle( pahsc->pahsc_EngineThread );"; z[lc++]=" pahsc->pahsc_EngineThread = NULL;"; z[lc++]=" }"; z[lc++]="#endif /* PA_USE_TIMER_CALLBACK */"; z[lc++]=" past->past_IsActive = 0;"; z[lc++]=" return paNoError;"; z[lc++]="}"; z[lc++]="/*************************************************************************/"; z[lc++]="PaError PaHost_StopInput( internalPortAudioStream *past, int abort )"; z[lc++]="{"; z[lc++]=" MMRESULT mr;"; z[lc++]=" PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData;"; z[lc++]=" if( pahsc == NULL ) return paNoError;"; z[lc++]=" (void) abort;"; z[lc++]=" if( pahsc->pahsc_HWaveIn != NULL )"; z[lc++]=" {"; z[lc++]=" mr = waveInReset( pahsc->pahsc_HWaveIn );"; z[lc++]=" if( mr != MMSYSERR_NOERROR )"; z[lc++]=" {"; z[lc++]=" sPaHostError = mr;"; z[lc++]=" return paHostError;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" return paNoError;"; z[lc++]="}"; z[lc++]="/*************************************************************************/"; z[lc++]="PaError PaHost_StopOutput( internalPortAudioStream *past, int abort )"; z[lc++]="{"; z[lc++]=" MMRESULT mr;"; z[lc++]=" PaHostSoundControl *pahsc;"; z[lc++]=" pahsc = (PaHostSoundControl *) past->past_DeviceData;"; z[lc++]=" if( pahsc == NULL ) return paNoError;"; z[lc++]=" (void) abort;"; z[lc++]="#if PA_TRACE_START_STOP"; z[lc++]=" AddTraceMessage( \"PaHost_StopOutput: pahsc_HWaveOut \", (int) pahsc->pahsc_HWaveOut );"; z[lc++]="#endif"; z[lc++]=" if( pahsc->pahsc_HWaveOut != NULL )"; z[lc++]=" {"; z[lc++]=" mr = waveOutReset( pahsc->pahsc_HWaveOut );"; z[lc++]=" if( mr != MMSYSERR_NOERROR )"; z[lc++]=" {"; z[lc++]=" sPaHostError = mr;"; z[lc++]=" return paHostError;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" return paNoError;"; z[lc++]="}"; z[lc++]="/*******************************************************************/"; z[lc++]="PaError PaHost_CloseStream( internalPortAudioStream *past )"; z[lc++]="{"; z[lc++]=" int i;"; z[lc++]=" PaHostSoundControl *pahsc;"; z[lc++]=" if( past == NULL ) return paBadStreamPtr;"; z[lc++]=" pahsc = (PaHostSoundControl *) past->past_DeviceData;"; z[lc++]=" if( pahsc == NULL ) return paNoError;"; z[lc++]="#if PA_TRACE_START_STOP"; z[lc++]=" AddTraceMessage( \"PaHost_CloseStream: pahsc_HWaveOut \", (int) pahsc->pahsc_HWaveOut );"; z[lc++]="#endif"; z[lc++]="/* Free data and device for output. */"; z[lc++]=" if( pahsc->pahsc_HWaveOut )"; z[lc++]=" {"; z[lc++]=" if( pahsc->pahsc_OutputBuffers )"; z[lc++]=" {"; z[lc++]=" for( i=0; ipahsc_NumHostBuffers; i++ )"; z[lc++]=" {"; z[lc++]=" waveOutUnprepareHeader( pahsc->pahsc_HWaveOut, &pahsc->pahsc_OutputBuffers[i], sizeof(WAVEHDR) );"; z[lc++]=" GlobalFree( pahsc->pahsc_OutputBuffers[i].lpData ); /* MEM */"; z[lc++]=" }"; z[lc++]=" GlobalFree( pahsc->pahsc_OutputBuffers ); /* MEM */"; z[lc++]=" }"; z[lc++]=" waveOutClose( pahsc->pahsc_HWaveOut );"; z[lc++]=" }"; z[lc++]=" /* Free data and device for input. */"; z[lc++]=" if( pahsc->pahsc_HWaveIn )"; z[lc++]=" {"; z[lc++]=" if( pahsc->pahsc_InputBuffers )"; z[lc++]=" {"; z[lc++]=" for( i=0; ipahsc_NumHostBuffers; i++ )"; z[lc++]=" {"; z[lc++]=" waveInUnprepareHeader( pahsc->pahsc_HWaveIn, &pahsc->pahsc_InputBuffers[i], sizeof(WAVEHDR) );"; z[lc++]=" GlobalFree( pahsc->pahsc_InputBuffers[i].lpData ); /* MEM */"; z[lc++]=" }"; z[lc++]=" GlobalFree( pahsc->pahsc_InputBuffers ); /* MEM */"; z[lc++]=" }"; z[lc++]=" waveInClose( pahsc->pahsc_HWaveIn );"; z[lc++]=" }"; z[lc++]="#if (PA_USE_TIMER_CALLBACK == 0)"; z[lc++]=" if( pahsc->pahsc_AbortEventInited ) CloseHandle( pahsc->pahsc_AbortEvent );"; z[lc++]=" if( pahsc->pahsc_BufferEventInited ) CloseHandle( pahsc->pahsc_BufferEvent );"; z[lc++]="#endif"; z[lc++]=" if( pahsc->pahsc_StreamLockInited )"; z[lc++]=" DeleteCriticalSection( &pahsc->pahsc_StreamLock );"; z[lc++]=" PaHost_FreeFastMemory( pahsc, sizeof(PaHostSoundControl) ); /* MEM */"; z[lc++]=" past->past_DeviceData = NULL;"; z[lc++]=" return paNoError;"; z[lc++]="}"; z[lc++]="/*************************************************************************"; z[lc++]="** Determine minimum number of buffers required for this host based"; z[lc++]="** on minimum latency. Latency can be optionally set by user by setting"; z[lc++]="** an environment variable. For example, to set latency to 200 msec, put:"; z[lc++]="**"; z[lc++]="** set PA_MIN_LATENCY_MSEC=200"; z[lc++]="**"; z[lc++]="** in the AUTOEXEC.BAT file and reboot."; z[lc++]="** If the environment variable is not set, then the latency will be determined"; z[lc++]="** based on the OS. Windows NT has higher latency than Win95."; z[lc++]="*/"; z[lc++]="#define PA_LATENCY_ENV_NAME (\"PA_MIN_LATENCY_MSEC\")"; z[lc++]="int Pa_GetMinNumBuffers( int framesPerBuffer, double sampleRate )"; z[lc++]="{"; z[lc++]=" char envbuf[PA_ENV_BUF_SIZE];"; z[lc++]=" DWORD hostVersion;"; z[lc++]=" DWORD hresult;"; z[lc++]=" int minLatencyMsec = 0;"; z[lc++]=" double msecPerBuffer = (1000.0 * framesPerBuffer) / sampleRate;"; z[lc++]=" int minBuffers;"; z[lc++]="/* Let user determine minimal latency by setting environment variable. */"; z[lc++]=" hresult = GetEnvironmentVariable( PA_LATENCY_ENV_NAME, envbuf, PA_ENV_BUF_SIZE );"; z[lc++]=" if( (hresult > 0) && (hresult < PA_ENV_BUF_SIZE) )"; z[lc++]=" {"; z[lc++]=" minLatencyMsec = atoi( envbuf );"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]="/* Set minimal latency based on whether NT or Win95."; z[lc++]=" * NT has higher latency."; z[lc++]=" */"; z[lc++]=" hostVersion = GetVersion();"; z[lc++]="/* High bit clear if NT */"; z[lc++]=" minLatencyMsec = ( (hostVersion & 0x80000000) == 0 ) ? PA_WIN_NT_LATENCY : PA_WIN_9X_LATENCY ;"; z[lc++]="#if PA_USE_HIGH_LATENCY"; z[lc++]=" PRINT((\"PA - Minimum Latency set to %d msec!\\n\", minLatencyMsec ));"; z[lc++]="#endif"; z[lc++]=" }"; z[lc++]=" DBUG((\"PA - Minimum Latency set to %d msec!\\n\", minLatencyMsec ));"; z[lc++]=" minBuffers = (int) (1.0 + ((double)minLatencyMsec / msecPerBuffer));"; z[lc++]=" if( minBuffers < 2 ) minBuffers = 2;"; z[lc++]=" return minBuffers;"; z[lc++]="}"; z[lc++]="/*************************************************************************"; z[lc++]="** Cleanup device info."; z[lc++]="*/"; z[lc++]="PaError PaHost_Term( void )"; z[lc++]="{"; z[lc++]=" int i;"; z[lc++]=" if( sNumDevices > 0 ){"; z[lc++]=" if( sDevicePtrs != NULL ){"; z[lc++]=" for( i=0; idsw_CounterTicksPerBuffer.LowPart );"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" dsw->dsw_CounterTicksPerBuffer.QuadPart = 0;"; z[lc++]=" }"; z[lc++]="// Let DSound set the starting write position because if we set it to zero, it looks like the"; z[lc++]="// buffer is full to begin with. This causes a long pause before sound starts when using large buffers."; z[lc++]=" hr = IDirectSoundBuffer_GetCurrentPosition( dsw->dsw_OutputBuffer, &playCursor, &dsw->dsw_WriteOffset );"; z[lc++]=" if( hr != DS_OK )"; z[lc++]=" {"; z[lc++]=" return hr;"; z[lc++]=" }"; z[lc++]=" dsw->dsw_FramesWritten = dsw->dsw_WriteOffset / dsw->dsw_BytesPerFrame;"; z[lc++]=" /* printf(\"DSW_InitOutputBuffer: playCursor = %d, writeCursor = %d\\n\", playCursor, dsw->dsw_WriteOffset ); */"; z[lc++]=" return DS_OK;"; z[lc++]="}"; z[lc++]="/************************************************************************************/"; z[lc++]="HRESULT DSW_StartOutput( DSoundWrapper *dsw )"; z[lc++]="{"; z[lc++]=" HRESULT hr;"; z[lc++]=" QueryPerformanceCounter( &dsw->dsw_LastPlayTime );"; z[lc++]=" dsw->dsw_LastPlayCursor = 0;"; z[lc++]=" dsw->dsw_FramesPlayed = 0;"; z[lc++]=" hr = IDirectSoundBuffer_SetCurrentPosition( dsw->dsw_OutputBuffer, 0 );"; z[lc++]=" if( hr != DS_OK )"; z[lc++]=" {"; z[lc++]=" return hr;"; z[lc++]=" }"; z[lc++]="// Start the buffer playback in a loop."; z[lc++]=" if( dsw->dsw_OutputBuffer != NULL )"; z[lc++]=" {"; z[lc++]=" hr = IDirectSoundBuffer_Play( dsw->dsw_OutputBuffer, 0, 0, DSBPLAY_LOOPING );"; z[lc++]=" if( hr != DS_OK )"; z[lc++]=" {"; z[lc++]=" return hr;"; z[lc++]=" }"; z[lc++]=" dsw->dsw_OutputRunning = TRUE;"; z[lc++]=" }"; z[lc++]=" "; z[lc++]=" return 0;"; z[lc++]="}"; z[lc++]="/************************************************************************************/"; z[lc++]="HRESULT DSW_StopOutput( DSoundWrapper *dsw )"; z[lc++]="{"; z[lc++]="// Stop the buffer playback"; z[lc++]=" if( dsw->dsw_OutputBuffer != NULL )"; z[lc++]=" {"; z[lc++]=" dsw->dsw_OutputRunning = FALSE;"; z[lc++]=" return IDirectSoundBuffer_Stop( dsw->dsw_OutputBuffer );"; z[lc++]=" }"; z[lc++]=" else return 0;"; z[lc++]="}"; z[lc++]="/************************************************************************************/"; z[lc++]="HRESULT DSW_QueryOutputSpace( DSoundWrapper *dsw, long *bytesEmpty )"; z[lc++]="{"; z[lc++]=" HRESULT hr;"; z[lc++]=" DWORD playCursor;"; z[lc++]=" DWORD writeCursor;"; z[lc++]=" long numBytesEmpty;"; z[lc++]=" long playWriteGap;"; z[lc++]="// Query to see how much room is in buffer."; z[lc++]="// Note: Even though writeCursor is not used, it must be passed to prevent DirectSound from dieing"; z[lc++]="// under WinNT. The Microsoft documentation says we can pass NULL but apparently not."; z[lc++]="// Thanks to Max Rheiner for the fix."; z[lc++]=" hr = IDirectSoundBuffer_GetCurrentPosition( dsw->dsw_OutputBuffer, &playCursor, &writeCursor );"; z[lc++]=" if( hr != DS_OK )"; z[lc++]=" {"; z[lc++]=" return hr;"; z[lc++]=" }"; z[lc++]=" AddTraceMessage(\"playCursor\", playCursor);"; z[lc++]=" AddTraceMessage(\"dsw_WriteOffset\", dsw->dsw_WriteOffset);"; z[lc++]="// Determine size of gap between playIndex and WriteIndex that we cannot write into."; z[lc++]=" playWriteGap = writeCursor - playCursor;"; z[lc++]=" if( playWriteGap < 0 ) playWriteGap += dsw->dsw_OutputSize; // unwrap"; z[lc++]="/* DirectSound doesn't have a large enough playCursor so we cannot detect wrap-around. */"; z[lc++]="/* Attempt to detect playCursor wrap-around and correct it. */"; z[lc++]=" if( dsw->dsw_OutputRunning && (dsw->dsw_CounterTicksPerBuffer.QuadPart != 0) )"; z[lc++]=" {"; z[lc++]="/* How much time has elapsed since last check. */"; z[lc++]=" LARGE_INTEGER currentTime;"; z[lc++]=" LARGE_INTEGER elapsedTime;"; z[lc++]=" long bytesPlayed;"; z[lc++]=" long bytesExpected;"; z[lc++]=" long buffersWrapped;"; z[lc++]=" QueryPerformanceCounter( ¤tTime );"; z[lc++]=" elapsedTime.QuadPart = currentTime.QuadPart - dsw->dsw_LastPlayTime.QuadPart;"; z[lc++]=" dsw->dsw_LastPlayTime = currentTime;"; z[lc++]="/* How many bytes does DirectSound say have been played. */"; z[lc++]=" bytesPlayed = playCursor - dsw->dsw_LastPlayCursor;"; z[lc++]=" if( bytesPlayed < 0 ) bytesPlayed += dsw->dsw_OutputSize; // unwrap"; z[lc++]=" dsw->dsw_LastPlayCursor = playCursor;"; z[lc++]="/* Calculate how many bytes we would have expected to been played by now. */"; z[lc++]=" bytesExpected = (long) ((elapsedTime.QuadPart * dsw->dsw_OutputSize) / dsw->dsw_CounterTicksPerBuffer.QuadPart);"; z[lc++]=" buffersWrapped = (bytesExpected - bytesPlayed) / dsw->dsw_OutputSize;"; z[lc++]=" if( buffersWrapped > 0 )"; z[lc++]=" {"; z[lc++]=" AddTraceMessage(\"playCursor wrapped! bytesPlayed\", bytesPlayed );"; z[lc++]=" AddTraceMessage(\"playCursor wrapped! bytesExpected\", bytesExpected );"; z[lc++]=" playCursor += (buffersWrapped * dsw->dsw_OutputSize);"; z[lc++]=" bytesPlayed += (buffersWrapped * dsw->dsw_OutputSize);"; z[lc++]=" }"; z[lc++]=" /* Maintain frame output cursor. */"; z[lc++]=" dsw->dsw_FramesPlayed += (bytesPlayed / dsw->dsw_BytesPerFrame);"; z[lc++]=" }"; z[lc++]=" numBytesEmpty = playCursor - dsw->dsw_WriteOffset;"; z[lc++]=" if( numBytesEmpty < 0 ) numBytesEmpty += dsw->dsw_OutputSize; // unwrap offset"; z[lc++]="/* Have we underflowed? */"; z[lc++]=" if( numBytesEmpty > (dsw->dsw_OutputSize - playWriteGap) )"; z[lc++]=" {"; z[lc++]=" if( dsw->dsw_OutputRunning )"; z[lc++]=" {"; z[lc++]=" dsw->dsw_OutputUnderflows += 1;"; z[lc++]=" AddTraceMessage(\"underflow detected! numBytesEmpty\", numBytesEmpty );"; z[lc++]=" }"; z[lc++]=" dsw->dsw_WriteOffset = writeCursor;"; z[lc++]=" numBytesEmpty = dsw->dsw_OutputSize - playWriteGap;"; z[lc++]=" }"; z[lc++]=" *bytesEmpty = numBytesEmpty;"; z[lc++]=" return hr;"; z[lc++]="}"; z[lc++]="/************************************************************************************/"; z[lc++]="HRESULT DSW_ZeroEmptySpace( DSoundWrapper *dsw )"; z[lc++]="{"; z[lc++]=" HRESULT hr;"; z[lc++]=" LPBYTE lpbuf1 = NULL;"; z[lc++]=" LPBYTE lpbuf2 = NULL;"; z[lc++]=" DWORD dwsize1 = 0;"; z[lc++]=" DWORD dwsize2 = 0;"; z[lc++]=" long bytesEmpty;"; z[lc++]=" hr = DSW_QueryOutputSpace( dsw, &bytesEmpty ); // updates dsw_FramesPlayed"; z[lc++]=" if (hr != DS_OK) return hr;"; z[lc++]=" if( bytesEmpty == 0 ) return DS_OK;"; z[lc++]=" // Lock free space in the DS"; z[lc++]=" hr = IDirectSoundBuffer_Lock( dsw->dsw_OutputBuffer, dsw->dsw_WriteOffset, bytesEmpty, (void **) &lpbuf1, &dwsize1,"; z[lc++]=" (void **) &lpbuf2, &dwsize2, 0);"; z[lc++]=" if (hr == DS_OK)"; z[lc++]=" {"; z[lc++]=" // Copy the buffer into the DS"; z[lc++]=" ZeroMemory(lpbuf1, dwsize1);"; z[lc++]=" if(lpbuf2 != NULL)"; z[lc++]=" {"; z[lc++]=" ZeroMemory(lpbuf2, dwsize2);"; z[lc++]=" }"; z[lc++]=" // Update our buffer offset and unlock sound buffer"; z[lc++]=" dsw->dsw_WriteOffset = (dsw->dsw_WriteOffset + dwsize1 + dwsize2) % dsw->dsw_OutputSize;"; z[lc++]=" IDirectSoundBuffer_Unlock( dsw->dsw_OutputBuffer, lpbuf1, dwsize1, lpbuf2, dwsize2);"; z[lc++]=" dsw->dsw_FramesWritten += bytesEmpty / dsw->dsw_BytesPerFrame;"; z[lc++]=" }"; z[lc++]=" return hr;"; z[lc++]="}"; z[lc++]="/************************************************************************************/"; z[lc++]="HRESULT DSW_WriteBlock( DSoundWrapper *dsw, char *buf, long numBytes )"; z[lc++]="{"; z[lc++]=" HRESULT hr;"; z[lc++]=" LPBYTE lpbuf1 = NULL;"; z[lc++]=" LPBYTE lpbuf2 = NULL;"; z[lc++]=" DWORD dwsize1 = 0;"; z[lc++]=" DWORD dwsize2 = 0;"; z[lc++]=" // Lock free space in the DS"; z[lc++]=" hr = IDirectSoundBuffer_Lock( dsw->dsw_OutputBuffer, dsw->dsw_WriteOffset, numBytes, (void **) &lpbuf1, &dwsize1,"; z[lc++]=" (void **) &lpbuf2, &dwsize2, 0);"; z[lc++]=" if (hr == DS_OK)"; z[lc++]=" {"; z[lc++]=" // Copy the buffer into the DS"; z[lc++]=" CopyMemory(lpbuf1, buf, dwsize1);"; z[lc++]=" if(lpbuf2 != NULL)"; z[lc++]=" {"; z[lc++]=" CopyMemory(lpbuf2, buf+dwsize1, dwsize2);"; z[lc++]=" }"; z[lc++]=" // Update our buffer offset and unlock sound buffer"; z[lc++]=" dsw->dsw_WriteOffset = (dsw->dsw_WriteOffset + dwsize1 + dwsize2) % dsw->dsw_OutputSize;"; z[lc++]=" IDirectSoundBuffer_Unlock( dsw->dsw_OutputBuffer, lpbuf1, dwsize1, lpbuf2, dwsize2);"; z[lc++]=" dsw->dsw_FramesWritten += numBytes / dsw->dsw_BytesPerFrame;"; z[lc++]=" }"; z[lc++]=" return hr;"; z[lc++]="}"; z[lc++]="/************************************************************************************/"; z[lc++]="DWORD DSW_GetOutputStatus( DSoundWrapper *dsw )"; z[lc++]="{"; z[lc++]=" DWORD status;"; z[lc++]=" if (IDirectSoundBuffer_GetStatus( dsw->dsw_OutputBuffer, &status ) != DS_OK)"; z[lc++]=" return( DSERR_INVALIDPARAM );"; z[lc++]=" else"; z[lc++]=" return( status );"; z[lc++]="}"; z[lc++]="#if SUPPORT_AUDIO_CAPTURE"; z[lc++]="/* These routines are used to support audio input."; z[lc++]=" * Do NOT compile these calls when using NT4 because it does"; z[lc++]=" * not support the entry points."; z[lc++]=" */"; z[lc++]="/************************************************************************************/"; z[lc++]="HRESULT DSW_InitInputDevice( DSoundWrapper *dsw, LPGUID lpGUID )"; z[lc++]="{"; z[lc++]=" HRESULT hr = DirectSoundCaptureCreate( lpGUID, &dsw->dsw_pDirectSoundCapture, NULL );"; z[lc++]=" if( hr != DS_OK ) return hr;"; z[lc++]=" return hr;"; z[lc++]="}"; z[lc++]="/************************************************************************************/"; z[lc++]="HRESULT DSW_InitInputBuffer( DSoundWrapper *dsw, unsigned long nFrameRate, int nChannels, int bytesPerBuffer )"; z[lc++]="{"; z[lc++]=" DSCBUFFERDESC captureDesc;"; z[lc++]=" WAVEFORMATEX wfFormat;"; z[lc++]=" HRESULT result;"; z[lc++]="// Define the buffer format"; z[lc++]=" wfFormat.wFormatTag = WAVE_FORMAT_PCM;"; z[lc++]=" wfFormat.nChannels = nChannels;"; z[lc++]=" wfFormat.nSamplesPerSec = nFrameRate;"; z[lc++]=" wfFormat.wBitsPerSample = 8 * sizeof(short);"; z[lc++]=" wfFormat.nBlockAlign = wfFormat.nChannels * (wfFormat.wBitsPerSample / 8);"; z[lc++]=" wfFormat.nAvgBytesPerSec = wfFormat.nSamplesPerSec * wfFormat.nBlockAlign;"; z[lc++]=" wfFormat.cbSize = 0; /* No extended format info. */"; z[lc++]=" dsw->dsw_InputSize = bytesPerBuffer;"; z[lc++]="// ----------------------------------------------------------------------"; z[lc++]="// Setup the secondary buffer description"; z[lc++]=" ZeroMemory(&captureDesc, sizeof(DSCBUFFERDESC));"; z[lc++]=" captureDesc.dwSize = sizeof(DSCBUFFERDESC);"; z[lc++]=" captureDesc.dwFlags = 0;"; z[lc++]=" captureDesc.dwBufferBytes = bytesPerBuffer;"; z[lc++]=" captureDesc.lpwfxFormat = &wfFormat;"; z[lc++]=" // Create the capture buffer"; z[lc++]=" if ((result = IDirectSoundCapture_CreateCaptureBuffer( dsw->dsw_pDirectSoundCapture,"; z[lc++]=" &captureDesc, &dsw->dsw_InputBuffer, NULL)) != DS_OK) return result;"; z[lc++]=" dsw->dsw_ReadOffset = 0; // reset last read position to start of buffer"; z[lc++]=" return DS_OK;"; z[lc++]="}"; z[lc++]="/************************************************************************************/"; z[lc++]="HRESULT DSW_StartInput( DSoundWrapper *dsw )"; z[lc++]="{"; z[lc++]="// Start the buffer playback"; z[lc++]=" if( dsw->dsw_InputBuffer != NULL )"; z[lc++]=" {"; z[lc++]=" return IDirectSoundCaptureBuffer_Start( dsw->dsw_InputBuffer, DSCBSTART_LOOPING );"; z[lc++]=" }"; z[lc++]=" else return 0;"; z[lc++]="}"; z[lc++]="/************************************************************************************/"; z[lc++]="HRESULT DSW_StopInput( DSoundWrapper *dsw )"; z[lc++]="{"; z[lc++]="// Stop the buffer playback"; z[lc++]=" if( dsw->dsw_InputBuffer != NULL )"; z[lc++]=" {"; z[lc++]=" return IDirectSoundCaptureBuffer_Stop( dsw->dsw_InputBuffer );"; z[lc++]=" }"; z[lc++]=" else return 0;"; z[lc++]="}"; z[lc++]="/************************************************************************************/"; z[lc++]="HRESULT DSW_QueryInputFilled( DSoundWrapper *dsw, long *bytesFilled )"; z[lc++]="{"; z[lc++]=" HRESULT hr;"; z[lc++]=" DWORD capturePos;"; z[lc++]=" DWORD readPos;"; z[lc++]=" long filled;"; z[lc++]="// Query to see how much data is in buffer."; z[lc++]="// We don't need the capture position but sometimes DirectSound doesn't handle NULLS correctly"; z[lc++]="// so let's pass a pointer just to be safe."; z[lc++]=" hr = IDirectSoundCaptureBuffer_GetCurrentPosition( dsw->dsw_InputBuffer, &capturePos, &readPos );"; z[lc++]=" if( hr != DS_OK )"; z[lc++]=" {"; z[lc++]=" return hr;"; z[lc++]=" }"; z[lc++]=" filled = readPos - dsw->dsw_ReadOffset;"; z[lc++]=" if( filled < 0 ) filled += dsw->dsw_InputSize; // unwrap offset"; z[lc++]=" *bytesFilled = filled;"; z[lc++]=" return hr;"; z[lc++]="}"; z[lc++]="/************************************************************************************/"; z[lc++]="HRESULT DSW_ReadBlock( DSoundWrapper *dsw, char *buf, long numBytes )"; z[lc++]="{"; z[lc++]=" HRESULT hr;"; z[lc++]=" LPBYTE lpbuf1 = NULL;"; z[lc++]=" LPBYTE lpbuf2 = NULL;"; z[lc++]=" DWORD dwsize1 = 0;"; z[lc++]=" DWORD dwsize2 = 0;"; z[lc++]=" // Lock free space in the DS"; z[lc++]=" hr = IDirectSoundCaptureBuffer_Lock ( dsw->dsw_InputBuffer, dsw->dsw_ReadOffset, numBytes, (void **) &lpbuf1, &dwsize1,"; z[lc++]=" (void **) &lpbuf2, &dwsize2, 0);"; z[lc++]=" if (hr == DS_OK)"; z[lc++]=" {"; z[lc++]=" // Copy from DS to the buffer"; z[lc++]=" CopyMemory( buf, lpbuf1, dwsize1);"; z[lc++]=" if(lpbuf2 != NULL)"; z[lc++]=" {"; z[lc++]=" CopyMemory( buf+dwsize1, lpbuf2, dwsize2);"; z[lc++]=" }"; z[lc++]=" // Update our buffer offset and unlock sound buffer"; z[lc++]=" dsw->dsw_ReadOffset = (dsw->dsw_ReadOffset + dwsize1 + dwsize2) % dsw->dsw_InputSize;"; z[lc++]=" IDirectSoundCaptureBuffer_Unlock ( dsw->dsw_InputBuffer, lpbuf1, dwsize1, lpbuf2, dwsize2);"; z[lc++]=" }"; z[lc++]=" return hr;"; z[lc++]="}"; z[lc++]="#endif /* SUPPORT_AUDIO_CAPTURE */"; printlib(lc); } void makepa_dsound(void) { int lc = 0; z[lc++]="/*"; z[lc++]=" * PortAudio Portable Real-Time Audio Library"; z[lc++]=" * Latest Version at: http://www.softsynth.com/portaudio/"; z[lc++]=" * DirectSound Implementation"; z[lc++]=" *"; z[lc++]=" * Copyright (c) 1999-2000 Phil Burk"; z[lc++]=" *"; z[lc++]=" * Permission is hereby granted, free of charge, to any person obtaining"; z[lc++]=" * a copy of this software and associated documentation files"; z[lc++]=" * (the \"Software\"), to deal in the Software without restriction,"; z[lc++]=" * including without limitation the rights to use, copy, modify, merge,"; z[lc++]=" * publish, distribute, sublicense, and/or sell copies of the Software,"; z[lc++]=" * and to permit persons to whom the Software is furnished to do so,"; z[lc++]=" * subject to the following conditions:"; z[lc++]=" *"; z[lc++]=" * The above copyright notice and this permission notice shall be"; z[lc++]=" * included in all copies or substantial portions of the Software."; z[lc++]=" *"; z[lc++]=" * Any person wishing to distribute modifications to the Software is"; z[lc++]=" * requested to send the modifications to the original developer so that"; z[lc++]=" * they can be incorporated into the canonical version."; z[lc++]=" *"; z[lc++]=" * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,"; z[lc++]=" * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF"; z[lc++]=" * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT."; z[lc++]=" * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR"; z[lc++]=" * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF"; z[lc++]=" * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION"; z[lc++]=" * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."; z[lc++]=" *"; z[lc++]=" */"; z[lc++]="/* Modifications"; z[lc++]=" * 7/19/01 Mike Berry - casts for compiling with __MWERKS__ CodeWarrior"; z[lc++]=" * 9/27/01 Phil Burk - use number of frames instead of real-time for CPULoad calculation."; z[lc++]=" */"; z[lc++]="/* Compiler flags:"; z[lc++]=" SUPPORT_AUDIO_CAPTURE - define this flag if you want to SUPPORT_AUDIO_CAPTURE"; z[lc++]=" */"; z[lc++]="#include "; z[lc++]="#include "; z[lc++]="#ifndef __MWERKS__"; z[lc++]="#include "; z[lc++]="#include "; z[lc++]="#endif //__MWERKS__"; z[lc++]="#include "; z[lc++]="#if 0"; z[lc++]="#include \"portaudio.h\""; z[lc++]="#include \"pa_host.h\""; z[lc++]="#include \"pa_trace.h\""; z[lc++]="#include \"dsound_wrapper.h\""; z[lc++]="#endif"; z[lc++]="#define PRINT(x) { printf x; fflush(stdout); }"; z[lc++]="#define ERR_RPT(x) PRINT(x)"; z[lc++]="#define DBUG(x) /* PRINT(x) */"; z[lc++]="#define DBUGX(x) /* PRINT(x) */"; z[lc++]="#define PA_USE_HIGH_LATENCY (0)"; z[lc++]="#if PA_USE_HIGH_LATENCY"; z[lc++]="#define PA_WIN_9X_LATENCY (500)"; z[lc++]="#define PA_WIN_NT_LATENCY (600)"; z[lc++]="#else"; z[lc++]="#define PA_WIN_9X_LATENCY (140)"; z[lc++]="#define PA_WIN_NT_LATENCY (280)"; z[lc++]="#endif"; z[lc++]="/* Trigger an underflow for testing purposes. Should normally be (0). */"; z[lc++]="#define PA_SIMULATE_UNDERFLOW (0)"; z[lc++]="#if PA_SIMULATE_UNDERFLOW"; z[lc++]="static gUnderCallbackCounter = 0;"; z[lc++]="#define UNDER_START_GAP (10)"; z[lc++]="#define UNDER_STOP_GAP (UNDER_START_GAP + 4)"; z[lc++]="#endif"; z[lc++]="/************************************************* Definitions ********/"; z[lc++]="typedef struct internalPortAudioStream internalPortAudioStream;"; z[lc++]="typedef struct internalPortAudioDevice"; z[lc++]="{"; z[lc++]=" GUID pad_GUID;"; z[lc++]=" GUID *pad_lpGUID;"; z[lc++]=" double pad_SampleRates[10]; /* for pointing to from pad_Info FIXME?!*/"; z[lc++]=" PaDeviceInfo pad_Info;"; z[lc++]="} internalPortAudioDevice;"; z[lc++]="/* Define structure to contain all DirectSound and Windows specific data. */"; z[lc++]="typedef struct PaHostSoundControl"; z[lc++]="{"; z[lc++]=" DSoundWrapper pahsc_DSoundWrapper;"; z[lc++]=" MMRESULT pahsc_TimerID;"; z[lc++]=" BOOL pahsc_IfInsideCallback; /* Test for reentrancy. */"; z[lc++]=" short *pahsc_NativeBuffer;"; z[lc++]=" unsigned int pahsc_BytesPerBuffer; /* native buffer size in bytes */"; z[lc++]=" double pahsc_ValidFramesWritten;"; z[lc++]=" int pahsc_FramesPerDSBuffer;"; z[lc++]="/* For measuring CPU utilization. */"; z[lc++]=" LARGE_INTEGER pahsc_EntryCount;"; z[lc++]=" double pahsc_InverseTicksPerUserBuffer;"; z[lc++]="} PaHostSoundControl;"; z[lc++]="/************************************************* Shared Data ********/"; z[lc++]="/* FIXME - put Mutex around this shared data. */"; z[lc++]="static int sNumDevices = 0;"; z[lc++]="static int sDeviceIndex = 0;"; z[lc++]="static internalPortAudioDevice *sDevices = NULL;"; z[lc++]="static int sDefaultInputDeviceID = paNoDevice;"; z[lc++]="static int sDefaultOutputDeviceID = paNoDevice;"; z[lc++]="static int sEnumerationError;"; z[lc++]="static int sPaHostError = 0;"; z[lc++]="/************************************************* Prototypes **********/"; z[lc++]="static internalPortAudioDevice *Pa_GetInternalDevice( PaDeviceID id );"; z[lc++]="static BOOL CALLBACK Pa_EnumProc(LPGUID lpGUID, "; z[lc++]=" LPCTSTR lpszDesc,"; z[lc++]=" LPCTSTR lpszDrvName, "; z[lc++]=" LPVOID lpContext );"; z[lc++]="static BOOL CALLBACK Pa_CountDevProc(LPGUID lpGUID, "; z[lc++]=" LPCTSTR lpszDesc,"; z[lc++]=" LPCTSTR lpszDrvName, "; z[lc++]=" LPVOID lpContext );"; z[lc++]="static Pa_QueryDevices( void );"; z[lc++]="static void CALLBACK Pa_TimerCallback(UINT uID, UINT uMsg,"; z[lc++]=" DWORD dwUser, DWORD dw1, DWORD dw2);"; z[lc++]="/********************************* BEGIN CPU UTILIZATION MEASUREMENT ****/"; z[lc++]="static void Pa_StartUsageCalculation( internalPortAudioStream *past )"; z[lc++]="{"; z[lc++]=" PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData;"; z[lc++]=" if( pahsc == NULL ) return;"; z[lc++]="/* Query system timer for usage analysis and to prevent overuse of CPU. */"; z[lc++]=" QueryPerformanceCounter( &pahsc->pahsc_EntryCount );"; z[lc++]="}"; z[lc++]="static void Pa_EndUsageCalculation( internalPortAudioStream *past )"; z[lc++]="{"; z[lc++]=" LARGE_INTEGER CurrentCount = { 0, 0 };"; z[lc++]=" PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData;"; z[lc++]=" if( pahsc == NULL ) return;"; z[lc++]="/*"; z[lc++]="** Measure CPU utilization during this callback. Note that this calculation"; z[lc++]="** assumes that we had the processor the whole time."; z[lc++]="*/"; z[lc++]="#define LOWPASS_COEFFICIENT_0 (0.9)"; z[lc++]="#define LOWPASS_COEFFICIENT_1 (0.99999 - LOWPASS_COEFFICIENT_0)"; z[lc++]=" if( QueryPerformanceCounter( &CurrentCount ) )"; z[lc++]=" {"; z[lc++]=" LONGLONG InsideCount = CurrentCount.QuadPart - pahsc->pahsc_EntryCount.QuadPart; "; z[lc++]=" double newUsage = InsideCount * pahsc->pahsc_InverseTicksPerUserBuffer;"; z[lc++]=" past->past_Usage = (LOWPASS_COEFFICIENT_0 * past->past_Usage) +"; z[lc++]=" (LOWPASS_COEFFICIENT_1 * newUsage);"; z[lc++]=" }"; z[lc++]="}"; z[lc++]="/****************************************** END CPU UTILIZATION *******/"; z[lc++]="static PaError Pa_QueryDevices( void )"; z[lc++]="{"; z[lc++]=" int numBytes;"; z[lc++]=" sDefaultInputDeviceID = paNoDevice;"; z[lc++]=" sDefaultOutputDeviceID = paNoDevice;"; z[lc++]="/* Enumerate once just to count devices. */"; z[lc++]=" sNumDevices = 0; // for default device"; z[lc++]=" DirectSoundEnumerate( (LPDSENUMCALLBACK)Pa_CountDevProc, NULL );"; z[lc++]="#if SUPPORT_AUDIO_CAPTURE"; z[lc++]=" DirectSoundCaptureEnumerate( (LPDSENUMCALLBACK)Pa_CountDevProc, NULL );"; z[lc++]="#endif /* SUPPORT_AUDIO_CAPTURE */"; z[lc++]="/* Allocate structures to hold device info. */"; z[lc++]=" numBytes = sNumDevices * sizeof(internalPortAudioDevice);"; z[lc++]=" sDevices = (internalPortAudioDevice *)PaHost_AllocateFastMemory( numBytes ); /* MEM */"; z[lc++]=" if( sDevices == NULL ) return paInsufficientMemory;"; z[lc++]="/* Enumerate again to fill in structures. */"; z[lc++]=" sDeviceIndex = 0;"; z[lc++]=" sEnumerationError = 0;"; z[lc++]=" DirectSoundEnumerate( (LPDSENUMCALLBACK)Pa_EnumProc, (void *)0 );"; z[lc++]="#if SUPPORT_AUDIO_CAPTURE"; z[lc++]=" if( sEnumerationError != paNoError ) return sEnumerationError;"; z[lc++]=" sEnumerationError = 0;"; z[lc++]=" DirectSoundCaptureEnumerate( (LPDSENUMCALLBACK)Pa_EnumProc, (void *)1 );"; z[lc++]="#endif /* SUPPORT_AUDIO_CAPTURE */"; z[lc++]=" return sEnumerationError;"; z[lc++]="}"; z[lc++]="/************************************************************************************/"; z[lc++]="long Pa_GetHostError()"; z[lc++]="{"; z[lc++]=" return sPaHostError;"; z[lc++]="}"; z[lc++]="/************************************************************************************"; z[lc++]="** Just count devices so we know how much memory to allocate."; z[lc++]="*/"; z[lc++]="static BOOL CALLBACK Pa_CountDevProc(LPGUID lpGUID, "; z[lc++]=" LPCTSTR lpszDesc,"; z[lc++]=" LPCTSTR lpszDrvName, "; z[lc++]=" LPVOID lpContext )"; z[lc++]="{"; z[lc++]=" sNumDevices++;"; z[lc++]=" return TRUE;"; z[lc++]="}"; z[lc++]="/************************************************************************************"; z[lc++]="** Extract capabilities info from each device."; z[lc++]="*/"; z[lc++]="static BOOL CALLBACK Pa_EnumProc(LPGUID lpGUID, "; z[lc++]=" LPCTSTR lpszDesc,"; z[lc++]=" LPCTSTR lpszDrvName, "; z[lc++]=" LPVOID lpContext )"; z[lc++]="{"; z[lc++]=" HRESULT hr;"; z[lc++]=" LPDIRECTSOUND lpDirectSound;"; z[lc++]="#if SUPPORT_AUDIO_CAPTURE"; z[lc++]=" LPDIRECTSOUNDCAPTURE lpDirectSoundCapture;"; z[lc++]="#endif /* SUPPORT_AUDIO_CAPTURE */"; z[lc++]=" int isInput = (int) lpContext; /* Passed from Pa_CountDevices() */"; z[lc++]=" internalPortAudioDevice *pad;"; z[lc++]=" "; z[lc++]=" if( sDeviceIndex >= sNumDevices )"; z[lc++]=" {"; z[lc++]=" sEnumerationError = paInternalError;"; z[lc++]=" return FALSE;"; z[lc++]=" }"; z[lc++]=" pad = &sDevices[sDeviceIndex];"; z[lc++]="/* Copy GUID to static array. Set pointer. */"; z[lc++]=" if( lpGUID == NULL )"; z[lc++]=" {"; z[lc++]=" pad->pad_lpGUID = NULL;"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" memcpy( &pad->pad_GUID, lpGUID, sizeof(GUID) );"; z[lc++]=" pad->pad_lpGUID = &pad->pad_GUID;"; z[lc++]=" }"; z[lc++]=" pad->pad_Info.sampleRates = pad->pad_SampleRates; /* Point to array. */"; z[lc++]="/* Allocate room for descriptive name. */"; z[lc++]=" if( lpszDesc != NULL )"; z[lc++]=" {"; z[lc++]=" int len = strlen(lpszDesc);"; z[lc++]=" pad->pad_Info.name = (char *)malloc( len+1 );"; z[lc++]=" if( pad->pad_Info.name == NULL )"; z[lc++]=" {"; z[lc++]=" sEnumerationError = paInsufficientMemory;"; z[lc++]=" return FALSE;"; z[lc++]=" }"; z[lc++]=" memcpy( (void *) pad->pad_Info.name, lpszDesc, len+1 );"; z[lc++]=" }"; z[lc++]="#if SUPPORT_AUDIO_CAPTURE"; z[lc++]=" if( isInput )"; z[lc++]=" {"; z[lc++]=" /********** Input ******************************/"; z[lc++]=" DSCCAPS caps;"; z[lc++]=" if( lpGUID == NULL ) sDefaultInputDeviceID = sDeviceIndex;"; z[lc++]=" hr = DirectSoundCaptureCreate( lpGUID, &lpDirectSoundCapture, NULL );"; z[lc++]=" if( hr != DS_OK )"; z[lc++]=" {"; z[lc++]=" pad->pad_Info.maxInputChannels = 0;"; z[lc++]=" DBUG((\"Cannot create Capture for %s. Result = 0x%x\\n\", lpszDesc, hr ));"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" /* Query device characteristics. */"; z[lc++]=" caps.dwSize = sizeof(caps);"; z[lc++]=" IDirectSoundCapture_GetCaps( lpDirectSoundCapture, &caps );"; z[lc++]=" /* printf(\"caps.dwFormats = 0x%x\\n\", caps.dwFormats ); */"; z[lc++]=" pad->pad_Info.maxInputChannels = caps.dwChannels;"; z[lc++]=" /* Determine sample rates from flags. */"; z[lc++]=" if( caps.dwChannels == 2 )"; z[lc++]=" {"; z[lc++]=" int index = 0;"; z[lc++]=" if( caps.dwFormats & WAVE_FORMAT_1S16) pad->pad_SampleRates[index++] = 11025.0;"; z[lc++]=" if( caps.dwFormats & WAVE_FORMAT_2S16) pad->pad_SampleRates[index++] = 22050.0;"; z[lc++]=" if( caps.dwFormats & WAVE_FORMAT_4S16) pad->pad_SampleRates[index++] = 44100.0;"; z[lc++]=" pad->pad_Info.numSampleRates = index;"; z[lc++]=" }"; z[lc++]=" else if( caps.dwChannels == 1 )"; z[lc++]=" {"; z[lc++]=" int index = 0;"; z[lc++]=" if( caps.dwFormats & WAVE_FORMAT_1M16) pad->pad_SampleRates[index++] = 11025.0;"; z[lc++]=" if( caps.dwFormats & WAVE_FORMAT_2M16) pad->pad_SampleRates[index++] = 22050.0;"; z[lc++]=" if( caps.dwFormats & WAVE_FORMAT_4M16) pad->pad_SampleRates[index++] = 44100.0;"; z[lc++]=" pad->pad_Info.numSampleRates = index;"; z[lc++]=" }"; z[lc++]=" else pad->pad_Info.numSampleRates = 0;"; z[lc++]=" IDirectSoundCapture_Release( lpDirectSoundCapture );"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]="#endif /* SUPPORT_AUDIO_CAPTURE */"; z[lc++]=" {"; z[lc++]=" /********** Output ******************************/"; z[lc++]=" DSCAPS caps;"; z[lc++]=" if( lpGUID == NULL ) sDefaultOutputDeviceID = sDeviceIndex;"; z[lc++]=" /* Create interfaces for each object. */"; z[lc++]=" hr = DirectSoundCreate( lpGUID, &lpDirectSound, NULL );"; z[lc++]=" if( hr != DS_OK )"; z[lc++]=" {"; z[lc++]=" pad->pad_Info.maxOutputChannels = 0;"; z[lc++]=" DBUG((\"Cannot create dsound for %s. Result = 0x%x\\n\", lpszDesc, hr ));"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" /* Query device characteristics. */"; z[lc++]=" caps.dwSize = sizeof(caps);"; z[lc++]=" IDirectSound_GetCaps( lpDirectSound, &caps );"; z[lc++]=" pad->pad_Info.maxOutputChannels = ( caps.dwFlags & DSCAPS_PRIMARYSTEREO ) ? 2 : 1;"; z[lc++]=" /* Get sample rates. */"; z[lc++]=" pad->pad_SampleRates[0] = (double) caps.dwMinSecondarySampleRate;"; z[lc++]=" pad->pad_SampleRates[1] = (double) caps.dwMaxSecondarySampleRate;"; z[lc++]=" if( caps.dwFlags & DSCAPS_CONTINUOUSRATE ) pad->pad_Info.numSampleRates = -1;"; z[lc++]=" else if( caps.dwMinSecondarySampleRate == caps.dwMaxSecondarySampleRate )"; z[lc++]=" {"; z[lc++]=" if( caps.dwMinSecondarySampleRate == 0 )"; z[lc++]=" {"; z[lc++]=" /*"; z[lc++]=" ** On my Thinkpad 380Z, DirectSoundV6 returns min-max=0 !!"; z[lc++]=" ** But it supports continuous sampling."; z[lc++]=" ** So fake range of rates, and hope it really supports it."; z[lc++]=" */"; z[lc++]=" pad->pad_SampleRates[0] = 11025.0f;"; z[lc++]=" pad->pad_SampleRates[1] = 48000.0f;"; z[lc++]=" pad->pad_Info.numSampleRates = -1; /* continuous range */"; z[lc++]=" "; z[lc++]=" DBUG((\"PA - Reported rates both zero. Setting to fake values for device #%d\\n\", sDeviceIndex ));"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" pad->pad_Info.numSampleRates = 1;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else if( (caps.dwMinSecondarySampleRate < 1000.0) && (caps.dwMaxSecondarySampleRate > 50000.0) )"; z[lc++]=" {"; z[lc++]=" /* The EWS88MT drivers lie, lie, lie. The say they only support two rates, 100 & 100000."; z[lc++]=" ** But we know that they really support a range of rates!"; z[lc++]=" ** So when we see a ridiculous set of rates, assume it is a range."; z[lc++]=" */"; z[lc++]=" pad->pad_Info.numSampleRates = -1;"; z[lc++]=" DBUG((\"PA - Sample rate range used instead of two odd values for device #%d\\n\", sDeviceIndex ));"; z[lc++]=" }"; z[lc++]=" else pad->pad_Info.numSampleRates = 2;"; z[lc++]=" IDirectSound_Release( lpDirectSound );"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" pad->pad_Info.nativeSampleFormats = paInt16;"; z[lc++]=" sDeviceIndex++;"; z[lc++]=" return( TRUE );"; z[lc++]="}"; z[lc++]="/*************************************************************************/"; z[lc++]="int Pa_CountDevices()"; z[lc++]="{"; z[lc++]=" if( sNumDevices <= 0 ) Pa_Initialize();"; z[lc++]=" return sNumDevices;"; z[lc++]="}"; z[lc++]="static internalPortAudioDevice *Pa_GetInternalDevice( PaDeviceID id )"; z[lc++]="{"; z[lc++]=" if( (id < 0) || ( id >= Pa_CountDevices()) ) return NULL;"; z[lc++]=" return &sDevices[id];"; z[lc++]="}"; z[lc++]="/*************************************************************************/"; z[lc++]="const PaDeviceInfo* Pa_GetDeviceInfo( PaDeviceID id )"; z[lc++]="{"; z[lc++]=" internalPortAudioDevice *pad;"; z[lc++]=" if( (id < 0) || ( id >= Pa_CountDevices()) ) return NULL;"; z[lc++]=" pad = Pa_GetInternalDevice( id );"; z[lc++]=" return &pad->pad_Info ;"; z[lc++]="}"; z[lc++]="static PaError Pa_MaybeQueryDevices( void )"; z[lc++]="{"; z[lc++]=" if( sNumDevices == 0 )"; z[lc++]=" {"; z[lc++]=" return Pa_QueryDevices();"; z[lc++]=" }"; z[lc++]=" return 0;"; z[lc++]="}"; z[lc++]="/*************************************************************************"; z[lc++]="** Returns recommended device ID."; z[lc++]="** On the PC, the recommended device can be specified by the user by"; z[lc++]="** setting an environment variable. For example, to use device #1."; z[lc++]="**"; z[lc++]="** set PA_RECOMMENDED_OUTPUT_DEVICE=1"; z[lc++]="**"; z[lc++]="** The user should first determine the available device ID by using"; z[lc++]="** the supplied application \"pa_devs\"."; z[lc++]="*/"; z[lc++]="#define PA_ENV_BUF_SIZE (32)"; z[lc++]="#define PA_REC_IN_DEV_ENV_NAME (\"PA_RECOMMENDED_INPUT_DEVICE\")"; z[lc++]="#define PA_REC_OUT_DEV_ENV_NAME (\"PA_RECOMMENDED_OUTPUT_DEVICE\")"; z[lc++]="static PaDeviceID PaHost_GetEnvDefaultDeviceID( char *envName )"; z[lc++]="{"; z[lc++]=" DWORD hresult;"; z[lc++]=" char envbuf[PA_ENV_BUF_SIZE];"; z[lc++]=" PaDeviceID recommendedID = paNoDevice;"; z[lc++]="/* Let user determine default device by setting environment variable. */"; z[lc++]=" hresult = GetEnvironmentVariable( envName, envbuf, PA_ENV_BUF_SIZE );"; z[lc++]=" if( (hresult > 0) && (hresult < PA_ENV_BUF_SIZE) )"; z[lc++]=" {"; z[lc++]=" recommendedID = atoi( envbuf );"; z[lc++]=" }"; z[lc++]=" return recommendedID;"; z[lc++]="}"; z[lc++]="PaDeviceID Pa_GetDefaultInputDeviceID( void )"; z[lc++]="{"; z[lc++]=" PaError result;"; z[lc++]=" result = PaHost_GetEnvDefaultDeviceID( PA_REC_IN_DEV_ENV_NAME );"; z[lc++]=" if( result < 0 )"; z[lc++]=" {"; z[lc++]=" result = Pa_MaybeQueryDevices();"; z[lc++]=" if( result < 0 ) return result;"; z[lc++]=" result = sDefaultInputDeviceID;"; z[lc++]=" }"; z[lc++]=" return result;"; z[lc++]="}"; z[lc++]="PaDeviceID Pa_GetDefaultOutputDeviceID( void )"; z[lc++]="{"; z[lc++]=" PaError result;"; z[lc++]=" result = PaHost_GetEnvDefaultDeviceID( PA_REC_OUT_DEV_ENV_NAME );"; z[lc++]=" if( result < 0 )"; z[lc++]=" {"; z[lc++]=" result = Pa_MaybeQueryDevices();"; z[lc++]=" if( result < 0 ) return result;"; z[lc++]=" result = sDefaultOutputDeviceID;"; z[lc++]=" }"; z[lc++]=" return result;"; z[lc++]="}"; z[lc++]="/**********************************************************************"; z[lc++]="** Make sure that we have queried the device capabilities."; z[lc++]="*/"; z[lc++]="PaError PaHost_Init( void )"; z[lc++]="{"; z[lc++]="#if PA_SIMULATE_UNDERFLOW"; z[lc++]=" PRINT((\"WARNING - Underflow Simulation Enabled - Expect a Big Glitch!!!\\n\"));"; z[lc++]="#endif"; z[lc++]=" return Pa_MaybeQueryDevices();"; z[lc++]="}"; z[lc++]="static PaError Pa_TimeSlice( internalPortAudioStream *past )"; z[lc++]="{"; z[lc++]=" PaError result = 0;"; z[lc++]=" long bytesEmpty = 0;"; z[lc++]=" long bytesFilled = 0;"; z[lc++]=" long bytesToXfer = 0;"; z[lc++]=" long numChunks;"; z[lc++]=" HRESULT hresult;"; z[lc++]=" PaHostSoundControl *pahsc;"; z[lc++]=" short *nativeBufPtr;"; z[lc++]=" past->past_NumCallbacks += 1;"; z[lc++]=" pahsc = (PaHostSoundControl *) past->past_DeviceData;"; z[lc++]=" if( pahsc == NULL ) return paInternalError;"; z[lc++]="/* How much input data is available? */"; z[lc++]="#if SUPPORT_AUDIO_CAPTURE"; z[lc++]=" if( past->past_NumInputChannels > 0 )"; z[lc++]=" {"; z[lc++]=" DSW_QueryInputFilled( &pahsc->pahsc_DSoundWrapper, &bytesFilled );"; z[lc++]=" bytesToXfer = bytesFilled;"; z[lc++]=" }"; z[lc++]="#endif /* SUPPORT_AUDIO_CAPTURE */"; z[lc++]="/* How much output room is available? */"; z[lc++]=" if( past->past_NumOutputChannels > 0 )"; z[lc++]=" {"; z[lc++]=" DSW_QueryOutputSpace( &pahsc->pahsc_DSoundWrapper, &bytesEmpty );"; z[lc++]=" bytesToXfer = bytesEmpty;"; z[lc++]=" }"; z[lc++]=" AddTraceMessage( \"bytesEmpty \", bytesEmpty );"; z[lc++]="/* Choose smallest value if both are active. */"; z[lc++]=" if( (past->past_NumInputChannels > 0) && (past->past_NumOutputChannels > 0) )"; z[lc++]=" {"; z[lc++]=" bytesToXfer = ( bytesFilled < bytesEmpty ) ? bytesFilled : bytesEmpty;"; z[lc++]=" }"; z[lc++]="/* printf(\"bytesFilled = %d, bytesEmpty = %d, bytesToXfer = %d\\n\","; z[lc++]=" bytesFilled, bytesEmpty, bytesToXfer);"; z[lc++]="*/"; z[lc++]="/* Quantize to multiples of a buffer. */"; z[lc++]=" numChunks = bytesToXfer / pahsc->pahsc_BytesPerBuffer;"; z[lc++]=" if( numChunks > (long)(past->past_NumUserBuffers/2) )"; z[lc++]=" {"; z[lc++]=" numChunks = (long)past->past_NumUserBuffers/2;"; z[lc++]=" }"; z[lc++]=" else if( numChunks < 0 )"; z[lc++]=" {"; z[lc++]=" numChunks = 0;"; z[lc++]=" }"; z[lc++]=" AddTraceMessage( \"numChunks \", numChunks );"; z[lc++]=" nativeBufPtr = pahsc->pahsc_NativeBuffer;"; z[lc++]=" if( numChunks > 0 )"; z[lc++]=" {"; z[lc++]=" while( numChunks-- > 0 )"; z[lc++]=" {"; z[lc++]=" /* Measure usage based on time to process one user buffer. */"; z[lc++]=" Pa_StartUsageCalculation( past );"; z[lc++]=" #if SUPPORT_AUDIO_CAPTURE"; z[lc++]=" /* Get native data from DirectSound. */"; z[lc++]=" if( past->past_NumInputChannels > 0 )"; z[lc++]=" {"; z[lc++]=" hresult = DSW_ReadBlock( &pahsc->pahsc_DSoundWrapper, (char *) nativeBufPtr, pahsc->pahsc_BytesPerBuffer );"; z[lc++]=" if( hresult < 0 )"; z[lc++]=" {"; z[lc++]=" ERR_RPT((\"DirectSound ReadBlock failed, hresult = 0x%x\\n\",hresult));"; z[lc++]=" sPaHostError = hresult;"; z[lc++]=" break;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" #endif /* SUPPORT_AUDIO_CAPTURE */"; z[lc++]=" /* Convert 16 bit native data to user data and call user routine. */"; z[lc++]=" result = Pa_CallConvertInt16( past, nativeBufPtr, nativeBufPtr );"; z[lc++]=" if( result != 0) break;"; z[lc++]=" /* Pass native data to DirectSound. */"; z[lc++]=" if( past->past_NumOutputChannels > 0 )"; z[lc++]=" {"; z[lc++]=" /* static short DEBUGHACK = 0;"; z[lc++]=" DEBUGHACK += 0x0049;"; z[lc++]=" nativeBufPtr[0] = DEBUGHACK; /* Make buzz to see if DirectSound still running. */"; z[lc++]=" hresult = DSW_WriteBlock( &pahsc->pahsc_DSoundWrapper, (char *) nativeBufPtr, pahsc->pahsc_BytesPerBuffer );"; z[lc++]=" if( hresult < 0 )"; z[lc++]=" {"; z[lc++]=" ERR_RPT((\"DirectSound WriteBlock failed, result = 0x%x\\n\",hresult));"; z[lc++]=" sPaHostError = hresult;"; z[lc++]=" break;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" Pa_EndUsageCalculation( past );"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" return result;"; z[lc++]="}"; z[lc++]="/*******************************************************************/"; z[lc++]="static void CALLBACK Pa_TimerCallback(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)"; z[lc++]="{"; z[lc++]=" internalPortAudioStream *past;"; z[lc++]=" PaHostSoundControl *pahsc;"; z[lc++]="#if PA_SIMULATE_UNDERFLOW"; z[lc++]=" gUnderCallbackCounter++;"; z[lc++]=" if( (gUnderCallbackCounter >= UNDER_START_GAP) &&"; z[lc++]=" (gUnderCallbackCounter <= UNDER_STOP_GAP) )"; z[lc++]=" {"; z[lc++]=" if( gUnderCallbackCounter == UNDER_START_GAP)"; z[lc++]=" {"; z[lc++]=" AddTraceMessage(\"Begin stall: gUnderCallbackCounter =======\", gUnderCallbackCounter );"; z[lc++]=" }"; z[lc++]=" if( gUnderCallbackCounter == UNDER_STOP_GAP)"; z[lc++]=" {"; z[lc++]=" AddTraceMessage(\"End stall: gUnderCallbackCounter =======\", gUnderCallbackCounter );"; z[lc++]=" }"; z[lc++]=" return;"; z[lc++]=" }"; z[lc++]="#endif"; z[lc++]=" past = (internalPortAudioStream *) dwUser;"; z[lc++]=" if( past == NULL ) return;"; z[lc++]=" pahsc = (PaHostSoundControl *) past->past_DeviceData;"; z[lc++]=" if( pahsc == NULL ) return;"; z[lc++]=" if( !pahsc->pahsc_IfInsideCallback && past->past_IsActive )"; z[lc++]=" {"; z[lc++]=" if( past->past_StopNow )"; z[lc++]=" {"; z[lc++]=" past->past_IsActive = 0;"; z[lc++]=" }"; z[lc++]=" else if( past->past_StopSoon )"; z[lc++]=" {"; z[lc++]=" DSoundWrapper *dsw = &pahsc->pahsc_DSoundWrapper;"; z[lc++]=" if( past->past_NumOutputChannels > 0 )"; z[lc++]=" {"; z[lc++]=" DSW_ZeroEmptySpace( dsw ); "; z[lc++]=" AddTraceMessage(\"Pa_TimerCallback: waiting - written \", (int) dsw->dsw_FramesWritten );"; z[lc++]=" AddTraceMessage(\"Pa_TimerCallback: waiting - played \", (int) dsw->dsw_FramesPlayed );"; z[lc++]=" /* clear past_IsActive when all sound played */"; z[lc++]=" if( dsw->dsw_FramesPlayed >= past->past_FrameCount )"; z[lc++]=" {"; z[lc++]=" past->past_IsActive = 0;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" past->past_IsActive = 0;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" pahsc->pahsc_IfInsideCallback = 1;"; z[lc++]=" if( Pa_TimeSlice( past ) != 0) /* Call time slice independant of timing method. */"; z[lc++]=" {"; z[lc++]=" past->past_StopSoon = 1;"; z[lc++]=" }"; z[lc++]=" pahsc->pahsc_IfInsideCallback = 0;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]="}"; z[lc++]="/*******************************************************************/"; z[lc++]="PaError PaHost_OpenStream( internalPortAudioStream *past )"; z[lc++]="{"; z[lc++]=" HRESULT hr;"; z[lc++]=" PaError result = paNoError;"; z[lc++]=" PaHostSoundControl *pahsc;"; z[lc++]=" int numBytes, maxChannels;"; z[lc++]=" unsigned int minNumBuffers;"; z[lc++]=" internalPortAudioDevice *pad;"; z[lc++]=" DSoundWrapper *dsw;"; z[lc++]="/* Allocate and initialize host data. */"; z[lc++]=" pahsc = (PaHostSoundControl *) PaHost_AllocateFastMemory(sizeof(PaHostSoundControl)); /* MEM */"; z[lc++]=" if( pahsc == NULL )"; z[lc++]=" {"; z[lc++]=" result = paInsufficientMemory;"; z[lc++]=" goto error;"; z[lc++]=" }"; z[lc++]=" memset( pahsc, 0, sizeof(PaHostSoundControl) );"; z[lc++]=" past->past_DeviceData = (void *) pahsc;"; z[lc++]=" pahsc->pahsc_TimerID = 0;"; z[lc++]=" dsw = &pahsc->pahsc_DSoundWrapper;"; z[lc++]=" DSW_Init( dsw );"; z[lc++]="/* Allocate native buffer. */"; z[lc++]=" maxChannels = ( past->past_NumOutputChannels > past->past_NumInputChannels ) ?"; z[lc++]=" past->past_NumOutputChannels : past->past_NumInputChannels;"; z[lc++]=" pahsc->pahsc_BytesPerBuffer = past->past_FramesPerUserBuffer * maxChannels * sizeof(short);"; z[lc++]=" if( maxChannels > 0 )"; z[lc++]=" {"; z[lc++]=" pahsc->pahsc_NativeBuffer = (short *) PaHost_AllocateFastMemory(pahsc->pahsc_BytesPerBuffer); /* MEM */"; z[lc++]=" if( pahsc->pahsc_NativeBuffer == NULL )"; z[lc++]=" {"; z[lc++]=" result = paInsufficientMemory;"; z[lc++]=" goto error;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" result = paInvalidChannelCount;"; z[lc++]=" goto error;"; z[lc++]=" }"; z[lc++]=" "; z[lc++]=" DBUG((\"PaHost_OpenStream: pahsc_MinFramesPerHostBuffer = %d\\n\", pahsc->pahsc_MinFramesPerHostBuffer ));"; z[lc++]=" minNumBuffers = Pa_GetMinNumBuffers( past->past_FramesPerUserBuffer, past->past_SampleRate );"; z[lc++]=" past->past_NumUserBuffers = ( minNumBuffers > past->past_NumUserBuffers ) ? minNumBuffers : past->past_NumUserBuffers;"; z[lc++]=" numBytes = pahsc->pahsc_BytesPerBuffer * past->past_NumUserBuffers;"; z[lc++]=" if( numBytes < DSBSIZE_MIN )"; z[lc++]=" {"; z[lc++]=" result = paBufferTooSmall;"; z[lc++]=" goto error;"; z[lc++]=" }"; z[lc++]=" if( numBytes > DSBSIZE_MAX )"; z[lc++]=" {"; z[lc++]=" result = paBufferTooBig;"; z[lc++]=" goto error;"; z[lc++]=" }"; z[lc++]=" pahsc->pahsc_FramesPerDSBuffer = past->past_FramesPerUserBuffer * past->past_NumUserBuffers;"; z[lc++]=" {"; z[lc++]=" int msecLatency = (int) ((pahsc->pahsc_FramesPerDSBuffer * 1000) / past->past_SampleRate);"; z[lc++]=" PRINT((\"PortAudio on DirectSound - Latency = %d frames, %d msec\\n\", pahsc->pahsc_FramesPerDSBuffer, msecLatency ));"; z[lc++]=" }"; z[lc++]="/* ------------------ OUTPUT */"; z[lc++]=" if( (past->past_OutputDeviceID >= 0) && (past->past_NumOutputChannels > 0) )"; z[lc++]=" {"; z[lc++]=" DBUG((\"PaHost_OpenStream: deviceID = 0x%x\\n\", past->past_OutputDeviceID));"; z[lc++]=" pad = Pa_GetInternalDevice( past->past_OutputDeviceID );"; z[lc++]=" hr = DirectSoundCreate( pad->pad_lpGUID, &dsw->dsw_pDirectSound, NULL );"; z[lc++]="/* If this fails, then try each output device until we find one that works. */"; z[lc++]=" if( hr != DS_OK )"; z[lc++]=" {"; z[lc++]=" int i;"; z[lc++]=" ERR_RPT((\"Creation of requested Audio Output device '%s' failed.\\n\","; z[lc++]=" ((pad->pad_lpGUID == NULL) ? \"Default\" : pad->pad_Info.name) ));"; z[lc++]=" for( i=0; ipad_Info.name ));"; z[lc++]=" hr = DirectSoundCreate( pad->pad_lpGUID, &dsw->dsw_pDirectSound, NULL );"; z[lc++]=" if( hr == DS_OK )"; z[lc++]=" {"; z[lc++]=" ERR_RPT((\"Using device '%s' instead.\\n\", pad->pad_Info.name ));"; z[lc++]=" break;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" if( hr != DS_OK )"; z[lc++]=" {"; z[lc++]=" ERR_RPT((\"PortAudio: DirectSoundCreate() failed!\\n\"));"; z[lc++]=" result = paHostError;"; z[lc++]=" sPaHostError = hr;"; z[lc++]=" goto error;"; z[lc++]=" }"; z[lc++]=" hr = DSW_InitOutputBuffer( dsw,"; z[lc++]=" (unsigned long) (past->past_SampleRate + 0.5),"; z[lc++]=" past->past_NumOutputChannels, numBytes );"; z[lc++]=" DBUG((\"DSW_InitOutputBuffer() returns %x\\n\", hr));"; z[lc++]=" if( hr != DS_OK )"; z[lc++]=" {"; z[lc++]=" result = paHostError;"; z[lc++]=" sPaHostError = hr;"; z[lc++]=" goto error;"; z[lc++]=" }"; z[lc++]=" past->past_FrameCount = pahsc->pahsc_DSoundWrapper.dsw_FramesWritten;"; z[lc++]=" }"; z[lc++]="#if SUPPORT_AUDIO_CAPTURE"; z[lc++]="/* ------------------ INPUT */"; z[lc++]=" if( (past->past_InputDeviceID >= 0) && (past->past_NumInputChannels > 0) )"; z[lc++]=" {"; z[lc++]=" pad = Pa_GetInternalDevice( past->past_InputDeviceID );"; z[lc++]=" hr = DirectSoundCaptureCreate( pad->pad_lpGUID, &dsw->dsw_pDirectSoundCapture, NULL );"; z[lc++]="/* If this fails, then try each input device until we find one that works. */"; z[lc++]=" if( hr != DS_OK )"; z[lc++]=" {"; z[lc++]=" int i;"; z[lc++]=" ERR_RPT((\"Creation of requested Audio Capture device '%s' failed.\\n\","; z[lc++]=" ((pad->pad_lpGUID == NULL) ? \"Default\" : pad->pad_Info.name) ));"; z[lc++]=" for( i=0; ipad_Info.name ));"; z[lc++]=" hr = DirectSoundCaptureCreate( pad->pad_lpGUID, &dsw->dsw_pDirectSoundCapture, NULL );"; z[lc++]=" if( hr == DS_OK ) break;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" if( hr != DS_OK )"; z[lc++]=" {"; z[lc++]=" ERR_RPT((\"PortAudio: DirectSoundCaptureCreate() failed!\\n\"));"; z[lc++]=" result = paHostError;"; z[lc++]=" sPaHostError = hr;"; z[lc++]=" goto error;"; z[lc++]=" }"; z[lc++]=" hr = DSW_InitInputBuffer( dsw,"; z[lc++]=" (unsigned long) (past->past_SampleRate + 0.5),"; z[lc++]=" past->past_NumInputChannels, numBytes );"; z[lc++]=" DBUG((\"DSW_InitInputBuffer() returns %x\\n\", hr));"; z[lc++]=" if( hr != DS_OK )"; z[lc++]=" {"; z[lc++]=" ERR_RPT((\"PortAudio: DSW_InitInputBuffer() returns %x\\n\", hr));"; z[lc++]=" result = paHostError;"; z[lc++]=" sPaHostError = hr;"; z[lc++]=" goto error;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]="#endif /* SUPPORT_AUDIO_CAPTURE */"; z[lc++]=" /* Calculate scalar used in CPULoad calculation. */ "; z[lc++]=" {"; z[lc++]=" LARGE_INTEGER frequency;"; z[lc++]=" if( QueryPerformanceFrequency( &frequency ) == 0 )"; z[lc++]=" {"; z[lc++]=" pahsc->pahsc_InverseTicksPerUserBuffer = 0.0;"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" pahsc->pahsc_InverseTicksPerUserBuffer = past->past_SampleRate /"; z[lc++]=" ( (double)frequency.QuadPart * past->past_FramesPerUserBuffer );"; z[lc++]=" DBUG((\"pahsc_InverseTicksPerUserBuffer = %g\\n\", pahsc->pahsc_InverseTicksPerUserBuffer ));"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" return result;"; z[lc++]="error:"; z[lc++]=" PaHost_CloseStream( past );"; z[lc++]=" return result;"; z[lc++]="}"; z[lc++]="/*************************************************************************/"; z[lc++]="PaError PaHost_StartOutput( internalPortAudioStream *past )"; z[lc++]="{"; z[lc++]=" HRESULT hr;"; z[lc++]=" PaHostSoundControl *pahsc;"; z[lc++]=" PaError result = paNoError;"; z[lc++]=" pahsc = (PaHostSoundControl *) past->past_DeviceData;"; z[lc++]="/* Give user callback a chance to pre-fill buffer. */"; z[lc++]=" result = Pa_TimeSlice( past );"; z[lc++]=" if( result != paNoError ) return result; // FIXME - what if finished?"; z[lc++]=" hr = DSW_StartOutput( &pahsc->pahsc_DSoundWrapper );"; z[lc++]=" DBUG((\"PaHost_StartOutput: DSW_StartOutput returned = 0x%X.\\n\", hr));"; z[lc++]=" if( hr != DS_OK )"; z[lc++]=" {"; z[lc++]=" result = paHostError;"; z[lc++]=" sPaHostError = hr;"; z[lc++]=" goto error;"; z[lc++]=" }"; z[lc++]="error:"; z[lc++]=" return result;"; z[lc++]="}"; z[lc++]="/*************************************************************************/"; z[lc++]="PaError PaHost_StartInput( internalPortAudioStream *past )"; z[lc++]="{"; z[lc++]=" PaError result = paNoError;"; z[lc++]="#if SUPPORT_AUDIO_CAPTURE"; z[lc++]=" HRESULT hr;"; z[lc++]=" PaHostSoundControl *pahsc;"; z[lc++]=" pahsc = (PaHostSoundControl *) past->past_DeviceData;"; z[lc++]=" hr = DSW_StartInput( &pahsc->pahsc_DSoundWrapper );"; z[lc++]=" DBUG((\"Pa_StartStream: DSW_StartInput returned = 0x%X.\\n\", hr));"; z[lc++]=" if( hr != DS_OK )"; z[lc++]=" {"; z[lc++]=" result = paHostError;"; z[lc++]=" sPaHostError = hr;"; z[lc++]=" goto error;"; z[lc++]=" }"; z[lc++]="error:"; z[lc++]="#endif /* SUPPORT_AUDIO_CAPTURE */"; z[lc++]=" return result;"; z[lc++]="}"; z[lc++]="/*************************************************************************/"; z[lc++]="PaError PaHost_StartEngine( internalPortAudioStream *past )"; z[lc++]="{"; z[lc++]=" PaHostSoundControl *pahsc;"; z[lc++]=" PaError result = paNoError;"; z[lc++]=" pahsc = (PaHostSoundControl *) past->past_DeviceData;"; z[lc++]=" past->past_StopNow = 0;"; z[lc++]=" past->past_StopSoon = 0;"; z[lc++]=" past->past_IsActive = 1;"; z[lc++]="/* Create timer that will wake us up so we can fill the DSound buffer. */"; z[lc++]=" {"; z[lc++]=" int msecPerBuffer;"; z[lc++]=" int resolution;"; z[lc++]=" int bufsPerInterrupt = past->past_NumUserBuffers/4;"; z[lc++]=" if( bufsPerInterrupt < 1 ) bufsPerInterrupt = 1;"; z[lc++]=" msecPerBuffer = 1000 * (bufsPerInterrupt * past->past_FramesPerUserBuffer) / (int) past->past_SampleRate;"; z[lc++]=" if( msecPerBuffer < 10 ) msecPerBuffer = 10;"; z[lc++]=" else if( msecPerBuffer > 100 ) msecPerBuffer = 100;"; z[lc++]=" resolution = msecPerBuffer/4;"; z[lc++]=" pahsc->pahsc_TimerID = timeSetEvent( msecPerBuffer, resolution, (LPTIMECALLBACK) Pa_TimerCallback,"; z[lc++]=" (DWORD) past, TIME_PERIODIC );"; z[lc++]=" }"; z[lc++]=" if( pahsc->pahsc_TimerID == 0 )"; z[lc++]=" {"; z[lc++]=" past->past_IsActive = 0;"; z[lc++]=" result = paHostError;"; z[lc++]=" sPaHostError = 0;"; z[lc++]=" goto error;"; z[lc++]=" }"; z[lc++]="error:"; z[lc++]=" return result;"; z[lc++]="}"; z[lc++]="/*************************************************************************/"; z[lc++]="PaError PaHost_StopEngine( internalPortAudioStream *past, int abort )"; z[lc++]="{"; z[lc++]=" int timeoutMsec;"; z[lc++]=" PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData;"; z[lc++]=" if( pahsc == NULL ) return paNoError;"; z[lc++]=" if( abort ) past->past_StopNow = 1;"; z[lc++]=" past->past_StopSoon = 1;"; z[lc++]="/* Set timeout at 20% beyond maximum time we might wait. */"; z[lc++]=" timeoutMsec = (int) (1200.0 * pahsc->pahsc_FramesPerDSBuffer / past->past_SampleRate);"; z[lc++]=" while( past->past_IsActive && (timeoutMsec > 0) )"; z[lc++]=" {"; z[lc++]=" Sleep(10);"; z[lc++]=" timeoutMsec -= 10;"; z[lc++]=" }"; z[lc++]=" if( pahsc->pahsc_TimerID != 0 )"; z[lc++]=" {"; z[lc++]=" timeKillEvent(pahsc->pahsc_TimerID); /* Stop callback timer. */"; z[lc++]=" pahsc->pahsc_TimerID = 0;"; z[lc++]=" }"; z[lc++]=" return paNoError;"; z[lc++]="}"; z[lc++]="/*************************************************************************/"; z[lc++]="PaError PaHost_StopInput( internalPortAudioStream *past, int abort )"; z[lc++]="{"; z[lc++]="#if SUPPORT_AUDIO_CAPTURE"; z[lc++]=" HRESULT hr;"; z[lc++]=" PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData;"; z[lc++]=" if( pahsc == NULL ) return paNoError;"; z[lc++]=" (void) abort;"; z[lc++]=" hr = DSW_StopInput( &pahsc->pahsc_DSoundWrapper );"; z[lc++]=" DBUG((\"DSW_StopInput() result is %x\\n\", hr));"; z[lc++]="#endif /* SUPPORT_AUDIO_CAPTURE */"; z[lc++]=" return paNoError;"; z[lc++]="}"; z[lc++]="/*************************************************************************/"; z[lc++]="PaError PaHost_StopOutput( internalPortAudioStream *past, int abort )"; z[lc++]="{"; z[lc++]=" HRESULT hr;"; z[lc++]=" PaHostSoundControl *pahsc;"; z[lc++]=" pahsc = (PaHostSoundControl *) past->past_DeviceData;"; z[lc++]=" if( pahsc == NULL ) return paNoError;"; z[lc++]=" (void) abort;"; z[lc++]=" hr = DSW_StopOutput( &pahsc->pahsc_DSoundWrapper );"; z[lc++]=" DBUG((\"DSW_StopOutput() result is %x\\n\", hr));"; z[lc++]=" return paNoError;"; z[lc++]="}"; z[lc++]="/*******************************************************************/"; z[lc++]="PaError PaHost_CloseStream( internalPortAudioStream *past )"; z[lc++]="{"; z[lc++]=" PaHostSoundControl *pahsc;"; z[lc++]=" if( past == NULL ) return paBadStreamPtr;"; z[lc++]=" pahsc = (PaHostSoundControl *) past->past_DeviceData;"; z[lc++]=" if( pahsc == NULL ) return paNoError;"; z[lc++]=" DSW_Term( &pahsc->pahsc_DSoundWrapper );"; z[lc++]=" if( pahsc->pahsc_NativeBuffer )"; z[lc++]=" {"; z[lc++]=" PaHost_FreeFastMemory( pahsc->pahsc_NativeBuffer, pahsc->pahsc_BytesPerBuffer ); /* MEM */"; z[lc++]=" pahsc->pahsc_NativeBuffer = NULL;"; z[lc++]=" }"; z[lc++]=" PaHost_FreeFastMemory( pahsc, sizeof(PaHostSoundControl) ); /* MEM */"; z[lc++]=" past->past_DeviceData = NULL;"; z[lc++]=" return paNoError;"; z[lc++]="}"; z[lc++]="/*************************************************************************"; z[lc++]="** Determine minimum number of buffers required for this host based"; z[lc++]="** on minimum latency. Latency can be optionally set by user by setting"; z[lc++]="** an environment variable. For example, to set latency to 200 msec, put:"; z[lc++]="**"; z[lc++]="** set PA_MIN_LATENCY_MSEC=200"; z[lc++]="**"; z[lc++]="** in the AUTOEXEC.BAT file and reboot."; z[lc++]="** If the environment variable is not set, then the latency will be determined"; z[lc++]="** based on the OS. Windows NT has higher latency than Win95."; z[lc++]="*/"; z[lc++]="#define PA_LATENCY_ENV_NAME (\"PA_MIN_LATENCY_MSEC\")"; z[lc++]="int Pa_GetMinNumBuffers( int framesPerBuffer, double sampleRate )"; z[lc++]="{"; z[lc++]=" char envbuf[PA_ENV_BUF_SIZE];"; z[lc++]=" DWORD hostVersion;"; z[lc++]=" DWORD hresult;"; z[lc++]=" int minLatencyMsec = 0;"; z[lc++]=" double msecPerBuffer = (1000.0 * framesPerBuffer) / sampleRate;"; z[lc++]=" int minBuffers;"; z[lc++]="/* Let user determine minimal latency by setting environment variable. */"; z[lc++]=" hresult = GetEnvironmentVariable( PA_LATENCY_ENV_NAME, envbuf, PA_ENV_BUF_SIZE );"; z[lc++]=" if( (hresult > 0) && (hresult < PA_ENV_BUF_SIZE) )"; z[lc++]=" {"; z[lc++]=" minLatencyMsec = atoi( envbuf );"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]="/* Set minimal latency based on whether NT or Win95."; z[lc++]=" * NT has higher latency."; z[lc++]=" */"; z[lc++]=" hostVersion = GetVersion();"; z[lc++]="/* High bit clear if NT */"; z[lc++]=" minLatencyMsec = ( (hostVersion & 0x80000000) == 0 ) ? PA_WIN_NT_LATENCY : PA_WIN_9X_LATENCY ;"; z[lc++]="#if PA_USE_HIGH_LATENCY"; z[lc++]=" PRINT((\"PA - Minimum Latency set to %d msec!\\n\", minLatencyMsec ));"; z[lc++]="#endif"; z[lc++]=" }"; z[lc++]=" minBuffers = (int) (1.0 + ((double)minLatencyMsec / msecPerBuffer));"; z[lc++]=" if( minBuffers < 2 ) minBuffers = 2;"; z[lc++]=" return minBuffers;"; z[lc++]="}"; z[lc++]="/*************************************************************************/"; z[lc++]="PaError PaHost_Term( void )"; z[lc++]="{"; z[lc++]=" int i;"; z[lc++]="/* Free names allocated during enumeration. */"; z[lc++]=" for( i=0; i