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 |
|
---|
9 | unit 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 |
|
---|
24 | interface
|
---|
25 |
|
---|
26 | uses
|
---|
27 | dynlibs, classes,
|
---|
28 | ctypes;
|
---|
29 |
|
---|
30 | const
|
---|
31 | libsf=
|
---|
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 |
|
---|
42 | type
|
---|
43 | PMemoryStream = ^TMemoryStream;
|
---|
44 |
|
---|
45 | type
|
---|
46 | {$IF Defined(MSWINDOWS)}
|
---|
47 | off_t = int64;
|
---|
48 | {$ELSE}
|
---|
49 | off_t = clonglong;
|
---|
50 | size_t = culong;
|
---|
51 | {$ENDIF}
|
---|
52 |
|
---|
53 | const
|
---|
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 |
|
---|
79 | const
|
---|
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 |
|
---|
114 | const
|
---|
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 | }
|
---|
130 | const
|
---|
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 | }
|
---|
202 | const
|
---|
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 |
|
---|
221 | const
|
---|
222 | // True and false
|
---|
223 | SF_FALSE = 0;
|
---|
224 | SF_TRUE = 1;
|
---|
225 |
|
---|
226 | const
|
---|
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 | }
|
---|
238 | const
|
---|
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 |
|
---|
247 | type
|
---|
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 | }
|
---|
260 | type
|
---|
261 | Puos_count_t = ^Tuos_count_t;
|
---|
262 | Tuos_count_t = off_t;
|
---|
263 |
|
---|
264 | const
|
---|
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 |
|
---|
273 | type
|
---|
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 |
|
---|
298 | type
|
---|
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 | }
|
---|
312 | const
|
---|
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 |
|
---|
320 | type
|
---|
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 | }
|
---|
333 | type
|
---|
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 |
|
---|
343 | const
|
---|
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 |
|
---|
350 | type
|
---|
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.
|
---|
369 | type
|
---|
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 | }
|
---|
399 | type
|
---|
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 |
|
---|
453 | function 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..
|
---|
457 | var
|
---|
458 | sf_open_native: function(path: PChar;
|
---|
459 | mode: ctypes.cint; sfinfo: PSF_INFO): TSNDFILE_HANDLE; cdecl;
|
---|
460 |
|
---|
461 | var
|
---|
462 | sf_version_string: function(): PChar; cdecl;
|
---|
463 |
|
---|
464 | var
|
---|
465 | sf_open_fd: function(fd: ctypes.cint; mode: ctypes.cint; sfinfo: PSF_INFO;
|
---|
466 | close_desc: ctypes.cint): TSNDFILE_HANDLE; cdecl;
|
---|
467 |
|
---|
468 | var
|
---|
469 | sf_open_virtual: function(sfvirtual: PSF_VIRTUAL; mode: ctypes.cint;
|
---|
470 | sfinfo: PSF_INFO; user_data: Pointer): TSNDFILE_HANDLE; cdecl;
|
---|
471 |
|
---|
472 | var
|
---|
473 | sf_error: function(sndfile: TSNDFILE_HANDLE): ctypes.cint; cdecl;
|
---|
474 |
|
---|
475 | var
|
---|
476 | sf_strerror: function(sndfile: TSNDFILE_HANDLE): PChar; cdecl;
|
---|
477 |
|
---|
478 | var
|
---|
479 | sf_error_number: function(errnum: ctypes.cint): PChar; cdecl;
|
---|
480 |
|
---|
481 | var
|
---|
482 | sf_perror: function(sndfile: TSNDFILE_HANDLE): ctypes.cint; cdecl;
|
---|
483 |
|
---|
484 | var
|
---|
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 |
|
---|
495 | var
|
---|
496 | sf_command_pointer: function(sndfile: TSNDFILE_HANDLE; command: ctypes.cint;
|
---|
497 | Data: Pointer; datasize: ctypes.cint): ctypes.cint; cdecl;
|
---|
498 |
|
---|
499 | var
|
---|
500 | sf_command_double: function(sndfile: TSNDFILE_HANDLE; command: ctypes.cint;
|
---|
501 | var Data: double; datasize: ctypes.cint): ctypes.cint; cdecl;
|
---|
502 |
|
---|
503 | var
|
---|
504 | sf_command_array: function(sndfile: TSNDFILE_HANDLE; command: ctypes.cint;
|
---|
505 | var Data: array of char; datasize: ctypes.cint): ctypes.cint; cdecl;
|
---|
506 |
|
---|
507 | var
|
---|
508 | sf_command_tsf: function(sndfile: TSNDFILE_HANDLE; command: ctypes.cint;
|
---|
509 | var Data: TSF_BROADCAST_INFO; datasize: ctypes.cint): ctypes.cint; cdecl;
|
---|
510 |
|
---|
511 | var
|
---|
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:
|
---|
528 | const
|
---|
529 | SEEK_SET = 0; //* seek relative to beginning of file */
|
---|
530 |
|
---|
531 | const
|
---|
532 | SEEK_CUR = 1; //* seek relative to current file position */
|
---|
533 |
|
---|
534 | const
|
---|
535 | SEEK_END = 2; //* seek relative to end of file */
|
---|
536 |
|
---|
537 | const
|
---|
538 | SEEK_DATA = 3; //* seek to the next data */
|
---|
539 |
|
---|
540 | const
|
---|
541 | SEEK_HOLE = 4; //* seek to the next hole */
|
---|
542 |
|
---|
543 | const
|
---|
544 | SEEK_MAX = SEEK_HOLE;
|
---|
545 |
|
---|
546 | var
|
---|
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 | }
|
---|
558 | var
|
---|
559 | sf_set_string: function(sndfile: TSNDFILE_HANDLE; str_type: ctypes.cint;
|
---|
560 | str: ctypes.pcchar): ctypes.cint; cdecl;
|
---|
561 |
|
---|
562 | var
|
---|
563 | sf_get_string: function(sndfile: TSNDFILE_HANDLE;
|
---|
564 | str_type: ctypes.cint): PChar; cdecl;
|
---|
565 |
|
---|
566 | var
|
---|
567 | sf_read_raw: function(sndfile: TSNDFILE_HANDLE; ptr: Pointer;
|
---|
568 | bytes: Tuos_count_t): Tuos_count_t; cdecl;
|
---|
569 |
|
---|
570 | var
|
---|
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 | }
|
---|
584 | var
|
---|
585 | sf_readf_short: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcshort;
|
---|
586 | frames: Tuos_count_t): Tuos_count_t; cdecl;
|
---|
587 |
|
---|
588 | var
|
---|
589 | sf_writef_short: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcshort;
|
---|
590 | frames: Tuos_count_t): Tuos_count_t; cdecl;
|
---|
591 |
|
---|
592 | var
|
---|
593 | sf_readf_int: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcint;
|
---|
594 | frames: Tuos_count_t): Tuos_count_t; cdecl;
|
---|
595 |
|
---|
596 | var
|
---|
597 | sf_writef_int: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcint;
|
---|
598 | frames: Tuos_count_t): Tuos_count_t; cdecl;
|
---|
599 |
|
---|
600 | var
|
---|
601 | sf_readf_float: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcfloat;
|
---|
602 | frames: Tuos_count_t): Tuos_count_t; cdecl;
|
---|
603 |
|
---|
604 | var
|
---|
605 | sf_writef_float: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcfloat;
|
---|
606 | frames: Tuos_count_t): Tuos_count_t; cdecl;
|
---|
607 |
|
---|
608 | var
|
---|
609 | sf_readf_double: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcdouble;
|
---|
610 | frames: Tuos_count_t): Tuos_count_t; cdecl;
|
---|
611 |
|
---|
612 | var
|
---|
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 | }
|
---|
621 | var
|
---|
622 | sf_read_short: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcshort;
|
---|
623 | frames: Tuos_count_t): Tuos_count_t; cdecl;
|
---|
624 |
|
---|
625 | var
|
---|
626 | sf_write_short: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcshort;
|
---|
627 | frames: Tuos_count_t): Tuos_count_t; cdecl;
|
---|
628 |
|
---|
629 | var
|
---|
630 | sf_read_int: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcint;
|
---|
631 | frames: Tuos_count_t): Tuos_count_t; cdecl;
|
---|
632 |
|
---|
633 | var
|
---|
634 | sf_write_int: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcint;
|
---|
635 | frames: Tuos_count_t): Tuos_count_t; cdecl;
|
---|
636 |
|
---|
637 | var
|
---|
638 | sf_read_float: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcfloat;
|
---|
639 | frames: Tuos_count_t): Tuos_count_t; cdecl;
|
---|
640 |
|
---|
641 | var
|
---|
642 | sf_write_float: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcfloat;
|
---|
643 | frames: Tuos_count_t): Tuos_count_t; cdecl;
|
---|
644 |
|
---|
645 | var
|
---|
646 | sf_read_double: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcdouble;
|
---|
647 | frames: Tuos_count_t): Tuos_count_t; cdecl;
|
---|
648 |
|
---|
649 | var
|
---|
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 | }
|
---|
658 | var
|
---|
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 | }
|
---|
666 | var
|
---|
667 | sf_write_sync: function(sndfile: TSNDFILE_HANDLE): ctypes.cint; cdecl;
|
---|
668 |
|
---|
669 | {Special function for dynamic loading of lib ...}
|
---|
670 |
|
---|
671 | var
|
---|
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 |
|
---|
675 | function sf_Load(const libfilename: string): boolean; // load the lib
|
---|
676 |
|
---|
677 | procedure sf_Unload();
|
---|
678 | // unload and frees the lib from memory : do not forget to call it before close application.
|
---|
679 |
|
---|
680 | function sf_IsLoaded: boolean;
|
---|
681 |
|
---|
682 | implementation
|
---|
683 |
|
---|
684 | var
|
---|
685 | ReferenceCounter: cardinal = 0; // Reference counter
|
---|
686 |
|
---|
687 | function sf_Load(const libfilename: string): boolean;
|
---|
688 | var
|
---|
689 | thelib: string;
|
---|
690 | begin
|
---|
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 |
|
---|
756 | end;
|
---|
757 |
|
---|
758 | procedure sf_Unload;
|
---|
759 | begin
|
---|
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 |
|
---|
772 | end;
|
---|
773 |
|
---|
774 | function sf_open(path: string; mode: ctypes.cint;
|
---|
775 | var sfinfo: TSF_INFO): TSNDFILE_HANDLE;
|
---|
776 | begin
|
---|
777 | Result := sf_open_native(PChar(path), mode, @sfinfo);
|
---|
778 | end;
|
---|
779 |
|
---|
780 | function sf_IsLoaded: boolean;
|
---|
781 | begin
|
---|
782 | Result := (sf_Handle <> dynlibs.NilHandle);
|
---|
783 | end;
|
---|
784 |
|
---|
785 | end.
|
---|