Fangjun Kuang
Committed by GitHub

Object pascal examples for recording and playing audio with portaudio. (#1271)

The recording example can be used for speech recognition while the playing example can be used for text to speech.

The portaudio wrapper for object pascal is copied from
https://github.com/UltraStar-Deluxe/USDX/blob/master/src/lib/portaudio/portaudio.pas
  1 +# Introduction
  2 +
  3 +[portaudio.pas](./portaudio.pas)
  4 +requires that the portaudio library is installed on your system.
  5 +
  6 +
  7 +On macOS, you can use
  8 +
  9 +```bash
  10 +brew install portaudio
  11 +```
  12 +
  13 +and it will install `portaudio` into `/usr/local/Cellar/portaudio/19.7.0`.
  1 +#!/usr/bin/env bash
  2 +
  3 +set -ex
  4 +
  5 +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
  6 +SHERPA_ONNX_DIR=$(cd $SCRIPT_DIR/../.. && pwd)
  7 +
  8 +echo "SHERPA_ONNX_DIR: $SHERPA_ONNX_DIR"
  9 +
  10 +if [[ ! -f ../../build/install/lib/libsherpa-onnx-c-api.dylib && ! -f ../../build/install/lib/libsherpa-onnx-c-api.so && ! -f ../../build/install/lib/sherpa-onnx-c-api.dll ]]; then
  11 + mkdir -p ../../build
  12 + pushd ../../build
  13 + cmake \
  14 + -DCMAKE_INSTALL_PREFIX=./install \
  15 + -DSHERPA_ONNX_ENABLE_PYTHON=OFF \
  16 + -DSHERPA_ONNX_ENABLE_TESTS=OFF \
  17 + -DSHERPA_ONNX_ENABLE_CHECK=OFF \
  18 + -DBUILD_SHARED_LIBS=ON \
  19 + -DSHERPA_ONNX_ENABLE_PORTAUDIO=OFF \
  20 + ..
  21 +
  22 + cmake --build . --target install --config Release
  23 + popd
  24 +fi
  25 +
  26 +fpc \
  27 + -g \
  28 + -dSHERPA_ONNX_USE_SHARED_LIBS \
  29 + -Fu$SHERPA_ONNX_DIR/sherpa-onnx/pascal-api \
  30 + -Fl$SHERPA_ONNX_DIR/build/install/lib \
  31 + -Fl/usr/local/Cellar/portaudio/19.7.0/lib \
  32 + ./test-play.pas
  33 +
  34 +export LD_LIBRARY_PATH=$SHERPA_ONNX_DIR/build/install/lib:$LD_LIBRARY_PATH
  35 +export DYLD_LIBRARY_PATH=$SHERPA_ONNX_DIR/build/install/lib:$DYLD_LIBRARY_PATH
  36 +
  37 +./test-play
  1 +#!/usr/bin/env bash
  2 +
  3 +set -ex
  4 +
  5 +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
  6 +SHERPA_ONNX_DIR=$(cd $SCRIPT_DIR/../.. && pwd)
  7 +
  8 +echo "SHERPA_ONNX_DIR: $SHERPA_ONNX_DIR"
  9 +
  10 +if [[ ! -f ../../build/install/lib/libsherpa-onnx-c-api.dylib && ! -f ../../build/install/lib/libsherpa-onnx-c-api.so && ! -f ../../build/install/lib/sherpa-onnx-c-api.dll ]]; then
  11 + mkdir -p ../../build
  12 + pushd ../../build
  13 + cmake \
  14 + -DCMAKE_INSTALL_PREFIX=./install \
  15 + -DSHERPA_ONNX_ENABLE_PYTHON=OFF \
  16 + -DSHERPA_ONNX_ENABLE_TESTS=OFF \
  17 + -DSHERPA_ONNX_ENABLE_CHECK=OFF \
  18 + -DBUILD_SHARED_LIBS=ON \
  19 + -DSHERPA_ONNX_ENABLE_PORTAUDIO=OFF \
  20 + ..
  21 +
  22 + cmake --build . --target install --config Release
  23 + popd
  24 +fi
  25 +
  26 +fpc \
  27 + -g \
  28 + -dSHERPA_ONNX_USE_SHARED_LIBS \
  29 + -Fu$SHERPA_ONNX_DIR/sherpa-onnx/pascal-api \
  30 + -Fl$SHERPA_ONNX_DIR/build/install/lib \
  31 + -Fl/usr/local/Cellar/portaudio/19.7.0/lib \
  32 + ./test-record.pas
  33 +
  34 +export LD_LIBRARY_PATH=$SHERPA_ONNX_DIR/build/install/lib:$LD_LIBRARY_PATH
  35 +export DYLD_LIBRARY_PATH=$SHERPA_ONNX_DIR/build/install/lib:$DYLD_LIBRARY_PATH
  36 +
  37 +./test-record
  1 +{ Copyright (c) 2024 Xiaomi Corporation }
  2 +{
  3 +This file shows how to use portaudio for playing.
  4 +
  5 +}
  6 +program main;
  7 +
  8 +{$mode objfpc}{$H+}
  9 +
  10 +
  11 +uses
  12 + portaudio,
  13 + sherpa_onnx,
  14 + dos,
  15 + ctypes,
  16 + SysUtils;
  17 +
  18 +var
  19 + Version: String;
  20 + EnvStr: String;
  21 + Status: Integer;
  22 + NumDevices: Integer;
  23 + DeviceIndex: Integer;
  24 + DeviceInfo: PPaDeviceInfo;
  25 + I: Integer;
  26 + Param: TPaStreamParameters;
  27 + Stream: PPaStream;
  28 + Wave: TSherpaOnnxWave;
  29 +
  30 + Buffer: TSherpaOnnxCircularBuffer;
  31 +
  32 +function PlayCallback(
  33 + input: Pointer; output: Pointer;
  34 + frameCount: culong;
  35 + timeInfo: PPaStreamCallbackTimeInfo;
  36 + statusFlags: TPaStreamCallbackFlags;
  37 + userData: Pointer ): cint; cdecl;
  38 +var
  39 + Samples: TSherpaOnnxSamplesArray;
  40 + I: Integer;
  41 +begin
  42 + if Buffer.Size >= frameCount then
  43 + begin
  44 + Samples := Buffer.Get(Buffer.Head, FrameCount);
  45 + Buffer.Pop(FrameCount);
  46 + end
  47 + else
  48 + begin
  49 + Samples := Buffer.Get(Buffer.Head, Buffer.Size);
  50 + Buffer.Pop(Buffer.Size);
  51 + SetLength(Samples, frameCount);
  52 + end;
  53 + for I := 0 to frameCount - 1 do
  54 + pcfloat(output)[I] := Samples[I];
  55 +
  56 + if Buffer.Size > 0 then
  57 + Result := paContinue
  58 + else
  59 + Result := paComplete;
  60 +end;
  61 +
  62 +
  63 +
  64 +begin
  65 + Version := String(Pa_GetVersionText);
  66 + WriteLn('Version is ', Version);
  67 + Status := Pa_Initialize;
  68 + if Status <> paNoError then
  69 + begin
  70 + WriteLn('Failed to initialize portaudio, ', Pa_GetErrorText(Status));
  71 + Exit;
  72 + end;
  73 +
  74 + NumDevices := Pa_GetDeviceCount;
  75 + WriteLn('Num devices: ', NumDevices);
  76 +
  77 + DeviceIndex := Pa_GetDefaultOutputDevice;
  78 +
  79 + if DeviceIndex = paNoDevice then
  80 + begin
  81 + WriteLn('No default output device found');
  82 + Pa_Terminate;
  83 + Exit;
  84 + end;
  85 +
  86 + EnvStr := GetEnv('SHERPA_ONNX_MIC_DEVICE');
  87 + if EnvStr <> '' then
  88 + begin
  89 + DeviceIndex := StrToIntDef(EnvStr, DeviceIndex);
  90 + WriteLn('Use device index from environment variable SHERPA_ONNX_MIC_DEVICE: ', EnvStr);
  91 + end;
  92 +
  93 + for I := 0 to (NumDevices - 1) do
  94 + begin
  95 + DeviceInfo := Pa_GetDeviceInfo(I);
  96 + if I = DeviceIndex then
  97 + { WriteLn(Format(' * %d %s', [I, DeviceInfo^.Name])) }
  98 + WriteLn(Format(' * %d %s', [I, AnsiString(DeviceInfo^.Name)]))
  99 + else
  100 + WriteLn(Format(' %d %s', [I, AnsiString(DeviceInfo^.Name)]));
  101 + end;
  102 +
  103 + WriteLn('Use device ', DeviceIndex);
  104 + WriteLn(' Name ', Pa_GetDeviceInfo(DeviceIndex)^.Name);
  105 + WriteLn(' Max output channels ', Pa_GetDeviceInfo(DeviceIndex)^.MaxOutputChannels);
  106 +
  107 + Wave := SherpaOnnxReadWave('./record.wav');
  108 + if Wave.Samples = nil then
  109 + begin
  110 + WriteLn('Failed to read ./record.wav');
  111 + Pa_Terminate;
  112 + Exit;
  113 + end;
  114 +
  115 + Initialize(Param);
  116 + Param.Device := DeviceIndex;
  117 + Param.ChannelCount := 1;
  118 + Param.SampleFormat := paFloat32;
  119 + param.SuggestedLatency := Pa_GetDeviceInfo(DeviceIndex)^.DefaultHighOutputLatency;
  120 + param.HostApiSpecificStreamInfo := nil;
  121 +
  122 + Buffer := TSherpaOnnxCircularBuffer.Create(Length(Wave.Samples));
  123 + Buffer.Push(Wave.Samples);
  124 +
  125 + Status := Pa_OpenStream(stream, nil, @Param, Wave.SampleRate, paFramesPerBufferUnspecified, paNoFlag,
  126 + PPaStreamCallback(@PlayCallback), nil);
  127 +
  128 + if Status <> paNoError then
  129 + begin
  130 + WriteLn('Failed to open stream, ', Pa_GetErrorText(Status));
  131 + Pa_Terminate;
  132 + Exit;
  133 + end;
  134 +
  135 + Status := Pa_StartStream(stream);
  136 + if Status <> paNoError then
  137 + begin
  138 + WriteLn('Failed to start stream, ', Pa_GetErrorText(Status));
  139 + Pa_Terminate;
  140 + Exit;
  141 + end;
  142 +
  143 + while Buffer.Size > 0 do
  144 + Pa_Sleep(100); {sleep for 0.1 second }
  145 +
  146 + Status := Pa_CloseStream(stream);
  147 + if Status <> paNoError then
  148 + begin
  149 + WriteLn('Failed to close stream, ', Pa_GetErrorText(Status));
  150 + Exit;
  151 + end;
  152 +
  153 + Status := Pa_Terminate;
  154 + if Status <> paNoError then
  155 + begin
  156 + WriteLn('Failed to deinitialize portaudio, ', Pa_GetErrorText(Status));
  157 + Exit;
  158 + end;
  159 +end.
  160 +
  1 +{ Copyright (c) 2024 Xiaomi Corporation }
  2 +{
  3 +This file shows how to use portaudio for recording.
  4 +
  5 +It records for 10 seconds and saves the audio samples to ./record.wav
  6 +}
  7 +program main;
  8 +
  9 +{$mode objfpc}
  10 +
  11 +uses
  12 + portaudio,
  13 + sherpa_onnx,
  14 + dos,
  15 + ctypes,
  16 + SysUtils;
  17 +
  18 +var
  19 + Version: String;
  20 + EnvStr: String;
  21 + Status: Integer;
  22 + NumDevices: Integer;
  23 + DeviceIndex: Integer;
  24 + DeviceInfo: PPaDeviceInfo;
  25 + I: Integer;
  26 + Param: TPaStreamParameters;
  27 + SampleRate: Double;
  28 + Stream: PPaStream;
  29 +
  30 + Buffer: TSherpaOnnxCircularBuffer;
  31 + AllSamples: TSherpaOnnxSamplesArray;
  32 +
  33 +function RecordCallback(
  34 + input: Pointer; output: Pointer;
  35 + frameCount: culong;
  36 + timeInfo: PPaStreamCallbackTimeInfo;
  37 + statusFlags: TPaStreamCallbackFlags;
  38 + userData: Pointer ): cint; cdecl;
  39 +begin
  40 + Buffer.Push(pcfloat(input), frameCount);
  41 + Result := paContinue;
  42 +end;
  43 +
  44 +
  45 +
  46 +begin
  47 + Version := String(Pa_GetVersionText);
  48 + WriteLn('Version is ', Version);
  49 + Status := Pa_Initialize;
  50 + if Status <> paNoError then
  51 + begin
  52 + WriteLn('Failed to initialize portaudio, ', Pa_GetErrorText(Status));
  53 + Exit;
  54 + end;
  55 +
  56 + NumDevices := Pa_GetDeviceCount;
  57 + WriteLn('Num devices: ', NumDevices);
  58 +
  59 + DeviceIndex := Pa_GetDefaultInputDevice;
  60 +
  61 + if DeviceIndex = paNoDevice then
  62 + begin
  63 + WriteLn('No default input device found');
  64 + Pa_Terminate;
  65 + Exit;
  66 + end;
  67 +
  68 + EnvStr := GetEnv('SHERPA_ONNX_MIC_DEVICE');
  69 + if EnvStr <> '' then
  70 + begin
  71 + DeviceIndex := StrToIntDef(EnvStr, DeviceIndex);
  72 + WriteLn('Use device index from environment variable SHERPA_ONNX_MIC_DEVICE: ', EnvStr);
  73 + end;
  74 +
  75 + for I := 0 to (NumDevices - 1) do
  76 + begin
  77 + DeviceInfo := Pa_GetDeviceInfo(I);
  78 + if I = DeviceIndex then
  79 + { WriteLn(Format(' * %d %s', [I, DeviceInfo^.Name])) }
  80 + WriteLn(Format(' * %d %s', [I, AnsiString(DeviceInfo^.Name)]))
  81 + else
  82 + WriteLn(Format(' %d %s', [I, AnsiString(DeviceInfo^.Name)]));
  83 + end;
  84 +
  85 + WriteLn('Use device ', DeviceIndex);
  86 + WriteLn(' Name ', Pa_GetDeviceInfo(DeviceIndex)^.Name);
  87 + WriteLn(' Max input channels ', Pa_GetDeviceInfo(DeviceIndex)^.MaxInputChannels);
  88 +
  89 + Initialize(Param);
  90 + Param.Device := DeviceIndex;
  91 + Param.ChannelCount := 1;
  92 + Param.SampleFormat := paFloat32;
  93 + param.SuggestedLatency := Pa_GetDeviceInfo(DeviceIndex)^.DefaultHighInputLatency;
  94 + param.HostApiSpecificStreamInfo := nil;
  95 +
  96 + SampleRate := 48000;
  97 + Buffer := TSherpaOnnxCircularBuffer.Create(Round(SampleRate) * 20);
  98 +
  99 + Status := Pa_OpenStream(stream, @Param, nil, SampleRate, paFramesPerBufferUnspecified, paNoFlag,
  100 + PPaStreamCallback(@RecordCallback), nil);
  101 +
  102 + if Status <> paNoError then
  103 + begin
  104 + WriteLn('Failed to open stream, ', Pa_GetErrorText(Status));
  105 + Pa_Terminate;
  106 + Exit;
  107 + end;
  108 +
  109 + Status := Pa_StartStream(stream);
  110 + if Status <> paNoError then
  111 + begin
  112 + WriteLn('Failed to start stream, ', Pa_GetErrorText(Status));
  113 + Pa_Terminate;
  114 + Exit;
  115 + end;
  116 +
  117 + WriteLn('Please speak! It will exit after 10 seconds.');
  118 + Pa_Sleep(10000); {sleep for 10 seconds }
  119 +
  120 + Status := Pa_CloseStream(stream);
  121 + if Status <> paNoError then
  122 + begin
  123 + WriteLn('Failed to close stream, ', Pa_GetErrorText(Status));
  124 + Exit;
  125 + end;
  126 +
  127 + AllSamples := Buffer.Get(0, Buffer.Size);
  128 +
  129 + SherpaOnnxWriteWave('record.wav', AllSamples, Round(SampleRate));
  130 + WriteLn('Saved to record.wav');
  131 +
  132 + Status := Pa_Terminate;
  133 + if Status <> paNoError then
  134 + begin
  135 + WriteLn('Failed to deinitialize portaudio, ', Pa_GetErrorText(Status));
  136 + Exit;
  137 + end;
  138 +end.
  139 +
@@ -5,3 +5,7 @@ This directory contains APIs for [Object Pascal](https://en.wikipedia.org/wiki/O @@ -5,3 +5,7 @@ This directory contains APIs for [Object Pascal](https://en.wikipedia.org/wiki/O
5 Please see 5 Please see
6 https://github.com/k2-fsa/sherpa-onnx/tree/master/pascal-api-examples 6 https://github.com/k2-fsa/sherpa-onnx/tree/master/pascal-api-examples
7 for usages. 7 for usages.
  8 +
  9 +[portaudio.pas](./portaudio.pas)
  10 +is copied from
  11 +https://github.com/UltraStar-Deluxe/USDX/blob/master/src/lib/portaudio/portaudio.pas
  1 +{
  2 +This file is copied from
  3 +https://github.com/UltraStar-Deluxe/USDX/blob/master/src/lib/portaudio/portaudio.pas
  4 +}
  5 +{*
  6 + * $Id: portaudio.h,v 1.7 2007/08/16 20:45:34 richardash1981 Exp $
  7 + * PortAudio Portable Real-Time Audio Library
  8 + * PortAudio API Header File
  9 + * Latest version available at: http://www.portaudio.com/
  10 + *
  11 + * Copyright (c) 1999-2002 Ross Bencina and Phil Burk
  12 + *
  13 + * Permission is hereby granted, free of charge, to any person obtaining
  14 + * a copy of this software and associated documentation files
  15 + * (the "Software"), to deal in the Software without restriction,
  16 + * including without limitation the rights to use, copy, modify, merge,
  17 + * publish, distribute, sublicense, and/or sell copies of the Software,
  18 + * and to permit persons to whom the Software is furnished to do so,
  19 + * subject to the following conditions:
  20 + *
  21 + * The above copyright notice and this permission notice shall be
  22 + * included in all copies or substantial portions of the Software.
  23 + *
  24 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  25 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  26 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  27 + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
  28 + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
  29 + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  30 + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  31 + *}
  32 +
  33 +{*
  34 + * The text above constitutes the entire PortAudio license; however,
  35 + * the PortAudio community also makes the following non-binding requests:
  36 + *
  37 + * Any person wishing to distribute modifications to the Software is
  38 + * requested to send the modifications to the original developer so that
  39 + * they can be incorporated into the canonical version. It is also
  40 + * requested that these non-binding requests be included along with the
  41 + * license above.
  42 + *}
  43 +
  44 +{** @file
  45 + @brief The PortAudio API.
  46 +*}
  47 +
  48 +unit portaudio;
  49 +
  50 +{$IFDEF FPC}
  51 + {$PACKENUM 4} (* use 4-byte enums *)
  52 + {$PACKRECORDS C} (* C/C++-compatible record packing *)
  53 + {$MODE DELPHI }
  54 +{$ELSE}
  55 + {$MINENUMSIZE 4} (* use 4-byte enums *)
  56 +{$ENDIF}
  57 +
  58 +interface
  59 +
  60 +uses
  61 + ctypes;
  62 +
  63 +const
  64 +{$IF Defined(MSWINDOWS)}
  65 + LibName = 'portaudio_x86.dll';
  66 +{$ELSEIF Defined(UNIX)}
  67 + LibName = 'portaudio';
  68 + {$LINKLIB portaudio}
  69 +{$IFEND}
  70 +
  71 +{** Retrieve the release number of the currently running PortAudio build,
  72 + eg 1900.
  73 +*}
  74 +function Pa_GetVersion(): cint; cdecl; external LibName;
  75 +
  76 +
  77 +{** Retrieve a textual description of the current PortAudio build,
  78 + eg "PortAudio V19-devel 13 October 2002".
  79 +*}
  80 +function Pa_GetVersionText(): PChar; cdecl; external LibName;
  81 +
  82 +
  83 +{** Error codes returned by PortAudio functions.
  84 + Note that with the exception of paNoError, all PaErrorCodes are negative.
  85 +*}
  86 +
  87 +type TPaError = cint;
  88 +type TPaErrorCode = {enum}cint; const
  89 +{enum_begin PaErrorCode}
  90 + paNoError = 0;
  91 +
  92 + paNotInitialized = -10000;
  93 + paUnanticipatedHostError = (paNotInitialized+ 1);
  94 + paInvalidChannelCount = (paNotInitialized+ 2);
  95 + paInvalidSampleRate = (paNotInitialized+ 3);
  96 + paInvalidDevice = (paNotInitialized+ 4);
  97 + paInvalidFlag = (paNotInitialized+ 5);
  98 + paSampleFormatNotSupported = (paNotInitialized+ 6);
  99 + paBadIODeviceCombination = (paNotInitialized+ 7);
  100 + paInsufficientMemory = (paNotInitialized+ 8);
  101 + paBufferTooBig = (paNotInitialized+ 9);
  102 + paBufferTooSmall = (paNotInitialized+10);
  103 + paNullCallback = (paNotInitialized+11);
  104 + paBadStreamPtr = (paNotInitialized+12);
  105 + paTimedOut = (paNotInitialized+13);
  106 + paInternalError = (paNotInitialized+14);
  107 + paDeviceUnavailable = (paNotInitialized+15);
  108 + paIncompatibleHostApiSpecificStreamInfo = (paNotInitialized+16);
  109 + paStreamIsStopped = (paNotInitialized+17);
  110 + paStreamIsNotStopped = (paNotInitialized+18);
  111 + paInputOverflowed = (paNotInitialized+19);
  112 + paOutputUnderflowed = (paNotInitialized+20);
  113 + paHostApiNotFound = (paNotInitialized+21); // The notes below are from the
  114 + paInvalidHostApi = (paNotInitialized+22); // original file portaudio.h
  115 + paCanNotReadFromACallbackStream = (paNotInitialized+23); {**< @todo review error code name *}
  116 + paCanNotWriteToACallbackStream = (paNotInitialized+24); {**< @todo review error code name *}
  117 + paCanNotReadFromAnOutputOnlyStream = (paNotInitialized+25); {**< @todo review error code name *}
  118 + paCanNotWriteToAnInputOnlyStream = (paNotInitialized+26); {**< @todo review error code name *}
  119 + paIncompatibleStreamHostApi = (paNotInitialized+27);
  120 + paBadBufferPtr = (paNotInitialized+28);
  121 +{enum_end PaErrorCode}
  122 +
  123 +
  124 +{** Translate the supplied PortAudio error code into a human readable
  125 + message.
  126 +*}
  127 +function Pa_GetErrorText( errorCode: TPaError ): PChar; cdecl; external LibName;
  128 +
  129 +
  130 +{** Library initialization function - call this before using PortAudio.
  131 + This function initialises internal data structures and prepares underlying
  132 + host APIs for use. With the exception of Pa_GetVersion(), Pa_GetVersionText(),
  133 + and Pa_GetErrorText(), this function MUST be called before using any other
  134 + PortAudio API functions.
  135 +
  136 + If Pa_Initialize() is called multiple times, each successful
  137 + call must be matched with a corresponding call to Pa_Terminate().
  138 + Pairs of calls to Pa_Initialize()/Pa_Terminate() may overlap, and are not
  139 + required to be fully nested.
  140 +
  141 + Note that if Pa_Initialize() returns an error code, Pa_Terminate() should
  142 + NOT be called.
  143 +
  144 + @return paNoError if successful, otherwise an error code indicating the cause
  145 + of failure.
  146 +
  147 + @see Pa_Terminate
  148 +*}
  149 +function Pa_Initialize(): TPaError; cdecl; external LibName;
  150 +
  151 +
  152 +{** Library termination function - call this when finished using PortAudio.
  153 + This function deallocates all resources allocated by PortAudio since it was
  154 + initializied by a call to Pa_Initialize(). In cases where Pa_Initialise() has
  155 + been called multiple times, each call must be matched with a corresponding call
  156 + to Pa_Terminate(). The final matching call to Pa_Terminate() will automatically
  157 + close any PortAudio streams that are still open.
  158 +
  159 + Pa_Terminate() MUST be called before exiting a program which uses PortAudio.
  160 + Failure to do so may result in serious resource leaks, such as audio devices
  161 + not being available until the next reboot.
  162 +
  163 + @return paNoError if successful, otherwise an error code indicating the cause
  164 + of failure.
  165 +
  166 + @see Pa_Initialize
  167 +*}
  168 +function Pa_Terminate(): TPaError; cdecl; external LibName;
  169 +
  170 +
  171 +
  172 +{** The type used to refer to audio devices. Values of this type usually
  173 + range from 0 to (Pa_GetDeviceCount()-1), and may also take on the PaNoDevice
  174 + and paUseHostApiSpecificDeviceSpecification values.
  175 +
  176 + @see Pa_GetDeviceCount, paNoDevice, paUseHostApiSpecificDeviceSpecification
  177 +*}
  178 +type TPaDeviceIndex = cint;
  179 +
  180 +
  181 +{** A special PaDeviceIndex value indicating that no device is available,
  182 + or should be used.
  183 +
  184 + @see PaDeviceIndex
  185 +*}
  186 +const paNoDevice = TPaDeviceIndex(-1);
  187 +
  188 +
  189 +{** A special PaDeviceIndex value indicating that the device(s) to be used
  190 + are specified in the host api specific stream info structure.
  191 +
  192 + @see PaDeviceIndex
  193 +*}
  194 +const paUseHostApiSpecificDeviceSpecification = TPaDeviceIndex(-2);
  195 +
  196 +
  197 +{* Host API enumeration mechanism *}
  198 +
  199 +{** The type used to enumerate to host APIs at runtime. Values of this type
  200 + range from 0 to (Pa_GetHostApiCount()-1).
  201 +
  202 + @see Pa_GetHostApiCount
  203 +*}
  204 +type TPaHostApiIndex = cint;
  205 +
  206 +{** Retrieve the number of available host APIs. Even if a host API is
  207 + available it may have no devices available.
  208 +
  209 + @return A non-negative value indicating the number of available host APIs
  210 + or, a PaErrorCode (which are always negative) if PortAudio is not initialized
  211 + or an error is encountered.
  212 +
  213 + @see PaHostApiIndex
  214 +*}
  215 +function Pa_GetHostApiCount(): TPaHostApiIndex; cdecl; external LibName;
  216 +
  217 +
  218 +{** Retrieve the index of the default host API. The default host API will be
  219 + the lowest common denominator host API on the current platform and is
  220 + unlikely to provide the best performance.
  221 +
  222 + @return A non-negative value ranging from 0 to (Pa_GetHostApiCount()-1)
  223 + indicating the default host API index or, a PaErrorCode (which are always
  224 + negative) if PortAudio is not initialized or an error is encountered.
  225 +*}
  226 +function Pa_GetDefaultHostApi(): TPaHostApiIndex; cdecl; external LibName;
  227 +
  228 +
  229 +{** Unchanging unique identifiers for each supported host API. This type
  230 + is used in the PaHostApiInfo structure. The values are guaranteed to be
  231 + unique and to never change, thus allowing code to be written that
  232 + conditionally uses host API specific extensions.
  233 +
  234 + New type ids will be allocated when support for a host API reaches
  235 + "public alpha" status, prior to that developers should use the
  236 + paInDevelopment type id.
  237 +
  238 + @see PaHostApiInfo
  239 +*}
  240 +type TPaHostApiTypeId = {enum}cint; const
  241 +{enum_begin PaHostApiTypeId}
  242 + paInDevelopment=0; {* use while developing support for a new host API *}
  243 + paDirectSound=1;
  244 + paMME=2;
  245 + paASIO=3;
  246 + paSoundManager=4;
  247 + paCoreAudio=5;
  248 + paOSS=7;
  249 + paALSA=8;
  250 + paAL=9;
  251 + paBeOS=10;
  252 + paWDMKS=11;
  253 + paJACK=12;
  254 + paWASAPI=13;
  255 + paAudioScienceHPI=14;
  256 +{enum_end PaHostApiTypeId}
  257 +
  258 +{** A structure containing information about a particular host API. *}
  259 +
  260 +type
  261 + PPaHostApiInfo = ^TPaHostApiInfo;
  262 + TPaHostApiInfo = record
  263 + {** this is struct version 1 *}
  264 + structVersion: cint;
  265 + {** The well known unique identifier of this host API @see PaHostApiTypeId *}
  266 + _type: TPaHostApiTypeId;
  267 + {** A textual description of the host API for display on user interfaces. *}
  268 + name: PChar;
  269 +
  270 + {** The number of devices belonging to this host API. This field may be
  271 + used in conjunction with Pa_HostApiDeviceIndexToDeviceIndex() to enumerate
  272 + all devices for this host API.
  273 + @see Pa_HostApiDeviceIndexToDeviceIndex
  274 + *}
  275 + deviceCount: cint;
  276 +
  277 + {** The default input device for this host API. The value will be a
  278 + device index ranging from 0 to (Pa_GetDeviceCount()-1), or paNoDevice
  279 + if no default input device is available.
  280 + *}
  281 + defaultInputDevice: TPaDeviceIndex;
  282 +
  283 + {** The default output device for this host API. The value will be a
  284 + device index ranging from 0 to (Pa_GetDeviceCount()-1), or paNoDevice
  285 + if no default output device is available.
  286 + *}
  287 + defaultOutputDevice: TPaDeviceIndex;
  288 + end;
  289 +
  290 +
  291 +{** Retrieve a pointer to a structure containing information about a specific
  292 + host Api.
  293 +
  294 + @param hostApi A valid host API index ranging from 0 to (Pa_GetHostApiCount()-1)
  295 +
  296 + @return A pointer to an immutable PaHostApiInfo structure describing
  297 + a specific host API. If the hostApi parameter is out of range or an error
  298 + is encountered, the function returns NULL.
  299 +
  300 + The returned structure is owned by the PortAudio implementation and must not
  301 + be manipulated or freed. The pointer is only guaranteed to be valid between
  302 + calls to Pa_Initialize() and Pa_Terminate().
  303 +*}
  304 +function Pa_GetHostApiInfo( hostApi: TPaHostApiIndex ): PPaHostApiInfo; cdecl; external LibName;
  305 +
  306 +
  307 +{** Convert a static host API unique identifier, into a runtime
  308 + host API index.
  309 +
  310 + @param type A unique host API identifier belonging to the PaHostApiTypeId
  311 + enumeration.
  312 +
  313 + @return A valid PaHostApiIndex ranging from 0 to (Pa_GetHostApiCount()-1) or,
  314 + a PaErrorCode (which are always negative) if PortAudio is not initialized
  315 + or an error is encountered.
  316 +
  317 + The paHostApiNotFound error code indicates that the host API specified by the
  318 + type parameter is not available.
  319 +
  320 + @see PaHostApiTypeId
  321 +*}
  322 +function Pa_HostApiTypeIdToHostApiIndex( _type: TPaHostApiTypeId ): TPaHostApiIndex; cdecl; external LibName;
  323 +
  324 +
  325 +{** Convert a host-API-specific device index to standard PortAudio device index.
  326 + This function may be used in conjunction with the deviceCount field of
  327 + PaHostApiInfo to enumerate all devices for the specified host API.
  328 +
  329 + @param hostApi A valid host API index ranging from 0 to (Pa_GetHostApiCount()-1)
  330 +
  331 + @param hostApiDeviceIndex A valid per-host device index in the range
  332 + 0 to (Pa_GetHostApiInfo(hostApi)->deviceCount-1)
  333 +
  334 + @return A non-negative PaDeviceIndex ranging from 0 to (Pa_GetDeviceCount()-1)
  335 + or, a PaErrorCode (which are always negative) if PortAudio is not initialized
  336 + or an error is encountered.
  337 +
  338 + A paInvalidHostApi error code indicates that the host API index specified by
  339 + the hostApi parameter is out of range.
  340 +
  341 + A paInvalidDevice error code indicates that the hostApiDeviceIndex parameter
  342 + is out of range.
  343 +
  344 + @see PaHostApiInfo
  345 +*}
  346 +function Pa_HostApiDeviceIndexToDeviceIndex( hostApi: TPaHostApiIndex;
  347 + hostApiDeviceIndex: cint ): TPaDeviceIndex; cdecl; external LibName;
  348 +
  349 +
  350 +
  351 +{** Structure used to return information about a host error condition.
  352 +*}
  353 +type
  354 + PPaHostErrorInfo = ^TPaHostErrorInfo;
  355 + TPaHostErrorInfo = record
  356 + hostApiType: TPaHostApiTypeId; {**< the host API which returned the error code *}
  357 + errorCode: clong; {**< the error code returned *}
  358 + errorText: PChar; {**< a textual description of the error if available, otherwise a zero-length string *}
  359 + end;
  360 +
  361 +
  362 +{** Return information about the last host error encountered. The error
  363 + information returned by Pa_GetLastHostErrorInfo() will never be modified
  364 + asyncronously by errors occurring in other PortAudio owned threads
  365 + (such as the thread that manages the stream callback.)
  366 +
  367 + This function is provided as a last resort, primarily to enhance debugging
  368 + by providing clients with access to all available error information.
  369 +
  370 + @return A pointer to an immutable structure constaining information about
  371 + the host error. The values in this structure will only be valid if a
  372 + PortAudio function has previously returned the paUnanticipatedHostError
  373 + error code.
  374 +*}
  375 +function Pa_GetLastHostErrorInfo(): PPaHostErrorInfo; cdecl; external LibName;
  376 +
  377 +
  378 +
  379 +{* Device enumeration and capabilities *}
  380 +
  381 +{** Retrieve the number of available devices. The number of available devices
  382 + may be zero.
  383 +
  384 + @return A non-negative value indicating the number of available devices or,
  385 + a PaErrorCode (which are always negative) if PortAudio is not initialized
  386 + or an error is encountered.
  387 +*}
  388 +function Pa_GetDeviceCount(): TPaDeviceIndex; cdecl; external LibName;
  389 +
  390 +
  391 +{** Retrieve the index of the default input device. The result can be
  392 + used in the inputDevice parameter to Pa_OpenStream().
  393 +
  394 + @return The default input device index for the default host API, or paNoDevice
  395 + if no default input device is available or an error was encountered.
  396 +*}
  397 +function Pa_GetDefaultInputDevice(): TPaDeviceIndex; cdecl; external LibName;
  398 +
  399 +
  400 +{** Retrieve the index of the default output device. The result can be
  401 + used in the outputDevice parameter to Pa_OpenStream().
  402 +
  403 + @return The default output device index for the defualt host API, or paNoDevice
  404 + if no default output device is available or an error was encountered.
  405 +
  406 + @note
  407 + On the PC, the user can specify a default device by
  408 + setting an environment variable. For example, to use device #1.
  409 +<pre>
  410 + set PA_RECOMMENDED_OUTPUT_DEVICE=1
  411 +</pre>
  412 + The user should first determine the available device ids by using
  413 + the supplied application "pa_devs".
  414 +*}
  415 +function Pa_GetDefaultOutputDevice(): TPaDeviceIndex; cdecl; external LibName;
  416 +
  417 +
  418 +{** The type used to represent monotonic time in seconds that can be used
  419 + for syncronisation. The type is used for the outTime argument to the
  420 + PaStreamCallback and as the result of Pa_GetStreamTime().
  421 +
  422 + @see PaStreamCallback, Pa_GetStreamTime
  423 +*}
  424 +type TPaTime = cdouble;
  425 +
  426 +
  427 +{** A type used to specify one or more sample formats. Each value indicates
  428 + a possible format for sound data passed to and from the stream callback,
  429 + Pa_ReadStream and Pa_WriteStream.
  430 +
  431 + The standard formats paFloat32, paInt16, paInt32, paInt24, paInt8
  432 + and aUInt8 are usually implemented by all implementations.
  433 +
  434 + The floating point representation (paFloat32) uses +1.0 and -1.0 as the
  435 + maximum and minimum respectively.
  436 +
  437 + paUInt8 is an unsigned 8 bit format where 128 is considered "ground"
  438 +
  439 + The paNonInterleaved flag indicates that a multichannel buffer is passed
  440 + as a set of non-interleaved pointers.
  441 +
  442 + @see Pa_OpenStream, Pa_OpenDefaultStream, PaDeviceInfo
  443 + @see paFloat32, paInt16, paInt32, paInt24, paInt8
  444 + @see paUInt8, paCustomFormat, paNonInterleaved
  445 +*}
  446 +type TPaSampleFormat = culong;
  447 +const
  448 + paFloat32 = TPaSampleFormat($00000001); {**< @see PaSampleFormat *}
  449 + paInt32 = TPaSampleFormat($00000002); {**< @see PaSampleFormat *}
  450 + paInt24 = TPaSampleFormat($00000004); {**< Packed 24 bit format. @see PaSampleFormat *}
  451 + paInt16 = TPaSampleFormat($00000008); {**< @see PaSampleFormat *}
  452 + paInt8 = TPaSampleFormat($00000010); {**< @see PaSampleFormat *}
  453 + paUInt8 = TPaSampleFormat($00000020); {**< @see PaSampleFormat *}
  454 + paCustomFormat = TPaSampleFormat($00010000); {**< @see PaSampleFormat *}
  455 + paNonInterleaved = TPaSampleFormat($80000000);
  456 +
  457 +{** A structure providing information and capabilities of PortAudio devices.
  458 + Devices may support input, output or both input and output.
  459 +*}
  460 +type
  461 + PPaDeviceInfo = ^TPaDeviceInfo;
  462 + TPaDeviceInfo = record
  463 + structVersion: cint; {* this is struct version 2 *}
  464 + name: PChar;
  465 + hostApi: TPaHostApiIndex; {* note this is a host API index, not a type id*}
  466 +
  467 + maxInputChannels: cint;
  468 + maxOutputChannels: cint;
  469 +
  470 + {* Default latency values for interactive performance. *}
  471 + defaultLowInputLatency: TPaTime;
  472 + defaultLowOutputLatency: TPaTime;
  473 + {* Default latency values for robust non-interactive applications (eg. playing sound files). *}
  474 + defaultHighInputLatency: TPaTime;
  475 + defaultHighOutputLatency: TPaTime;
  476 +
  477 + defaultSampleRate: cdouble;
  478 + end;
  479 +
  480 +
  481 +{** Retrieve a pointer to a PaDeviceInfo structure containing information
  482 + about the specified device.
  483 + @return A pointer to an immutable PaDeviceInfo structure. If the device
  484 + parameter is out of range the function returns NULL.
  485 +
  486 + @param device A valid device index in the range 0 to (Pa_GetDeviceCount()-1)
  487 +
  488 + @note PortAudio manages the memory referenced by the returned pointer,
  489 + the client must not manipulate or free the memory. The pointer is only
  490 + guaranteed to be valid between calls to Pa_Initialize() and Pa_Terminate().
  491 +
  492 + @see PaDeviceInfo, PaDeviceIndex
  493 +*}
  494 +function Pa_GetDeviceInfo( device: TPaDeviceIndex ): PPaDeviceInfo; cdecl; external LibName;
  495 +
  496 +
  497 +{** Parameters for one direction (input or output) of a stream.
  498 +*}
  499 +type
  500 + PPaStreamParameters = ^TPaStreamParameters;
  501 + TPaStreamParameters = record
  502 + {** A valid device index in the range 0 to (Pa_GetDeviceCount()-1)
  503 + specifying the device to be used or the special constant
  504 + paUseHostApiSpecificDeviceSpecification which indicates that the actual
  505 + device(s) to use are specified in hostApiSpecificStreamInfo.
  506 + This field must not be set to paNoDevice.
  507 + *}
  508 + device: TPaDeviceIndex;
  509 +
  510 + {** The number of channels of sound to be delivered to the
  511 + stream callback or accessed by Pa_ReadStream() or Pa_WriteStream().
  512 + It can range from 1 to the value of maxInputChannels in the
  513 + PaDeviceInfo record for the device specified by the device parameter.
  514 + *}
  515 + channelCount: cint;
  516 +
  517 + {** The sample format of the buffer provided to the stream callback,
  518 + a_ReadStream() or Pa_WriteStream(). It may be any of the formats described
  519 + by the PaSampleFormat enumeration.
  520 + *}
  521 + sampleFormat: TPaSampleFormat;
  522 +
  523 + {** The desired latency in seconds. Where practical, implementations should
  524 + configure their latency based on these parameters, otherwise they may
  525 + choose the closest viable latency instead. Unless the suggested latency
  526 + is greater than the absolute upper limit for the device implementations
  527 + should round the suggestedLatency up to the next practial value - ie to
  528 + provide an equal or higher latency than suggestedLatency wherever possibe.
  529 + Actual latency values for an open stream may be retrieved using the
  530 + inputLatency and outputLatency fields of the PaStreamInfo structure
  531 + returned by Pa_GetStreamInfo().
  532 + @see default*Latency in PaDeviceInfo, *Latency in PaStreamInfo
  533 + *}
  534 + suggestedLatency: TPaTime;
  535 +
  536 + {** An optional pointer to a host api specific data structure
  537 + containing additional information for device setup and/or stream processing.
  538 + hostApiSpecificStreamInfo is never required for correct operation,
  539 + if not used it should be set to NULL.
  540 + *}
  541 + hostApiSpecificStreamInfo: Pointer;
  542 + end;
  543 +
  544 +
  545 +{** Return code for Pa_IsFormatSupported indicating success. *}
  546 +const paFormatIsSupported = (0);
  547 +
  548 +{** Determine whether it would be possible to open a stream with the specified
  549 + parameters.
  550 +
  551 + @param inputParameters A structure that describes the input parameters used to
  552 + open a stream. The suggestedLatency field is ignored. See PaStreamParameters
  553 + for a description of these parameters. inputParameters must be NULL for
  554 + output-only streams.
  555 +
  556 + @param outputParameters A structure that describes the output parameters used
  557 + to open a stream. The suggestedLatency field is ignored. See PaStreamParameters
  558 + for a description of these parameters. outputParameters must be NULL for
  559 + input-only streams.
  560 +
  561 + @param sampleRate The required sampleRate. For full-duplex streams it is the
  562 + sample rate for both input and output
  563 +
  564 + @return Returns 0 if the format is supported, and an error code indicating why
  565 + the format is not supported otherwise. The constant paFormatIsSupported is
  566 + provided to compare with the return value for success.
  567 +
  568 + @see paFormatIsSupported, PaStreamParameters
  569 +*}
  570 +function Pa_IsFormatSupported( inputParameters: PPaStreamParameters;
  571 + outputParameters: PPaStreamParameters;
  572 + sampleRate: cdouble ): TPaError; cdecl; external LibName;
  573 +
  574 +
  575 +
  576 +{* Streaming types and functions *}
  577 +
  578 +
  579 +{**
  580 + A single PaStream can provide multiple channels of real-time
  581 + streaming audio input and output to a client application. A stream
  582 + provides access to audio hardware represented by one or more
  583 + PaDevices. Depending on the underlying Host API, it may be possible
  584 + to open multiple streams using the same device, however this behavior
  585 + is implementation defined. Portable applications should assume that
  586 + a PaDevice may be simultaneously used by at most one PaStream.
  587 +
  588 + Pointers to PaStream objects are passed between PortAudio functions that
  589 + operate on streams.
  590 +
  591 + @see Pa_OpenStream, Pa_OpenDefaultStream, Pa_OpenDefaultStream, Pa_CloseStream,
  592 + Pa_StartStream, Pa_StopStream, Pa_AbortStream, Pa_IsStreamActive,
  593 + Pa_GetStreamTime, Pa_GetStreamCpuLoad
  594 +
  595 +*}
  596 +type
  597 + PPaStream = Pointer;
  598 +
  599 +{** Can be passed as the framesPerBuffer parameter to Pa_OpenStream()
  600 + or Pa_OpenDefaultStream() to indicate that the stream callback will
  601 + accept buffers of any size.
  602 +*}
  603 +const paFramesPerBufferUnspecified = (0);
  604 +
  605 +
  606 +{** Flags used to control the behavior of a stream. They are passed as
  607 + parameters to Pa_OpenStream or Pa_OpenDefaultStream. Multiple flags may be
  608 + ORed together.
  609 +
  610 + @see Pa_OpenStream, Pa_OpenDefaultStream
  611 + @see paNoFlag, paClipOff, paDitherOff, paNeverDropInput,
  612 + paPrimeOutputBuffersUsingStreamCallback, paPlatformSpecificFlags
  613 +*}
  614 +type TPaStreamFlags = culong;
  615 +
  616 +{** @see PaStreamFlags *}
  617 +const paNoFlag = TPaStreamFlags(0);
  618 +
  619 +{** Disable default clipping of out of range samples.
  620 + @see PaStreamFlags
  621 +*}
  622 +const paClipOff = TPaStreamFlags($00000001);
  623 +
  624 +{** Disable default dithering.
  625 + @see PaStreamFlags
  626 +*}
  627 +const paDitherOff = TPaStreamFlags($00000002);
  628 +
  629 +{** Flag requests that where possible a full duplex stream will not discard
  630 + overflowed input samples without calling the stream callback. This flag is
  631 + only valid for full duplex callback streams and only when used in combination
  632 + with the paFramesPerBufferUnspecified (0) framesPerBuffer parameter. Using
  633 + this flag incorrectly results in a paInvalidFlag error being returned from
  634 + Pa_OpenStream and Pa_OpenDefaultStream.
  635 +
  636 + @see PaStreamFlags, paFramesPerBufferUnspecified
  637 +*}
  638 +const paNeverDropInput = TPaStreamFlags($00000004);
  639 +
  640 +{** Call the stream callback to fill initial output buffers, rather than the
  641 + default behavior of priming the buffers with zeros (silence). This flag has
  642 + no effect for input-only and blocking read/write streams.
  643 +
  644 + @see PaStreamFlags
  645 +*}
  646 +const paPrimeOutputBuffersUsingStreamCallback = TPaStreamFlags($00000008);
  647 +
  648 +{** A mask specifying the platform specific bits.
  649 + @see PaStreamFlags
  650 +*}
  651 +const paPlatformSpecificFlags = TPaStreamFlags($FFFF0000);
  652 +
  653 +{**
  654 + Timing information for the buffers passed to the stream callback.
  655 +*}
  656 +type
  657 + PPaStreamCallbackTimeInfo = ^TPaStreamCallbackTimeInfo;
  658 + TPaStreamCallbackTimeInfo = record
  659 + inputBufferAdcTime: TPaTime;
  660 + currentTime: TPaTime;
  661 + outputBufferDacTime: TPaTime;
  662 + end;
  663 +
  664 +
  665 +{**
  666 + Flag bit constants for the statusFlags to PaStreamCallback.
  667 +
  668 + @see paInputUnderflow, paInputOverflow, paOutputUnderflow, paOutputOverflow,
  669 + paPrimingOutput
  670 +*}
  671 +type TPaStreamCallbackFlags = culong;
  672 +
  673 +{** In a stream opened with paFramesPerBufferUnspecified, indicates that
  674 + input data is all silence (zeros) because no real data is available. In a
  675 + stream opened without paFramesPerBufferUnspecified, it indicates that one or
  676 + more zero samples have been inserted into the input buffer to compensate
  677 + for an input underflow.
  678 + @see PaStreamCallbackFlags
  679 +*}
  680 +const paInputUnderflow = TPaStreamCallbackFlags($00000001);
  681 +
  682 +{** In a stream opened with paFramesPerBufferUnspecified, indicates that data
  683 + prior to the first sample of the input buffer was discarded due to an
  684 + overflow, possibly because the stream callback is using too much CPU time.
  685 + Otherwise indicates that data prior to one or more samples in the
  686 + input buffer was discarded.
  687 + @see PaStreamCallbackFlags
  688 +*}
  689 +const paInputOverflow = TPaStreamCallbackFlags($00000002);
  690 +
  691 +{** Indicates that output data (or a gap) was inserted, possibly because the
  692 + stream callback is using too much CPU time.
  693 + @see PaStreamCallbackFlags
  694 +*}
  695 +const paOutputUnderflow = TPaStreamCallbackFlags($00000004);
  696 +
  697 +{** Indicates that output data will be discarded because no room is available.
  698 + @see PaStreamCallbackFlags
  699 +*}
  700 +const paOutputOverflow = TPaStreamCallbackFlags($00000008);
  701 +
  702 +{** Some of all of the output data will be used to prime the stream, input
  703 + data may be zero.
  704 + @see PaStreamCallbackFlags
  705 +*}
  706 +const paPrimingOutput = TPaStreamCallbackFlags($00000010);
  707 +
  708 +{**
  709 + Allowable return values for the PaStreamCallback.
  710 + @see PaStreamCallback
  711 +*}
  712 +type TPaStreamCallbackResult = {enum}cint; const
  713 +{enum_begin PaStreamCallbackResult}
  714 + paContinue=0;
  715 + paComplete=1;
  716 + paAbort=2;
  717 +{enum_end PaStreamCallbackResult}
  718 +
  719 +{**
  720 + Functions of type PaStreamCallback are implemented by PortAudio clients.
  721 + They consume, process or generate audio in response to requests from an
  722 + active PortAudio stream.
  723 +
  724 + @param input and @param output are arrays of interleaved samples,
  725 + the format, packing and number of channels used by the buffers are
  726 + determined by parameters to Pa_OpenStream().
  727 +
  728 + @param frameCount The number of sample frames to be processed by
  729 + the stream callback.
  730 +
  731 + @param timeInfo The time in seconds when the first sample of the input
  732 + buffer was received at the audio input, the time in seconds when the first
  733 + sample of the output buffer will begin being played at the audio output, and
  734 + the time in seconds when the stream callback was called.
  735 + See also Pa_GetStreamTime()
  736 +
  737 + @param statusFlags Flags indicating whether input and/or output buffers
  738 + have been inserted or will be dropped to overcome underflow or overflow
  739 + conditions.
  740 +
  741 + @param userData The value of a user supplied pointer passed to
  742 + Pa_OpenStream() intended for storing synthesis data etc.
  743 +
  744 + @return
  745 + The stream callback should return one of the values in the
  746 + PaStreamCallbackResult enumeration. To ensure that the callback continues
  747 + to be called, it should return paContinue (0). Either paComplete or paAbort
  748 + can be returned to finish stream processing, after either of these values is
  749 + returned the callback will not be called again. If paAbort is returned the
  750 + stream will finish as soon as possible. If paComplete is returned, the stream
  751 + will continue until all buffers generated by the callback have been played.
  752 + This may be useful in applications such as soundfile players where a specific
  753 + duration of output is required. However, it is not necessary to utilise this
  754 + mechanism as Pa_StopStream(), Pa_AbortStream() or Pa_CloseStream() can also
  755 + be used to stop the stream. The callback must always fill the entire output
  756 + buffer irrespective of its return value.
  757 +
  758 + @see Pa_OpenStream, Pa_OpenDefaultStream
  759 +
  760 + @note With the exception of Pa_GetStreamCpuLoad() it is not permissable to call
  761 + PortAudio API functions from within the stream callback.
  762 +*}
  763 +type
  764 + PPaStreamCallback = ^TPaStreamCallback;
  765 + TPaStreamCallback = function(
  766 + input: Pointer; output: Pointer;
  767 + frameCount: culong;
  768 + timeInfo: PPaStreamCallbackTimeInfo;
  769 + statusFlags: TPaStreamCallbackFlags;
  770 + userData: Pointer ): cint; cdecl;
  771 +
  772 +
  773 +{** Opens a stream for either input, output or both.
  774 +
  775 + @param stream The address of a PaStream pointer which will receive
  776 + a pointer to the newly opened stream.
  777 +
  778 + @param inputParameters A structure that describes the input parameters used by
  779 + the opened stream. See PaStreamParameters for a description of these parameters.
  780 + inputParameters must be NULL for output-only streams.
  781 +
  782 + @param outputParameters A structure that describes the output parameters used by
  783 + the opened stream. See PaStreamParameters for a description of these parameters.
  784 + outputParameters must be NULL for input-only streams.
  785 +
  786 + @param sampleRate The desired sampleRate. For full-duplex streams it is the
  787 + sample rate for both input and output
  788 +
  789 + @param framesPerBuffer The number of frames passed to the stream callback
  790 + function, or the preferred block granularity for a blocking read/write stream.
  791 + The special value paFramesPerBufferUnspecified (0) may be used to request that
  792 + the stream callback will recieve an optimal (and possibly varying) number of
  793 + frames based on host requirements and the requested latency settings.
  794 + Note: With some host APIs, the use of non-zero framesPerBuffer for a callback
  795 + stream may introduce an additional layer of buffering which could introduce
  796 + additional latency. PortAudio guarantees that the additional latency
  797 + will be kept to the theoretical minimum however, it is strongly recommended
  798 + that a non-zero framesPerBuffer value only be used when your algorithm
  799 + requires a fixed number of frames per stream callback.
  800 +
  801 + @param streamFlags Flags which modify the behaviour of the streaming process.
  802 + This parameter may contain a combination of flags ORed together. Some flags may
  803 + only be relevant to certain buffer formats.
  804 +
  805 + @param streamCallback A pointer to a client supplied function that is responsible
  806 + for processing and filling input and output buffers. If this parameter is NULL
  807 + the stream will be opened in 'blocking read/write' mode. In blocking mode,
  808 + the client can receive sample data using Pa_ReadStream and write sample data
  809 + using Pa_WriteStream, the number of samples that may be read or written
  810 + without blocking is returned by Pa_GetStreamReadAvailable and
  811 + Pa_GetStreamWriteAvailable respectively.
  812 +
  813 + @param userData A client supplied pointer which is passed to the stream callback
  814 + function. It could for example, contain a pointer to instance data necessary
  815 + for processing the audio buffers. This parameter is ignored if streamCallback
  816 + is NULL.
  817 +
  818 + @return
  819 + Upon success Pa_OpenStream() returns paNoError and places a pointer to a
  820 + valid PaStream in the stream argument. The stream is inactive (stopped).
  821 + If a call to Pa_OpenStream() fails, a non-zero error code is returned (see
  822 + PaError for possible error codes) and the value of stream is invalid.
  823 +
  824 + @see PaStreamParameters, PaStreamCallback, Pa_ReadStream, Pa_WriteStream,
  825 + Pa_GetStreamReadAvailable, Pa_GetStreamWriteAvailable
  826 +*}
  827 +function Pa_OpenStream( var stream: PPaStream;
  828 + inputParameters: PPaStreamParameters;
  829 + outputParameters: PPaStreamParameters;
  830 + sampleRate: cdouble;
  831 + framesPerBuffer: culong;
  832 + streamFlags: TPaStreamFlags;
  833 + streamCallback: PPaStreamCallback;
  834 + userData: Pointer ): TPaError; cdecl; external LibName;
  835 +
  836 +
  837 +{** A simplified version of Pa_OpenStream() that opens the default input
  838 + and/or output devices.
  839 +
  840 + @param stream The address of a PaStream pointer which will receive
  841 + a pointer to the newly opened stream.
  842 +
  843 + @param numInputChannels The number of channels of sound that will be supplied
  844 + to the stream callback or returned by Pa_ReadStream. It can range from 1 to
  845 + the value of maxInputChannels in the PaDeviceInfo record for the default input
  846 + device. If 0 the stream is opened as an output-only stream.
  847 +
  848 + @param numOutputChannels The number of channels of sound to be delivered to the
  849 + stream callback or passed to Pa_WriteStream. It can range from 1 to the value
  850 + of maxOutputChannels in the PaDeviceInfo record for the default output dvice.
  851 + If 0 the stream is opened as an output-only stream.
  852 +
  853 + @param sampleFormat The sample format of both the input and output buffers
  854 + provided to the callback or passed to and from Pa_ReadStream and Pa_WriteStream.
  855 + sampleFormat may be any of the formats described by the PaSampleFormat
  856 + enumeration.
  857 +
  858 + @param sampleRate Same as Pa_OpenStream parameter of the same name.
  859 + @param framesPerBuffer Same as Pa_OpenStream parameter of the same name.
  860 + @param streamCallback Same as Pa_OpenStream parameter of the same name.
  861 + @param userData Same as Pa_OpenStream parameter of the same name.
  862 +
  863 + @return As for Pa_OpenStream
  864 +
  865 + @see Pa_OpenStream, PaStreamCallback
  866 +*}
  867 +function Pa_OpenDefaultStream( var stream: PPaStream;
  868 + numInputChannels: cint;
  869 + numOutputChannels: cint;
  870 + sampleFormat: TPaSampleFormat;
  871 + sampleRate: cdouble;
  872 + framesPerBuffer: culong;
  873 + streamCallback: PPaStreamCallback;
  874 + userData: Pointer ): TPaError; cdecl; external LibName;
  875 +
  876 +
  877 +{** Closes an audio stream. If the audio stream is active it
  878 + discards any pending buffers as if Pa_AbortStream() had been called.
  879 +*}
  880 +function Pa_CloseStream( stream: PPaStream ): TPaError; cdecl; external LibName;
  881 +
  882 +
  883 +{** Functions of type PaStreamFinishedCallback are implemented by PortAudio
  884 + clients. They can be registered with a stream using the Pa_SetStreamFinishedCallback
  885 + function. Once registered they are called when the stream becomes inactive
  886 + (ie once a call to Pa_StopStream() will not block).
  887 + A stream will become inactive after the stream callback returns non-zero,
  888 + or when Pa_StopStream or Pa_AbortStream is called. For a stream providing audio
  889 + output, if the stream callback returns paComplete, or Pa_StopStream is called,
  890 + the stream finished callback will not be called until all generated sample data
  891 + has been played.
  892 +
  893 + @param userData The userData parameter supplied to Pa_OpenStream()
  894 +
  895 + @see Pa_SetStreamFinishedCallback
  896 +*}
  897 +type
  898 + PPaStreamFinishedCallback = ^TPaStreamFinishedCallback;
  899 + TPaStreamFinishedCallback = procedure( userData: Pointer ); cdecl;
  900 +
  901 +
  902 +{** Register a stream finished callback function which will be called when the
  903 + stream becomes inactive. See the description of PaStreamFinishedCallback for
  904 + further details about when the callback will be called.
  905 +
  906 + @param stream a pointer to a PaStream that is in the stopped state - if the
  907 + stream is not stopped, the stream's finished callback will remain unchanged
  908 + and an error code will be returned.
  909 +
  910 + @param streamFinishedCallback a pointer to a function with the same signature
  911 + as PaStreamFinishedCallback, that will be called when the stream becomes
  912 + inactive. Passing NULL for this parameter will un-register a previously
  913 + registered stream finished callback function.
  914 +
  915 + @return on success returns paNoError, otherwise an error code indicating the cause
  916 + of the error.
  917 +
  918 + @see PaStreamFinishedCallback
  919 +*}
  920 +function Pa_SetStreamFinishedCallback( stream: PPaStream;
  921 + streamFinishedCallback: PPaStreamFinishedCallback ): TPaError; cdecl; external LibName;
  922 +
  923 +
  924 +{** Commences audio processing.
  925 +*}
  926 +function Pa_StartStream( stream: PPaStream ): TPaError; cdecl; external LibName;
  927 +
  928 +
  929 +{** Terminates audio processing. It waits until all pending
  930 + audio buffers have been played before it returns.
  931 +*}
  932 +function Pa_StopStream( stream: PPaStream ): TPaError; cdecl; external LibName;
  933 +
  934 +
  935 +{** Terminates audio processing immediately without waiting for pending
  936 + buffers to complete.
  937 +*}
  938 +function Pa_AbortStream( stream: PPaStream ): TPaError; cdecl; external LibName;
  939 +
  940 +
  941 +{** Determine whether the stream is stopped.
  942 + A stream is considered to be stopped prior to a successful call to
  943 + Pa_StartStream and after a successful call to Pa_StopStream or Pa_AbortStream.
  944 + If a stream callback returns a value other than paContinue the stream is NOT
  945 + considered to be stopped.
  946 +
  947 + @return Returns one (1) when the stream is stopped, zero (0) when
  948 + the stream is running or, a PaErrorCode (which are always negative) if
  949 + PortAudio is not initialized or an error is encountered.
  950 +
  951 + @see Pa_StopStream, Pa_AbortStream, Pa_IsStreamActive
  952 +*}
  953 +function Pa_IsStreamStopped( stream: PPaStream ): TPaError; cdecl; external LibName;
  954 +
  955 +
  956 +{** Determine whether the stream is active.
  957 + A stream is active after a successful call to Pa_StartStream(), until it
  958 + becomes inactive either as a result of a call to Pa_StopStream() or
  959 + Pa_AbortStream(), or as a result of a return value other than paContinue from
  960 + the stream callback. In the latter case, the stream is considered inactive
  961 + after the last buffer has finished playing.
  962 +
  963 + @return Returns one (1) when the stream is active (ie playing or recording
  964 + audio), zero (0) when not playing or, a PaErrorCode (which are always negative)
  965 + if PortAudio is not initialized or an error is encountered.
  966 +
  967 + @see Pa_StopStream, Pa_AbortStream, Pa_IsStreamStopped
  968 +*}
  969 +function Pa_IsStreamActive( stream: PPaStream ): TPaError; cdecl; external LibName;
  970 +
  971 +
  972 +
  973 +{** A structure containing unchanging information about an open stream.
  974 + @see Pa_GetStreamInfo
  975 +*}
  976 +type
  977 + PPaStreamInfo = ^TPaStreamInfo;
  978 + TPaStreamInfo = record
  979 + {** this is struct version 1 *}
  980 + structVersion: cint;
  981 +
  982 + {** The input latency of the stream in seconds. This value provides the most
  983 + accurate estimate of input latency available to the implementation. It may
  984 + differ significantly from the suggestedLatency value passed to Pa_OpenStream().
  985 + The value of this field will be zero (0.) for output-only streams.
  986 + @see PaTime
  987 + *}
  988 + inputLatency: TPaTime;
  989 +
  990 + {** The output latency of the stream in seconds. This value provides the most
  991 + accurate estimate of output latency available to the implementation. It may
  992 + differ significantly from the suggestedLatency value passed to Pa_OpenStream().
  993 + The value of this field will be zero (0.) for input-only streams.
  994 + @see PaTime
  995 + *}
  996 + outputLatency: TPaTime;
  997 +
  998 + {** The sample rate of the stream in Hertz (samples per second). In cases
  999 + where the hardware sample rate is inaccurate and PortAudio is aware of it,
  1000 + the value of this field may be different from the sampleRate parameter
  1001 + passed to Pa_OpenStream(). If information about the actual hardware sample
  1002 + rate is not available, this field will have the same value as the sampleRate
  1003 + parameter passed to Pa_OpenStream().
  1004 + *}
  1005 + sampleRate: cdouble;
  1006 + end;
  1007 +
  1008 +
  1009 +{** Retrieve a pointer to a PaStreamInfo structure containing information
  1010 + about the specified stream.
  1011 + @return A pointer to an immutable PaStreamInfo structure. If the stream
  1012 + parameter invalid, or an error is encountered, the function returns NULL.
  1013 +
  1014 + @param stream A pointer to an open stream previously created with Pa_OpenStream.
  1015 +
  1016 + @note PortAudio manages the memory referenced by the returned pointer,
  1017 + the client must not manipulate or free the memory. The pointer is only
  1018 + guaranteed to be valid until the specified stream is closed.
  1019 +
  1020 + @see PaStreamInfo
  1021 +*}
  1022 +function Pa_GetStreamInfo( stream: PPaStream ): PPaStreamInfo; cdecl; external LibName;
  1023 +
  1024 +
  1025 +{** Determine the current time for the stream according to the same clock used
  1026 + to generate buffer timestamps. This time may be used for syncronising other
  1027 + events to the audio stream, for example synchronizing audio to MIDI.
  1028 +
  1029 + @return The stream's current time in seconds, or 0 if an error occurred.
  1030 +
  1031 + @see PaTime, PaStreamCallback
  1032 +*}
  1033 +function Pa_GetStreamTime( stream: PPaStream ): TPaTime; cdecl; external LibName;
  1034 +
  1035 +
  1036 +{** Retrieve CPU usage information for the specified stream.
  1037 + The "CPU Load" is a fraction of total CPU time consumed by a callback stream's
  1038 + audio processing routines including, but not limited to the client supplied
  1039 + stream callback. This function does not work with blocking read/write streams.
  1040 +
  1041 + This function may be called from the stream callback function or the
  1042 + application.
  1043 +
  1044 + @return
  1045 + A floating point value, typically between 0.0 and 1.0, where 1.0 indicates
  1046 + that the stream callback is consuming the maximum number of CPU cycles possible
  1047 + to maintain real-time operation. A value of 0.5 would imply that PortAudio and
  1048 + the stream callback was consuming roughly 50% of the available CPU time. The
  1049 + return value may exceed 1.0. A value of 0.0 will always be returned for a
  1050 + blocking read/write stream, or if an error occurrs.
  1051 +*}
  1052 +function Pa_GetStreamCpuLoad( stream: PPaStream ): cdouble; cdecl; external LibName;
  1053 +
  1054 +
  1055 +{** Read samples from an input stream. The function doesn't return until
  1056 + the entire buffer has been filled - this may involve waiting for the operating
  1057 + system to supply the data.
  1058 +
  1059 + @param stream A pointer to an open stream previously created with Pa_OpenStream.
  1060 +
  1061 + @param buffer A pointer to a buffer of sample frames. The buffer contains
  1062 + samples in the format specified by the inputParameters->sampleFormat field
  1063 + used to open the stream, and the number of channels specified by
  1064 + inputParameters->numChannels. If non-interleaved samples were requested,
  1065 + buffer is a pointer to the first element of an array of non-interleaved
  1066 + buffer pointers, one for each channel.
  1067 +
  1068 + @param frames The number of frames to be read into buffer. This parameter
  1069 + is not constrained to a specific range, however high performance applications
  1070 + will want to match this parameter to the framesPerBuffer parameter used
  1071 + when opening the stream.
  1072 +
  1073 + @return On success PaNoError will be returned, or PaInputOverflowed if input
  1074 + data was discarded by PortAudio after the previous call and before this call.
  1075 +*}
  1076 +function Pa_ReadStream( stream: PPaStream;
  1077 + buffer: Pointer;
  1078 + frames: culong ): TPaError; cdecl; external LibName;
  1079 +
  1080 +
  1081 +{** Write samples to an output stream. This function doesn't return until the
  1082 + entire buffer has been consumed - this may involve waiting for the operating
  1083 + system to consume the data.
  1084 +
  1085 + @param stream A pointer to an open stream previously created with Pa_OpenStream.
  1086 +
  1087 + @param buffer A pointer to a buffer of sample frames. The buffer contains
  1088 + samples in the format specified by the outputParameters->sampleFormat field
  1089 + used to open the stream, and the number of channels specified by
  1090 + outputParameters->numChannels. If non-interleaved samples were requested,
  1091 + buffer is a pointer to the first element of an array of non-interleaved
  1092 + buffer pointers, one for each channel.
  1093 +
  1094 + @param frames The number of frames to be written from buffer. This parameter
  1095 + is not constrained to a specific range, however high performance applications
  1096 + will want to match this parameter to the framesPerBuffer parameter used
  1097 + when opening the stream.
  1098 +
  1099 + @return On success PaNoError will be returned, or paOutputUnderflowed if
  1100 + additional output data was inserted after the previous call and before this
  1101 + call.
  1102 +*}
  1103 +function Pa_WriteStream( stream: PPaStream;
  1104 + buffer: Pointer;
  1105 + frames: culong ): TPaError; cdecl; external LibName;
  1106 +
  1107 +
  1108 +{** Retrieve the number of frames that can be read from the stream without
  1109 + waiting.
  1110 +
  1111 + @return Returns a non-negative value representing the maximum number of frames
  1112 + that can be read from the stream without blocking or busy waiting or, a
  1113 + PaErrorCode (which are always negative) if PortAudio is not initialized or an
  1114 + error is encountered.
  1115 +*}
  1116 +function Pa_GetStreamReadAvailable( stream: PPaStream ): cslong; cdecl; external LibName;
  1117 +
  1118 +
  1119 +{** Retrieve the number of frames that can be written to the stream without
  1120 + waiting.
  1121 +
  1122 + @return Returns a non-negative value representing the maximum number of frames
  1123 + that can be written to the stream without blocking or busy waiting or, a
  1124 + PaErrorCode (which are always negative) if PortAudio is not initialized or an
  1125 + error is encountered.
  1126 +*}
  1127 +function Pa_GetStreamWriteAvailable( stream: PPaStream ): cslong; cdecl; external LibName;
  1128 +
  1129 +
  1130 +{** Retrieve the host type handling an open stream.
  1131 +
  1132 + @return Returns a non-negative value representing the host API type
  1133 + handling an open stream or, a PaErrorCode (which are always negative)
  1134 + if PortAudio is not initialized or an error is encountered.
  1135 +*}
  1136 +function Pa_GetStreamHostApiType( stream: PPaStream ): TPaHostApiTypeId; cdecl; external LibName;
  1137 +
  1138 +
  1139 +{* Miscellaneous utilities *}
  1140 +
  1141 +
  1142 +{** Retrieve the size of a given sample format in bytes.
  1143 +
  1144 + @return The size in bytes of a single sample in the specified format,
  1145 + or paSampleFormatNotSupported if the format is not supported.
  1146 +*}
  1147 +function Pa_GetSampleSize( format: TPaSampleFormat ): TPaError; cdecl; external LibName;
  1148 +
  1149 +
  1150 +{** Put the caller to sleep for at least 'msec' milliseconds. This function is
  1151 + provided only as a convenience for authors of portable code (such as the tests
  1152 + and examples in the PortAudio distribution.)
  1153 +
  1154 + The function may sleep longer than requested so don't rely on this for accurate
  1155 + musical timing.
  1156 +*}
  1157 +procedure Pa_Sleep( msec: clong ); cdecl; external LibName;
  1158 +
  1159 +implementation
  1160 +
  1161 +end.
@@ -10,6 +10,8 @@ unit sherpa_onnx; @@ -10,6 +10,8 @@ unit sherpa_onnx;
10 (* {$LongStrings ON} *) 10 (* {$LongStrings ON} *)
11 11
12 interface 12 interface
  13 +uses
  14 + ctypes;
13 15
14 type 16 type
15 TSherpaOnnxWave = record 17 TSherpaOnnxWave = record
@@ -260,7 +262,8 @@ type @@ -260,7 +262,8 @@ type
260 public 262 public
261 constructor Create(Capacity: Integer); 263 constructor Create(Capacity: Integer);
262 destructor Destroy; override; 264 destructor Destroy; override;
263 - procedure Push(Samples: array of Single); 265 + procedure Push(Samples: array of Single); overload;
  266 + procedure Push(Samples: pcfloat; N: Integer); overload;
264 function Get(StartIndex: Integer; N: Integer): TSherpaOnnxSamplesArray; 267 function Get(StartIndex: Integer; N: Integer): TSherpaOnnxSamplesArray;
265 procedure Pop(N: Integer); 268 procedure Pop(N: Integer);
266 procedure Reset; 269 procedure Reset;
@@ -305,7 +308,6 @@ type @@ -305,7 +308,6 @@ type
305 implementation 308 implementation
306 309
307 uses 310 uses
308 - ctypes,  
309 fpjson, 311 fpjson,
310 { See 312 { See
311 - https://wiki.freepascal.org/fcl-json 313 - https://wiki.freepascal.org/fcl-json
@@ -1323,6 +1325,11 @@ begin @@ -1323,6 +1325,11 @@ begin
1323 SherpaOnnxCircularBufferPush(Self.Handle, pcfloat(Samples), Length(Samples)); 1325 SherpaOnnxCircularBufferPush(Self.Handle, pcfloat(Samples), Length(Samples));
1324 end; 1326 end;
1325 1327
  1328 +procedure TSherpaOnnxCircularBuffer.Push(Samples: pcfloat; N: Integer);
  1329 +begin
  1330 + SherpaOnnxCircularBufferPush(Self.Handle, Samples, N);
  1331 +end;
  1332 +
1326 function TSherpaOnnxCircularBuffer.Get(StartIndex: Integer; N: Integer): TSherpaOnnxSamplesArray; 1333 function TSherpaOnnxCircularBuffer.Get(StartIndex: Integer; N: Integer): TSherpaOnnxSamplesArray;
1327 var 1334 var
1328 P: pcfloat; 1335 P: pcfloat;