1 | {This unit is part of United Openlibraries of Sound (uos)}
|
---|
2 |
|
---|
3 | {This is the Dynamic loading version of PortAudio Pascal Wrapper.
|
---|
4 | Load library with pa_load() and release with pa_unload().
|
---|
5 | License : modified LGPL.
|
---|
6 | Fred van Stappen / fiens@hotmail.com
|
---|
7 | Reference counting added by Max Karpushin / homeplaner@yandex.ru}
|
---|
8 |
|
---|
9 | unit uos_portaudio;
|
---|
10 |
|
---|
11 | {$mode objfpc}{$H+}
|
---|
12 | {$PACKRECORDS C}
|
---|
13 |
|
---|
14 | interface
|
---|
15 |
|
---|
16 | uses
|
---|
17 | dynlibs, CTypes;
|
---|
18 |
|
---|
19 | const
|
---|
20 | libpa=
|
---|
21 | {$IFDEF unix}
|
---|
22 | {$IFDEF darwin}
|
---|
23 | 'libportaudio.2.dylib';
|
---|
24 | {$ELSE}
|
---|
25 | 'libportaudio.so.2';
|
---|
26 | {$ENDIF}
|
---|
27 | {$ELSE}
|
---|
28 | 'portaudio.dll';
|
---|
29 | {$ENDIF}
|
---|
30 |
|
---|
31 | type
|
---|
32 | PaError = CInt32;
|
---|
33 | PaErrorCode =(
|
---|
34 | paNotInitialized := -10000,
|
---|
35 | paUnanticipatedHostError,
|
---|
36 | paInvalidChannelCount,
|
---|
37 | paInvalidSampleRate,
|
---|
38 | paInvalidDevice,
|
---|
39 | paInvalidFlag,
|
---|
40 | paSampleFormatNotSupported,
|
---|
41 | paBadIODeviceCombination,
|
---|
42 | paInsufficientMemory,
|
---|
43 | paBufferTooBig,
|
---|
44 | paBufferTooSmall,
|
---|
45 | paNullCallback,
|
---|
46 | paBadStreamPtr,
|
---|
47 | paTimedOut,
|
---|
48 | paInternalError,
|
---|
49 | paDeviceUnavailable,
|
---|
50 | paIncompatibleHostApiSpecificStreamInfo,
|
---|
51 | paStreamIsStopped,
|
---|
52 | paStreamIsNotStopped,
|
---|
53 | paInputOverflowed,
|
---|
54 | paOutputUnderflowed,
|
---|
55 | paHostApiNotFound,
|
---|
56 | paInvalidHostApi,
|
---|
57 | paCanNotReadFromACallbackStream,
|
---|
58 | paCanNotWriteToACallbackStream,
|
---|
59 | paCanNotReadFromAnOutputOnlyStream,
|
---|
60 | paCanNotWriteToAnInputOnlyStream,
|
---|
61 | paIncompatibleStreamHostApi,
|
---|
62 | paBadBufferPtr,
|
---|
63 | paNoError := 0
|
---|
64 | );
|
---|
65 |
|
---|
66 | PaDeviceIndex = CInt32;
|
---|
67 |
|
---|
68 | PaHostApiIndex = CInt32;
|
---|
69 |
|
---|
70 | PaHostApiTypeId =(paInDevelopment := 0,
|
---|
71 | paDirectSound := 1,
|
---|
72 | paMME := 2,
|
---|
73 | paASIO := 3,
|
---|
74 | paSoundManager := 4,
|
---|
75 | paCoreAudio := 5,
|
---|
76 | paOSS := 7,
|
---|
77 | paALSA := 8,
|
---|
78 | paAL := 9,
|
---|
79 | paBeOS := 10,
|
---|
80 | paWDMKS := 11,
|
---|
81 | paJACK := 12,
|
---|
82 | paWASAPI := 13,
|
---|
83 | paAudioScienceHPI := 14
|
---|
84 | );
|
---|
85 |
|
---|
86 | PaHostApiInfo = record
|
---|
87 | structVersion : CInt32;
|
---|
88 | _type : PaHostApiTypeId ;
|
---|
89 | _name : Pchar;
|
---|
90 | deviceCount : CInt32;
|
---|
91 | defaultInputDevice : PaDeviceIndex;
|
---|
92 | defaultOutputDevice : PaDeviceIndex;
|
---|
93 | end;
|
---|
94 | PPaHostApiInfo = ^PaHostApiInfo;
|
---|
95 |
|
---|
96 | PaHostErrorInfo = record
|
---|
97 | hostApiType : PaHostApiTypeId;
|
---|
98 | errorCode : CLong;
|
---|
99 | errorText : PChar;
|
---|
100 | end;
|
---|
101 | PPaHostErrorInfo = ^PaHostErrorInfo;
|
---|
102 |
|
---|
103 | PaTime = CDouble;
|
---|
104 |
|
---|
105 | PaSampleFormat = pCULongLong;
|
---|
106 |
|
---|
107 | PaDeviceInfo = record
|
---|
108 | structVersion : CInt32;
|
---|
109 | _name : PChar;
|
---|
110 | hostApi : PaHostApiIndex;
|
---|
111 | maxInputChannels : CInt32;
|
---|
112 | maxOutputChannels : CInt32;
|
---|
113 | defaultLowInputLatency : PaTime;
|
---|
114 | defaultLowOutputLatency : PaTime;
|
---|
115 | defaultHighInputLatency : PaTime;
|
---|
116 | defaultHighOutputLatency : PaTime;
|
---|
117 | defaultSampleRate : CDouble;
|
---|
118 | end;
|
---|
119 | PPaDeviceInfo = ^PaDeviceInfo;
|
---|
120 |
|
---|
121 | PaStreamParameters = record
|
---|
122 | device : PaDeviceIndex;
|
---|
123 | channelCount : CInt32;
|
---|
124 | sampleFormat : PaSampleFormat;
|
---|
125 | suggestedLatency : PaTime;
|
---|
126 | hostApiSpecificStreamInfo : Pointer;
|
---|
127 | end;
|
---|
128 | PPaStreamParameters = ^PaStreamParameters;
|
---|
129 |
|
---|
130 | // ************************* Streaming types *************************
|
---|
131 |
|
---|
132 | PaStream = Pointer;
|
---|
133 | PPaStream = ^PaStream;
|
---|
134 | PPPaStream = ^PPaStream;
|
---|
135 |
|
---|
136 | PaStreamFlags = CULong;
|
---|
137 |
|
---|
138 | PaStreamCallbackTimeInfo = record
|
---|
139 | inputBufferAdcTime : PaTime;
|
---|
140 | currentTime : PaTime;
|
---|
141 | outputBufferDacTime : PaTime;
|
---|
142 | end;
|
---|
143 | PPaStreamCallbackTimeInfo = ^PaStreamCallbackTimeInfo;
|
---|
144 |
|
---|
145 | PaStreamCallbackFlags = CULong;
|
---|
146 |
|
---|
147 | PaStreamCallbackResult =(
|
---|
148 | paContinue := 0,
|
---|
149 | paComplete := 1,
|
---|
150 | paAbort := 2);
|
---|
151 |
|
---|
152 | PaStreamCallback = function(
|
---|
153 | input : Pointer;
|
---|
154 | output : Pointer;
|
---|
155 | frameCount : CULong;
|
---|
156 | timeInfo : PPaStreamCallbackTimeInfo;
|
---|
157 | statusFlags : PaStreamCallbackFlags;
|
---|
158 | userData : Pointer) : CInt32;
|
---|
159 | PPaStreamCallback = ^PaStreamCallback;
|
---|
160 |
|
---|
161 | PaStreamFinishedCallback = procedure(userData : Pointer); cdecl;
|
---|
162 | PPaStreamFinishedCallback = ^PaStreamFinishedCallback;
|
---|
163 |
|
---|
164 | PaStreamInfo = record
|
---|
165 | structVersion : CInt32;
|
---|
166 | inputLatency : PaTime;
|
---|
167 | outputLatency : PaTime;
|
---|
168 | sampleRate : CDouble;
|
---|
169 | end;
|
---|
170 | PPaStreamInfo = ^PaStreamInfo;
|
---|
171 |
|
---|
172 | const
|
---|
173 | paFormatIsSupported = 0;
|
---|
174 | paFramesPerBufferUnspecified = 0;
|
---|
175 | paNoDevice = PaDeviceIndex(-1);
|
---|
176 | paUseHostApiSpecificDeviceSpecification = PaDeviceIndex(-2);
|
---|
177 | paFloat32 = PaSampleFormat($00000001);
|
---|
178 | paInt32 = PaSampleFormat($00000002);
|
---|
179 | paInt24 = PaSampleFormat($00000004);
|
---|
180 | paInt16 = PaSampleFormat($00000008);
|
---|
181 | paInt8 = PaSampleFormat($00000010);
|
---|
182 | paUInt8 = PaSampleFormat($00000020);
|
---|
183 | paCustomFormat = PaSampleFormat($00010000);
|
---|
184 | paNonInterleaved = PaSampleFormat($80000000);
|
---|
185 | paNoFlag = PaStreamFlags(0);
|
---|
186 | paClipOff = PaStreamFlags($00000001);
|
---|
187 | paDitherOff = PaStreamFlags($00000002);
|
---|
188 | paNeverDropInput = PaStreamFlags($00000004);
|
---|
189 | paPrimeOutputBuffersUsingStreamCallback = PaStreamFlags($00000008);
|
---|
190 | paPlatformSpecificFlags = PaStreamFlags($FFFF0000);
|
---|
191 | paInputUnderflow = PaStreamCallbackFlags($00000001);
|
---|
192 | paInputOverflow = PaStreamCallbackFlags($00000002);
|
---|
193 | paOutputUnderflow = PaStreamCallbackFlags($00000004);
|
---|
194 | paOutputOverflow = PaStreamCallbackFlags($00000008);
|
---|
195 | paPrimingOutput = PaStreamCallbackFlags($00000010);
|
---|
196 |
|
---|
197 | ////// Dynamic load : Vars that will hold our dynamically loaded functions...
|
---|
198 |
|
---|
199 | // *************************** functions *******************************
|
---|
200 |
|
---|
201 | var Pa_GetVersion: function():CInt32 ; cdecl;
|
---|
202 |
|
---|
203 | var Pa_GetVersionText: function():PChar ; cdecl;
|
---|
204 |
|
---|
205 | var Pa_GetErrorText: function(errorCode : PaError):PChar ; cdecl;
|
---|
206 |
|
---|
207 | var Pa_Initialize: function():PaError ; cdecl;
|
---|
208 |
|
---|
209 | var Pa_Terminate: function():PaError ; cdecl;
|
---|
210 |
|
---|
211 | var Pa_GetHostApiCount: function():PaHostApiIndex ; cdecl;
|
---|
212 |
|
---|
213 | var Pa_GetDefaultHostApi: function():PaHostApiIndex ; cdecl;
|
---|
214 |
|
---|
215 | var Pa_GetHostApiInfo: function(hostApi : PaHostApiIndex):PPaHostApiInfo ; cdecl;
|
---|
216 |
|
---|
217 | var Pa_HostApiTypeIdToHostApiIndex: function(_type : PaHostApiTypeId):PaHostApiIndex ; cdecl;
|
---|
218 |
|
---|
219 | var Pa_HostApiDeviceIndexToDeviceIndex: function(hostApi : PaHostApiIndex;hostApiDeviceIndex : CInt32):PaDeviceIndex ; cdecl;
|
---|
220 |
|
---|
221 | var Pa_GetLastHostErrorInfo: function():PPaHostErrorInfo ; cdecl;
|
---|
222 |
|
---|
223 | // ************** Device enumeration and capabilities ******************
|
---|
224 |
|
---|
225 | var Pa_GetDeviceCount: function:PaDeviceIndex ; cdecl;
|
---|
226 |
|
---|
227 | var Pa_GetDefaultInputDevice: function:PaDeviceIndex ; cdecl;
|
---|
228 |
|
---|
229 | var Pa_GetDefaultOutputDevice: function:PaDeviceIndex ; cdecl;
|
---|
230 |
|
---|
231 | var Pa_GetDeviceInfo: function(device : PaDeviceIndex):PPaDeviceInfo ; cdecl;
|
---|
232 |
|
---|
233 | var Pa_IsFormatSupported: function(inputParameters,outputParameters : PPaStreamParameters; sampleRate : CDouble):PaError ; cdecl;
|
---|
234 |
|
---|
235 | // *********************** Stream function *****************************
|
---|
236 |
|
---|
237 | var Pa_OpenStream: function(stream : PPPaStream;
|
---|
238 | inputParameters : PPaStreamParameters;
|
---|
239 | outputParameters : PPaStreamParameters;
|
---|
240 | sampleRate : CDouble;
|
---|
241 | framesPerBuffer : CULong;
|
---|
242 | streamFlags : PaStreamFlags;
|
---|
243 | streamCallback : PPaStreamCallback;
|
---|
244 | userData : Pointer):PaError ; cdecl;
|
---|
245 |
|
---|
246 | var Pa_OpenDefaultStream: function(stream : PPPaStream;
|
---|
247 | numInputChannels : CInt32;
|
---|
248 | numOutputChannels : CInt32;
|
---|
249 | sampleFormat : PaSampleFormat;
|
---|
250 | sampleRate : CDouble;
|
---|
251 | framesPerBuffer : CULong;
|
---|
252 | streamCallback : PaStreamCallback;
|
---|
253 | userData : Pointer):PaError ; cdecl;
|
---|
254 |
|
---|
255 | var Pa_CloseStream: function(stream : PPaStream):PaError ; cdecl;
|
---|
256 |
|
---|
257 | var Pa_SetStreamFinishedCallback: function(stream : PPaStream;
|
---|
258 | streamFinishedCallback : PaStreamFinishedCallback):PaError ; cdecl;
|
---|
259 |
|
---|
260 | var Pa_StartStream: function(stream : PPaStream):PaError ; cdecl;
|
---|
261 |
|
---|
262 | var Pa_StopStream: function(stream : PPaStream):PaError ; cdecl;
|
---|
263 |
|
---|
264 | var Pa_AbortStream: function(stream : PPaStream):PaError ; cdecl;
|
---|
265 |
|
---|
266 | var Pa_IsStreamStopped: function(stream : PPaStream):PaError ; cdecl;
|
---|
267 |
|
---|
268 | var Pa_IsStreamActive: function(stream : PPaStream):PaError ; cdecl;
|
---|
269 |
|
---|
270 | var Pa_GetStreamInfo: function(stream : PPaStream):PPaStreamInfo ; cdecl;
|
---|
271 |
|
---|
272 | var Pa_GetStreamTime: function(stream : PPaStream):Patime ; cdecl;
|
---|
273 |
|
---|
274 | var Pa_GetStreamCpuLoad: function(stream : PPaStream):CDouble ; cdecl;
|
---|
275 |
|
---|
276 | var Pa_ReadStream: function(stream : PPaStream; buffer : pcfloat ;frames : CULong):PaError ; cdecl;
|
---|
277 |
|
---|
278 | var Pa_WriteStream: function(stream : PPaStream; buffer : pcfloat ;frames : CULong):PaError ; cdecl;
|
---|
279 |
|
---|
280 | var Pa_GetStreamReadAvailable: function(stream : PPaStream):CSLong ; cdecl;
|
---|
281 |
|
---|
282 | var Pa_GetStreamWriteAvailable: function(stream : PPaStream):CSLong ; cdecl;
|
---|
283 |
|
---|
284 | // ****************** Miscellaneous utilities **************************
|
---|
285 |
|
---|
286 | var Pa_GetSampleSize: function(format : PaSampleFormat):PaError ; cdecl;
|
---|
287 |
|
---|
288 | var Pa_Sleep: function(msec : CLong) : integer; cdecl;
|
---|
289 |
|
---|
290 | ///////////////////////////////////////////////
|
---|
291 |
|
---|
292 | {Special function for dynamic loading of lib ...}
|
---|
293 |
|
---|
294 | var Pa_Handle:TLibHandle=dynlibs.NilHandle; // this will hold our handle for the lib; it functions nicely as a mutli-lib prevention unit as well...
|
---|
295 |
|
---|
296 | var ReferenceCounter : cardinal = 0; // Reference counter
|
---|
297 |
|
---|
298 | function Pa_IsLoaded : boolean; inline;
|
---|
299 |
|
---|
300 | Function Pa_Load(const libfilename:string) :boolean; // load the lib
|
---|
301 |
|
---|
302 | Procedure Pa_Unload(); // unload and frees the lib from memory : do not forget to call it before close application.
|
---|
303 |
|
---|
304 | /////////////////////////////////////////////////////////////////////////////////////////////////
|
---|
305 |
|
---|
306 | implementation
|
---|
307 |
|
---|
308 | function Pa_IsLoaded: boolean;
|
---|
309 | begin
|
---|
310 | Result := (Pa_Handle <> dynlibs.NilHandle);
|
---|
311 | end;
|
---|
312 |
|
---|
313 | Function Pa_Load (const libfilename:string) :boolean;
|
---|
314 | var
|
---|
315 | thelib: string;
|
---|
316 | begin
|
---|
317 | Result := False;
|
---|
318 | if Pa_Handle<>0 then
|
---|
319 | begin
|
---|
320 | Inc(ReferenceCounter);
|
---|
321 | result:=true {is it already there ?}
|
---|
322 | end else
|
---|
323 | begin {go & load the library}
|
---|
324 | if Length(libfilename) = 0 then thelib := libpa else thelib := libfilename;
|
---|
325 | Pa_Handle:=DynLibs.SafeLoadLibrary(thelib); // obtain the handle we want
|
---|
326 | if Pa_Handle <> DynLibs.NilHandle then
|
---|
327 | begin {now we tie the functions to the VARs from above}
|
---|
328 |
|
---|
329 | Pointer(Pa_GetVersion):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetVersion'));
|
---|
330 | Pointer(Pa_GetVersionText):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetVersionText'));
|
---|
331 | Pointer(Pa_GetErrorText):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetErrorText'));
|
---|
332 | Pointer(Pa_Initialize):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_Initialize'));
|
---|
333 | Pointer(Pa_Terminate):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_Terminate'));
|
---|
334 | Pointer(Pa_GetHostApiCount):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetHostApiCount'));
|
---|
335 | Pointer(Pa_GetDefaultHostApi):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetDefaultHostApi'));
|
---|
336 | Pointer(Pa_GetHostApiInfo):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetHostApiInfo'));
|
---|
337 | Pointer(Pa_HostApiTypeIdToHostApiIndex):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_HostApiTypeIdToHostApiIndex'));
|
---|
338 | Pointer(Pa_HostApiDeviceIndexToDeviceIndex):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_HostApiDeviceIndexToDeviceIndex'));
|
---|
339 | Pointer(Pa_GetLastHostErrorInfo):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetLastHostErrorInfo'));
|
---|
340 | //////////////////
|
---|
341 | Pointer(Pa_GetDeviceCount):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetDeviceCount'));
|
---|
342 | Pointer(Pa_GetDefaultInputDevice):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetDefaultInputDevice'));
|
---|
343 | Pointer(Pa_GetDefaultOutputDevice):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetDefaultOutputDevice'));
|
---|
344 | Pointer(Pa_GetDeviceInfo):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetDeviceInfo'));
|
---|
345 | Pointer(Pa_IsFormatSupported):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_IsFormatSupported'));
|
---|
346 | //////////////////////
|
---|
347 | Pointer(Pa_OpenStream):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_OpenStream'));
|
---|
348 | Pointer(Pa_OpenDefaultStream):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_OpenDefaultStream'));
|
---|
349 | Pointer(Pa_CloseStream):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_CloseStream'));
|
---|
350 | Pointer(Pa_SetStreamFinishedCallback):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_SetStreamFinishedCallback'));
|
---|
351 | Pointer(Pa_StartStream):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_StartStream'));
|
---|
352 | Pointer(Pa_StopStream):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_StopStream'));
|
---|
353 | Pointer(Pa_AbortStream):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_AbortStream'));
|
---|
354 | Pointer(Pa_IsStreamStopped):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_IsStreamStopped'));
|
---|
355 | Pointer(Pa_IsStreamActive):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_IsStreamActive'));
|
---|
356 | Pointer(Pa_GetStreamInfo):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetStreamInfo'));
|
---|
357 | Pointer(Pa_GetStreamTime):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetStreamTime'));
|
---|
358 | Pointer(Pa_GetStreamCpuLoad):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetStreamCpuLoad'));
|
---|
359 | Pointer(Pa_ReadStream):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_ReadStream'));
|
---|
360 | Pointer(Pa_WriteStream):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_WriteStream'));
|
---|
361 | Pointer(Pa_GetStreamReadAvailable):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetStreamReadAvailable'));
|
---|
362 | Pointer(Pa_GetStreamWriteAvailable):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetStreamWriteAvailable'));
|
---|
363 | Pointer(Pa_GetSampleSize):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetSampleSize'));
|
---|
364 | Pointer(Pa_Sleep):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_Sleep'));
|
---|
365 | end;
|
---|
366 | Result := Pa_IsLoaded;
|
---|
367 | ReferenceCounter:=1;
|
---|
368 | end;
|
---|
369 |
|
---|
370 | end;
|
---|
371 |
|
---|
372 | Procedure Pa_Unload;
|
---|
373 | begin
|
---|
374 | // < Reference counting
|
---|
375 | if ReferenceCounter > 0 then
|
---|
376 | dec(ReferenceCounter);
|
---|
377 | if ReferenceCounter > 0 then
|
---|
378 | exit;
|
---|
379 | // >
|
---|
380 | if Pa_IsLoaded then
|
---|
381 | begin
|
---|
382 | Pa_Terminate();
|
---|
383 | DynLibs.UnloadLibrary(Pa_Handle);
|
---|
384 | Pa_Handle:=DynLibs.NilHandle;
|
---|
385 | end;
|
---|
386 | end;
|
---|
387 |
|
---|
388 | end.
|
---|
389 |
|
---|