source: trunk/Packages/uos/uos_libsndfile.pas

Last change on this file was 664, checked in by chronos, 3 days ago
  • Added: Ability to play music in background in start screen and in-game. Used uos as audio library.
File size: 24.9 KB
Line 
1{This unit is part of United Openlibraries of Sound (uos)}
2
3{This is the Dynamic loading version with reference counting of LibSndFile.pas.
4 Load the library with sf_load() and release with sf_unload().
5 Thanks to Phoenix for sf_open_virtual (TMemoryStream as input)
6 License : modified LGPL.
7 Fred van Stappen / fiens@hotmail.com }
8
9unit uos_libsndfile;
10
11{$IFDEF FPC}
12 {$mode objfpc}{$H+}
13 {$PACKENUM 4}(* use 4-byte enums *)
14 {$PACKRECORDS C}(* C/C++-compatible record packing *)
15 {$MACRO ON}//don't know whatfor !
16{$ELSE}
17 {$MINENUMSIZE 4}(* use 4-byte enums *)
18{** MINENUMSIZE is equivalent to Z+}
19{$ENDIF}
20
21{$LONGSTRINGS ON}
22{** LONGSTRINGS is equivalent to H+}
23
24interface
25
26uses
27 dynlibs, classes,
28 ctypes;
29
30const
31libsf=
32 {$IFDEF unix}
33 {$IFDEF darwin}
34 'libsndfile.1.dylib';
35 {$ELSE}
36 'libsndfile.so.1';
37 {$ENDIF}
38 {$ELSE}
39 'sndfile.dll';
40 {$ENDIF}
41
42type
43 PMemoryStream = ^TMemoryStream;
44
45type
46 {$IF Defined(MSWINDOWS)}
47 off_t = int64;
48 {$ELSE}
49 off_t = clonglong;
50 size_t = culong;
51 {$ENDIF}
52
53const
54 //* Major formats. *//
55 SF_FORMAT_WAV = $010000; // Microsoft WAV format (little endian default).
56 SF_FORMAT_AIFF = $020000; // Apple/SGI AIFF format (big endian).
57 SF_FORMAT_AU = $030000; // Sun/NeXT AU format (big endian).
58 SF_FORMAT_RAW = $040000; // RAW PCM data.
59 SF_FORMAT_PAF = $050000; // Ensoniq PARIS file format.
60 SF_FORMAT_SVX = $060000; // Amiga IFF / SVX8 / SV16 format.
61 SF_FORMAT_NIST = $070000; // Sphere NIST format.
62 SF_FORMAT_VOC = $080000; // VOC files.
63 SF_FORMAT_IRCAM = $0A0000; // Berkeley/IRCAM/CARL
64 SF_FORMAT_W64 = $0B0000; // Sonic Foundry's 64 bit RIFF/WAV
65 SF_FORMAT_MAT4 = $0C0000; // Matlab (tm) V4.2 / GNU Octave 2.0
66 SF_FORMAT_MAT5 = $0D0000; // Matlab (tm) V5.0 / GNU Octave 2.1
67 SF_FORMAT_PVF = $0E0000; // Portable Voice Format
68 SF_FORMAT_XI = $0F0000; // Fasttracker 2 Extended Instrument
69 SF_FORMAT_HTK = $100000; // HMM Tool Kit format
70 SF_FORMAT_SDS = $110000; // Midi Sample Dump Standard
71 SF_FORMAT_AVR = $120000; // Audio Visual Research
72 SF_FORMAT_WAVEX = $130000; // MS WAVE with WAVEFORMATEX
73 SF_FORMAT_SD2 = $160000; // Sound Designer 2
74 SF_FORMAT_FLAC = $170000; // FLAC lossless file format
75 SF_FORMAT_CAF = $180000; // Core Audio File format
76 SF_FORMAT_OGG = $200000; // Xiph OGG container
77
78
79const
80 //Subtypes from here on.
81 SF_FORMAT_PCM_S8 = $0001; // Signed 8 bit data
82 SF_FORMAT_PCM_16 = $0002; // Signed 16 bit data
83 SF_FORMAT_PCM_24 = $0003; // Signed 24 bit data
84 SF_FORMAT_PCM_32 = $0004; // Signed 32 bit data
85
86 SF_FORMAT_PCM_U8 = $0005; // Unsigned 8 bit data (WAV and RAW only)
87
88 SF_FORMAT_FLOAT = $0006; // 32 bit float data
89 SF_FORMAT_DOUBLE = $0007; // 64 bit float data
90
91 SF_FORMAT_ULAW = $0010; // U-Law encoded.
92 SF_FORMAT_ALAW = $0011; // A-Law encoded.
93 SF_FORMAT_IMA_ADPCM = $0012; // IMA ADPCM.
94 SF_FORMAT_MS_ADPCM = $0013; // Microsoft ADPCM.
95
96 SF_FORMAT_GSM610 = $0020; // GSM 6.10 encoding.
97 SF_FORMAT_VOX_ADPCM = $0021; // OKI / Dialogix ADPCM
98
99 SF_FORMAT_G721_32 = $0030; // 32kbs G721 ADPCM encoding.
100 SF_FORMAT_G723_24 = $0031; // 24kbs G723 ADPCM encoding.
101 SF_FORMAT_G723_40 = $0032; // 40kbs G723 ADPCM encoding.
102
103 SF_FORMAT_DWVW_12 = $0040; // 12 bit Delta Width Variable Word encoding.
104 SF_FORMAT_DWVW_16 = $0041; // 16 bit Delta Width Variable Word encoding.
105 SF_FORMAT_DWVW_24 = $0042; // 24 bit Delta Width Variable Word encoding.
106 SF_FORMAT_DWVW_N = $0043; // N bit Delta Width Variable Word encoding.
107
108 SF_FORMAT_DPCM_8 = $0050; // 8 bit differential PCM (XI only)
109 SF_FORMAT_DPCM_16 = $0051; // 16 bit differential PCM (XI only)
110
111 SF_FORMAT_VORBIS = $0060; // Xiph Vorbis encoding.
112
113
114const
115 //* Endian-ness options. *//
116 SF_ENDIAN_FILE = $00000000; // Default file endian-ness.
117 SF_ENDIAN_LITTLE = $10000000; // Force little endian-ness.
118 SF_ENDIAN_BIG = $20000000; // Force big endian-ness.
119 SF_ENDIAN_CPU = $30000000; // Force CPU endian-ness.
120
121 SF_FORMAT_SUBMASK = $0000FFFF;
122 SF_FORMAT_TYPEMASK = $0FFF0000;
123 SF_FORMAT_ENDMASK = $30000000;
124
125{
126** The following are the valid command numbers for the sf_command()
127** interface. The use of these commands is documented in the file
128** command.html in the doc directory of the source code distribution.
129}
130const
131 SFC_GET_LIB_VERSION = $1000;
132 SFC_GET_LOG_INFO = $1001;
133
134 SFC_GET_NORM_DOUBLE = $1010;
135 SFC_GET_NORM_FLOAT = $1011;
136 SFC_SET_NORM_DOUBLE = $1012;
137 SFC_SET_NORM_FLOAT = $1013;
138 SFC_SET_SCALE_FLOAT_INT_READ = $1014;
139
140 SFC_GET_SIMPLE_FORMAT_COUNT = $1020;
141 SFC_GET_SIMPLE_FORMAT = $1021;
142
143 SFC_GET_FORMAT_INFO = $1028;
144
145 SFC_GET_FORMAT_MAJOR_COUNT = $1030;
146 SFC_GET_FORMAT_MAJOR = $1031;
147 SFC_GET_FORMAT_SUBTYPE_COUNT = $1032;
148 SFC_GET_FORMAT_SUBTYPE = $1033;
149
150 SFC_CALC_SIGNAL_MAX = $1040;
151 SFC_CALC_NORM_SIGNAL_MAX = $1041;
152 SFC_CALC_MAX_ALL_CHANNELS = $1042;
153 SFC_CALC_NORM_MAX_ALL_CHANNELS = $1043;
154 SFC_GET_SIGNAL_MAX = $1044;
155 SFC_GET_MAX_ALL_CHANNELS = $1045;
156
157 SFC_SET_ADD_PEAK_CHUNK = $1050;
158
159 SFC_UPDATE_HEADER_NOW = $1060;
160 SFC_SET_UPDATE_HEADER_AUTO = $1061;
161
162 SFC_FILE_TRUNCATE = $1080;
163
164 SFC_SET_RAW_START_OFFSET = $1090;
165
166 SFC_SET_DITHER_ON_WRITE = $10A0;
167 SFC_SET_DITHER_ON_READ = $10A1;
168
169 SFC_GET_DITHER_INFO_COUNT = $10A2;
170 SFC_GET_DITHER_INFO = $10A3;
171
172 SFC_GET_EMBED_FILE_INFO = $10B0;
173
174 SFC_SET_CLIPPING = $10C0;
175 SFC_GET_CLIPPING = $10C1;
176
177 SFC_GET_INSTRUMENT = $10D0;
178 SFC_SET_INSTRUMENT = $10D1;
179
180 SFC_GET_LOOP_INFO = $10E0;
181
182 SFC_GET_BROADCAST_INFO = $10F0;
183 SFC_SET_BROADCAST_INFO = $10F1;
184
185 // Following commands for testing only.
186 SFC_TEST_IEEE_FLOAT_REPLACE = $6001;
187
188 {
189 ** SFC_SET_ADD_* values are deprecated and will disappear at some
190 ** time in the future. They are guaranteed to be here up to and
191 ** including version 1.0.8 to avoid breakage of existing software.
192 ** They currently do nothing and will continue to do nothing.
193 }
194 SFC_SET_ADD_DITHER_ON_WRITE = $1070;
195 SFC_SET_ADD_DITHER_ON_READ = $1071;
196
197{
198** String types that can be set and read from files. Not all file types
199** support this and even the file types which support one, may not support
200** all string types.
201}
202const
203 SF_STR_TITLE = $01;
204 SF_STR_COPYRIGHT = $02;
205 SF_STR_SOFTWARE = $03;
206 SF_STR_ARTIST = $04;
207 SF_STR_COMMENT = $05;
208 SF_STR_DATE = $06;
209 SF_STR_ALBUM = $07;
210 SF_STR_LICENSE = $08;
211 SF_STR_TRACKNUMBER = $09;
212 SF_STR_GENRE = $10;
213
214{
215** Use the following as the start and end index when doing metadata
216** transcoding.
217}
218 SF_STR_FIRST = SF_STR_TITLE;
219 SF_STR_LAST = SF_STR_GENRE;
220
221const
222 // True and false
223 SF_FALSE = 0;
224 SF_TRUE = 1;
225
226const
227 // Modes for opening files.
228 SFM_READ = $10;
229 SFM_WRITE = $20;
230 SFM_RDWR = $30;
231
232{
233** Public error values. These are guaranteed to remain unchanged
234** for the duration of the library major version number.
235** There are also a large number of private error numbers which are
236** internal to the library which can change at any time.
237}
238const
239 SF_ERR_NO_ERROR = 0;
240 SF_ERR_UNRECOGNISED_FORMAT = 1;
241 SF_ERR_SYSTEM = 2;
242 SF_ERR_MALFORMED_FILE = 3;
243 SF_ERR_UNSUPPORTED_ENCODING = 4;
244
245//A SNDFILE* pointer can be passed around much like stdio.h's FILE* pointer.
246
247type
248 TSNDFILE_HANDLE = pointer; // this is not a usual pointer, more like a THandle ..
249// so NOT called "PSndFile_handle"
250// => we never access members of the internal
251// structure where the pointer points to !
252// Everything is managed by the DLL internally !!!
253//PSNDFILE_tag = PSNDFILE;
254
255 {
256** The following typedef is system specific and is defined when libsndfile is.
257** compiled. uos_count_t can be one of loff_t (Linux), off_t (*BSD),
258** off64_t (Solaris), __int64_t (Win32) etc.
259}
260type
261 Puos_count_t = ^Tuos_count_t;
262 Tuos_count_t = off_t;
263
264const
265 SF_COUNT_MAX = ctypes.clonglong($7FFFFFFFFFFFFFFF);
266
267{
268** A pointer to a SF_INFO structure is passed to sf_open_read () and filled in.
269** On write, the SF_INFO structure is filled in by the user and passed into
270** sf_open_write ().
271}
272
273type
274 PSF_INFO = ^TSF_INFO;
275
276 TSF_INFO = record
277 frames: Tuos_count_t;
278 // Used to be called samples. Changed to avoid confusion.
279 samplerate: ctypes.cint;
280 channels: ctypes.cint;
281 format: ctypes.cint;
282 sections: ctypes.cint;
283 seekable: ctypes.cint;
284 end;
285
286{
287** The SF_FORMAT_INFO struct is used to retrieve information about the sound
288** file formats libsndfile supports using the sf_command () interface.
289**
290** Using this interface will allow applications to support new file formats
291** and encoding types when libsndfile is upgraded, without requiring
292** re-compilation of the application.
293**
294** Please consult the libsndfile documentation (particularly the information
295** on the sf_command () interface) for examples of its use.
296}
297
298type
299 PSF_FORMAT_INFO = ^TSF_FORMAT_INFO;
300
301 TSF_FORMAT_INFO = record
302 format: ctypes.cint;
303 Name: ctypes.pcchar;
304 extention: ctypes.pcchar;
305 end;
306
307{
308** Enums and typedefs for adding dither on read and write.
309** See the html documentation for sf_command(), SFC_SET_DITHER_ON_WRITE
310** and SFC_SET_DITHER_ON_READ.
311}
312const
313 SFD_DEFAULT_LEVEL = 0;
314 SFD_CUSTOM_LEVEL = $40000000;
315
316 SFD_NO_DITHER = 500;
317 SFD_WHITE = 501;
318 SFD_TRIANGULAR_PDF = 502;
319
320type
321 PSF_DITHER_INFO = ^TSF_DITHER_INFO;
322
323 TSF_DITHER_INFO = record
324 type_: ctypes.cint;
325 level: ctypes.cdouble;
326 Name: ctypes.pcchar;
327 end;
328
329{
330** Struct used to retrieve information about a file embedded within a
331** larger file. See SFC_GET_EMBED_FILE_INFO.
332}
333type
334 PSF_EMBED_FILE_INFO = ^TSF_EMBED_FILE_INFO;
335
336 TSF_EMBED_FILE_INFO = record
337 offset: Tuos_count_t;
338 length: Tuos_count_t;
339 end;
340
341// Structs used to retrieve music sample information from a file.
342
343const
344 // The loop mode field in SF_INSTRUMENT will be one of the following.
345 SF_LOOP_NONE = 800;
346 SF_LOOP_FORWARD = 801;
347 SF_LOOP_BACKWARD = 802;
348 SF_LOOP_ALTERNATING = 803;
349
350type
351 PSF_INSTRUMENT = ^TSF_INSTRUMENT;
352
353 TSF_INSTRUMENT = record
354 gain: ctypes.cint;
355 basenote,
356 detune: ctypes.cchar;
357 velocity_lo,
358 velocity_hi: ctypes.cchar;
359 loop_count: ctypes.cint;
360 loops: array[0..15] of record
361 mode: ctypes.cint;
362 start: ctypes.cuint;
363 end_: ctypes.cuint;
364 Count: ctypes.cuint;
365 end;
366 end;
367
368// Struct used to retrieve loop information from a file.
369type
370 PSF_LOOP_INFO = ^TSF_LOOP_INFO;
371
372 TSF_LOOP_INFO = record
373 time_sig_num: ctypes.cushort;
374 // any positive integer > 0
375 time_sig_den: ctypes.cushort;
376 // any positive power of 2 > 0
377 loop_mode: ctypes.cint; // see SF_LOOP enum
378
379 num_beats: ctypes.cint;
380 // this is NOT the amount of quarter notes !!!
381 // a full bar of 4/4 is 4 beats
382 // a full bar of 7/8 is 7 beats
383
384 bpm: ctypes.cfloat;
385 // suggestion, as it can be calculated using other fields:
386 // file's lenght, file's sampleRate and our time_sig_den
387 // -> bpms are always the amount of _quarter notes_ per minute
388
389 root_key: ctypes.cint;
390 // MIDI note, or -1 for None
391 future: array[0..5] of ctypes.cint;
392 end;
393
394
395{
396** Struct used to retrieve broadcast (EBU) information from a file.
397** Strongly (!) based on EBU "bext" chunk format used in Broadcast WAVE.
398}
399type
400 PSF_BROADCAST_INFO = ^TSF_BROADCAST_INFO;
401
402 TSF_BROADCAST_INFO = record
403 description: array[0..255] of char;//ctypes.cchar;
404 originator: array[0..31] of char;//ctypes.cchar;
405 originator_reference: array[0..31] of char;//ctypes.cchar;
406 origination_date: array[0..9] of char;//ctypes.cchar;
407 origination_time: array[0..7] of char;//ctypes.cchar;
408 time_reference_low: ctypes.cuint;//ctypes.cint;
409 time_reference_high: ctypes.cuint;//ctypes.cint;
410 version: ctypes.cshort;
411 umid: array[0..63] of char;//ctypes.cchar;
412 reserved: array[0..189] of char;//ctypes.cchar;
413 coding_history_size: ctypes.cuint;
414 coding_history: array[0..255] of char;//ctypes.cchar;
415 end;
416
417 // Thanks to Phoenix
418 type
419 //pm_get_filelen = ^tm_get_filelen;
420 tm_get_filelen =
421 function (pms: PMemoryStream): Tuos_count_t; cdecl;
422 //pm_seek = ^tm_seek;
423 tm_seek =
424 function (offset: Tuos_count_t; whence: cint32; pms: PMemoryStream): Tuos_count_t; cdecl;
425 //pm_read = ^tm_read;
426 tm_read =
427 function (const buf: Pointer; count: Tuos_count_t; pms: PMemoryStream): Tuos_count_t; cdecl;
428 //pm_write = ^tm_write;
429 tm_write =
430 function (const buf: Pointer; count: Tuos_count_t; pms: PMemoryStream): Tuos_count_t; cdecl;
431 //pm_tell = ^tm_tell;
432 tm_tell =
433 function (pms: PMemoryStream): Tuos_count_t; cdecl;
434
435 TSF_VIRTUAL = packed record
436 sf_vio_get_filelen : tm_get_filelen;
437 seek : tm_seek;
438 read : tm_read;
439 write : tm_write;
440 tell : tm_tell;
441 end;
442
443 PSF_VIRTUAL = ^TSF_VIRTUAL;
444
445{
446** Open the specified file for read, write or both. On error, this will
447** return a NULL pointer. To find the error number, pass a NULL SNDFILE
448** to sf_perror () or sf_error_str ().
449** All calls to sf_open() should be matched with a call to sf_close().
450}
451////////////////////////////////////////////////////////////////////////////////////////
452
453function sf_open(path: string; mode: ctypes.cint;
454 var sfinfo: TSF_INFO): TSNDFILE_HANDLE;
455
456////// Dynamic load : Vars that will hold our dynamically loaded functions..
457var
458 sf_open_native: function(path: PChar;
459 mode: ctypes.cint; sfinfo: PSF_INFO): TSNDFILE_HANDLE; cdecl;
460
461var
462sf_version_string: function(): PChar; cdecl;
463
464var
465 sf_open_fd: function(fd: ctypes.cint; mode: ctypes.cint; sfinfo: PSF_INFO;
466 close_desc: ctypes.cint): TSNDFILE_HANDLE; cdecl;
467
468var
469 sf_open_virtual: function(sfvirtual: PSF_VIRTUAL; mode: ctypes.cint;
470 sfinfo: PSF_INFO; user_data: Pointer): TSNDFILE_HANDLE; cdecl;
471
472var
473 sf_error: function(sndfile: TSNDFILE_HANDLE): ctypes.cint; cdecl;
474
475var
476 sf_strerror: function(sndfile: TSNDFILE_HANDLE): PChar; cdecl;
477
478var
479 sf_error_number: function(errnum: ctypes.cint): PChar; cdecl;
480
481var
482 sf_perror: function(sndfile: TSNDFILE_HANDLE): ctypes.cint; cdecl;
483
484var
485 sf_error_str: function(sndfile: TSNDFILE_HANDLE;
486 str: ctypes.pcchar; len: size_t): ctypes.cint; cdecl;
487
488{
489 In libsndfile there are 4 functions with the same name (sf_command), 3 of them use the parameter "overload".
490 In dynamic loading (because of var) we use 4 different names for the 4 functions sf_command :
491 sf_command_pointer, sf_command_double, sf_command_array, sf_command_tsf. All that 4 functions gonna point
492 to sf_command in libsndfile library.
493}
494
495var
496 sf_command_pointer: function(sndfile: TSNDFILE_HANDLE; command: ctypes.cint;
497 Data: Pointer; datasize: ctypes.cint): ctypes.cint; cdecl;
498
499var
500 sf_command_double: function(sndfile: TSNDFILE_HANDLE; command: ctypes.cint;
501 var Data: double; datasize: ctypes.cint): ctypes.cint; cdecl;
502
503var
504 sf_command_array: function(sndfile: TSNDFILE_HANDLE; command: ctypes.cint;
505 var Data: array of char; datasize: ctypes.cint): ctypes.cint; cdecl;
506
507var
508 sf_command_tsf: function(sndfile: TSNDFILE_HANDLE; command: ctypes.cint;
509 var Data: TSF_BROADCAST_INFO; datasize: ctypes.cint): ctypes.cint; cdecl;
510
511var
512 sf_format_check: function(var info: TSF_INFO): ctypes.cint; cdecl;
513
514{
515** Seek within the waveform data chunk of the SNDFILE. sf_seek () uses
516** the same values for whence (SEEK_SET, SEEK_CUR and SEEK_END) as
517** stdio.h function fseek ().
518** An offset of zero with whence set to SEEK_SET will position the
519** read / write pointer to the first data sample.
520** On success sf_seek returns the current position in (multi-channel)
521** samples from the start of the file.
522** Please see the libsndfile documentation for moving the read pointer
523** separately from the write pointer on files open in mode SFM_RDWR.
524** On error all of these functions return -1.
525}
526
527//the following CONST values originally are NOT in libsndfile.pas:
528const
529 SEEK_SET = 0; //* seek relative to beginning of file */
530
531const
532 SEEK_CUR = 1; //* seek relative to current file position */
533
534const
535 SEEK_END = 2; //* seek relative to end of file */
536
537const
538 SEEK_DATA = 3; //* seek to the next data */
539
540const
541 SEEK_HOLE = 4; //* seek to the next hole */
542
543const
544 SEEK_MAX = SEEK_HOLE;
545
546var
547 sf_seek: function(sndfile: TSNDFILE_HANDLE; frame: Tuos_count_t;
548 whence: ctypes.cint): Tuos_count_t; cdecl;
549
550{
551** Functions for retrieving and setting string data within sound files.
552** Not all file types support this features; AIFF and WAV do. For both
553** functions, the str_type parameter must be one of the SF_STR_* values
554** defined above.
555** On error, sf_set_string() returns non-zero while sf_get_string()
556** returns NULL.
557}
558var
559 sf_set_string: function(sndfile: TSNDFILE_HANDLE; str_type: ctypes.cint;
560 str: ctypes.pcchar): ctypes.cint; cdecl;
561
562var
563 sf_get_string: function(sndfile: TSNDFILE_HANDLE;
564 str_type: ctypes.cint): PChar; cdecl;
565
566var
567 sf_read_raw: function(sndfile: TSNDFILE_HANDLE; ptr: Pointer;
568 bytes: Tuos_count_t): Tuos_count_t; cdecl;
569
570var
571 sf_write_raw: function(sndfile: TSNDFILE_HANDLE; ptr: Pointer;
572 bytes: Tuos_count_t): Tuos_count_t; cdecl;
573
574{
575** Functions for reading and writing the data chunk in terms of frames.
576** The number of items actually read/written = frames * number of channels.
577** sf_xxxx_raw read/writes the raw data bytes from/to the file
578** sf_xxxx_short passes data in the native short format
579** sf_xxxx_int passes data in the native int format
580** sf_xxxx_float passes data in the native float format
581** sf_xxxx_double passes data in the native double format
582** All of these read/write function return number of frames read/written.
583}
584var
585 sf_readf_short: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcshort;
586 frames: Tuos_count_t): Tuos_count_t; cdecl;
587
588var
589 sf_writef_short: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcshort;
590 frames: Tuos_count_t): Tuos_count_t; cdecl;
591
592var
593 sf_readf_int: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcint;
594 frames: Tuos_count_t): Tuos_count_t; cdecl;
595
596var
597 sf_writef_int: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcint;
598 frames: Tuos_count_t): Tuos_count_t; cdecl;
599
600var
601 sf_readf_float: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcfloat;
602 frames: Tuos_count_t): Tuos_count_t; cdecl;
603
604var
605 sf_writef_float: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcfloat;
606 frames: Tuos_count_t): Tuos_count_t; cdecl;
607
608var
609 sf_readf_double: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcdouble;
610 frames: Tuos_count_t): Tuos_count_t; cdecl;
611
612var
613 sf_writef_double: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcdouble;
614 frames: Tuos_count_t): Tuos_count_t; cdecl;
615
616{
617** Functions for reading and writing the data chunk in terms of items.
618** Otherwise similar to above.
619** All of these read/write function return number of items read/written.
620}
621var
622 sf_read_short: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcshort;
623 frames: Tuos_count_t): Tuos_count_t; cdecl;
624
625var
626 sf_write_short: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcshort;
627 frames: Tuos_count_t): Tuos_count_t; cdecl;
628
629var
630 sf_read_int: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcint;
631 frames: Tuos_count_t): Tuos_count_t; cdecl;
632
633var
634 sf_write_int: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcint;
635 frames: Tuos_count_t): Tuos_count_t; cdecl;
636
637var
638 sf_read_float: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcfloat;
639 frames: Tuos_count_t): Tuos_count_t; cdecl;
640
641var
642 sf_write_float: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcfloat;
643 frames: Tuos_count_t): Tuos_count_t; cdecl;
644
645var
646 sf_read_double: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcdouble;
647 frames: Tuos_count_t): Tuos_count_t; cdecl;
648
649var
650 sf_write_double: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcdouble;
651 frames: Tuos_count_t): Tuos_count_t; cdecl;
652
653{
654** Close the SNDFILE and clean up all memory allocations associated
655** with this file.
656** Returns 0 on success, or an error number.
657}
658var
659 sf_close: function(sndfile: TSNDFILE_HANDLE): ctypes.cint; cdecl;
660
661{
662** If the file is opened SFM_WRITE or SFM_RDWR, call fsync() on the file
663** to force the writing of data to disk. If the file is opened SFM_READ
664** no action is taken.
665}
666var
667 sf_write_sync: function(sndfile: TSNDFILE_HANDLE): ctypes.cint; cdecl;
668
669{Special function for dynamic loading of lib ...}
670
671var
672 sf_Handle: TLibHandle;
673// this will hold our handle for the lib; it functions nicely as a mutli-lib prevention unit as well...
674
675function sf_Load(const libfilename: string): boolean; // load the lib
676
677procedure sf_Unload();
678// unload and frees the lib from memory : do not forget to call it before close application.
679
680function sf_IsLoaded: boolean;
681
682implementation
683
684var
685 ReferenceCounter: cardinal = 0; // Reference counter
686
687function sf_Load(const libfilename: string): boolean;
688var
689thelib: string;
690begin
691 Result := False;
692 if sf_Handle <> 0 then
693 begin
694 Result := True {is it already there ?};
695 //Reference counting
696 Inc(ReferenceCounter);
697 end
698 else
699 begin {go & load the library}
700 if Length(libfilename) = 0 then thelib := libsf else thelib := libfilename;
701 sf_Handle := DynLibs.SafeLoadLibrary(thelib); // obtain the handle we want
702 if sf_Handle <> DynLibs.NilHandle then
703 begin {now we tie the functions to the VARs from above}
704
705 Pointer(sf_version_string) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_version_string'));
706 Pointer(sf_open_native) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_open'));
707 Pointer(sf_open_fd) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_open_fd'));
708 Pointer(sf_open_virtual) := DynLibs.GetProcedureAddress(
709 sf_Handle, PChar('sf_open_virtual'));
710 Pointer(sf_error) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_error'));
711 Pointer(sf_strerror) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_strerror'));
712 Pointer(sf_error_number) := DynLibs.GetProcedureAddress(
713 sf_Handle, PChar('sf_error_number'));
714 Pointer(sf_perror) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_perror'));
715 Pointer(sf_error_str) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_error_str'));
716 Pointer(sf_command_pointer) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_command'));
717 Pointer(sf_command_array) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_command'));
718 Pointer(sf_command_double) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_command'));
719 Pointer(sf_command_tsf) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_command'));
720 Pointer(sf_format_check) := DynLibs.GetProcedureAddress(
721 sf_Handle, PChar('sf_format_check'));
722 Pointer(sf_seek) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_seek'));
723 Pointer(sf_set_string) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_set_string'));
724 Pointer(sf_get_string) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_get_string'));
725 Pointer(sf_read_raw) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_read_raw'));
726 Pointer(sf_write_raw) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_write_raw'));
727 Pointer(sf_readf_short) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_readf_short'));
728 Pointer(sf_writef_short) := DynLibs.GetProcedureAddress(
729 sf_Handle, PChar('sf_writef_short'));
730 Pointer(sf_readf_int) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_readf_int'));
731 Pointer(sf_writef_int) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_writef_int'));
732 Pointer(sf_readf_float) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_readf_float'));
733 Pointer(sf_writef_float) := DynLibs.GetProcedureAddress(
734 sf_Handle, PChar('sf_writef_float'));
735 Pointer(sf_readf_double) := DynLibs.GetProcedureAddress(
736 sf_Handle, PChar('sf_readf_double'));
737 Pointer(sf_writef_double) := DynLibs.GetProcedureAddress(
738 sf_Handle, PChar('sf_writef_double'));
739 Pointer(sf_read_short) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_read_short'));
740 Pointer(sf_write_short) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_write_short'));
741 Pointer(sf_read_int) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_read_int'));
742 Pointer(sf_write_int) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_write_int'));
743 Pointer(sf_read_float) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_read_float'));
744 Pointer(sf_write_float) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_write_float'));
745 Pointer(sf_read_double) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_read_double'));
746 Pointer(sf_write_double) := DynLibs.GetProcedureAddress(
747 sf_Handle, PChar('sf_write_double'));
748 Pointer(sf_close) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_close'));
749 Pointer(sf_write_sync) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_write_sync'));
750
751 end;
752 Result := sf_IsLoaded;
753 ReferenceCounter := 1;
754 end;
755
756end;
757
758procedure sf_Unload;
759begin
760 // < Reference counting
761 if ReferenceCounter > 0 then
762 Dec(ReferenceCounter);
763 if ReferenceCounter > 0 then
764 exit;
765 // >
766 if sf_IsLoaded then
767 begin
768 DynLibs.UnloadLibrary(sf_Handle);
769 sf_Handle := DynLibs.NilHandle;
770 end;
771
772end;
773
774function sf_open(path: string; mode: ctypes.cint;
775 var sfinfo: TSF_INFO): TSNDFILE_HANDLE;
776begin
777 Result := sf_open_native(PChar(path), mode, @sfinfo);
778end;
779
780function sf_IsLoaded: boolean;
781begin
782 Result := (sf_Handle <> dynlibs.NilHandle);
783end;
784
785end.
Note: See TracBrowser for help on using the repository browser.