source: trunk/Packages/uos/uos_aac.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.
  • Property svn:executable set to *
File size: 31.5 KB
Line 
1{This unit is part of United Openlibraries of Sound (uos)}
2
3{This is the Dynamic loading version of FAAD2 Pascal Wrapper.
4 mcwNeAACDec.pas, mcwMP4FF.pas, mcwAAC.pas
5 By Franklyn A. Harlow Feb 2016
6 License : modified LGPL.
7 mcw* merged into uos_aac by Fred van Stappen / fiens@hotmail.com }
8
9unit uos_aac;
10
11{$mode objfpc}{$H+}
12{$PACKRECORDS C}
13
14interface
15
16uses
17 Classes, SysUtils, ctypes, math,
18 dynlibs;
19
20const
21
22 {$IFDEF unix}
23{$IFDEF darwin}
24libaa= 'libfaad.2.dylib';
25libm4= 'libmp4ff.0.dylib';
26 {$ELSE}
27libaa= 'libfaad.so.2';
28libm4= 'libmp4ff.so.0.0.0';
29 {$ENDIF}
30 {$ELSE}
31libaa= 'Faad2.dll';
32libm4= 'mp4ff.dll';
33 {$ENDIF}
34
35//////////// from mcwMP4FF.pas By Franklyn A. Harlow
36type
37
38 ArSingle = array of Single;
39 PArSingle = ^ArSingle;
40
41 read_callback_t = function(user_data : Pointer; buffer : pcfloat; length : LongWord) : LongWord; cdecl;
42 write_callback_t = function(user_data : Pointer; buffer : pcfloat; length : LongWord) : LongWord; cdecl;
43 seek_callback_t = function(user_data : Pointer; Position : cInt64) : LongWord; cdecl;
44 truncate_callback_t = function(user_data : Pointer) : LongWord; cdecl;
45
46 mp4ff_callback_t = record
47 read : read_callback_t;
48 write : write_callback_t;
49 seek : seek_callback_t;
50 truncate : truncate_callback_t;
51 user_data : Pointer;
52 end;
53 p_mp4ff_callback_t = ^mp4ff_callback_t;
54
55 mp4ff_t = pointer;
56 int32_t = LongInt;
57 int64_t = cInt64;
58 uint32_t = LongWord;
59
60var
61 mp4ff_open_read : function(f : p_mp4ff_callback_t) : mp4ff_t; cdecl;
62 mp4ff_open_read_metaonly : function(f : p_mp4ff_callback_t) : mp4ff_t; cdecl;
63 mp4ff_close : procedure(f : mp4ff_t); cdecl;
64 mp4ff_get_sample_duration : function(f : mp4ff_t; track, sample : int32_t) : int32_t; cdecl;
65 mp4ff_get_sample_duration_use_offsets : function(f : mp4ff_t; track, sample : int32_t) : int32_t; cdecl;
66 mp4ff_get_sample_position : function(f : mp4ff_t; track, sample : int32_t) : int64_t; cdecl;
67 mp4ff_get_sample_offset : function(f : mp4ff_t; track, sample : int32_t) : int32_t; cdecl;
68 mp4ff_find_sample : function(f : mp4ff_t; track : int32_t; offset : int64_t; var toskip : int32_t) : int32_t; cdecl;
69 mp4ff_find_sample_use_offsets : function(f : mp4ff_t; track : int32_t; offset : int64_t; var toskip : int32_t) : int32_t; cdecl;
70 mp4ff_set_sample_position : function(f : mp4ff_t; track : int32_t; sample : int64_t) : int32_t; cdecl;
71 mp4ff_read_sample : function(f : mp4ff_t; track, sample : int32_t; var audio_buffer : pcfloat; var bytes : LongWord) : int32_t; cdecl;
72 mp4ff_read_sample_v2 : function(f : mp4ff_t; track, sample : int32_t; buffer : pcfloat): int32_t; cdecl; //returns 0 on error, number of bytes read on success, use mp4ff_read_sample_getsize_t = function() to check buffer size needed
73 mp4ff_read_sample_getsize : function(f : mp4ff_t; track, sample : Integer) : int32_t; cdecl; //returns 0 on error, buffer size needed for mp4ff_read_sample_v2_t = function() on success
74 mp4ff_get_decoder_config : function(f : mp4ff_t; track : Integer; var ppBuf : pcfloat; var pBufSize : LongWord) : int32_t; cdecl;
75 mp4ff_free_decoder_config : procedure(Buf : pcfloat); cdecl;
76 mp4ff_get_track_type : function(f : mp4ff_t; const track : Integer) : int32_t; cdecl;
77 mp4ff_total_tracks : function(f : mp4ff_t) : int32_t; cdecl;
78 mp4ff_num_samples : function(f : mp4ff_t; track : Integer) : int32_t; cdecl;
79 mp4ff_time_scale : function(f : mp4ff_t; track : Integer) : int32_t; cdecl;
80 mp4ff_get_avg_bitrate : function(f : mp4ff_t; track : int32_t) : uint32_t; cdecl;
81 mp4ff_get_max_bitrate : function(f : mp4ff_t; track : int32_t) : uint32_t; cdecl;
82 mp4ff_get_track_duration : function(f : mp4ff_t; track : int32_t) : int64_t; cdecl; //returns _t = function(-1) if unknown
83 mp4ff_get_track_duration_use_offsets : function(f : mp4ff_t; track : int32_t) : Integer; cdecl; //returns _t = function(-1) if unknown
84 mp4ff_get_sample_rate : function(f : mp4ff_t; track : int32_t) : uint32_t; cdecl;
85 mp4ff_get_channel_count : function(f : mp4ff_t; track : int32_t) : uint32_t; cdecl;
86 mp4ff_get_audio_type : function(f : mp4ff_t; track : int32_t) : uint32_t; cdecl;
87 mp4ff_meta_get_num_items : function(f : mp4ff_t) : Integer; cdecl;
88 mp4ff_meta_get_by_index : function(f : mp4ff_t; index : LongWord; var item, value : PChar) : Integer; cdecl;
89 mp4ff_meta_get_title : function(f : mp4ff_t; var value : PChar) : Integer; cdecl;
90 mp4ff_meta_get_artist : function(f : mp4ff_t; var value : PChar) : Integer; cdecl;
91 mp4ff_meta_get_writer : function(f : mp4ff_t; var value : PChar) : Integer; cdecl;
92 mp4ff_meta_get_album : function(f : mp4ff_t; var value : PChar) : Integer; cdecl;
93 mp4ff_meta_get_date : function(f : mp4ff_t; var value : PChar) : Integer; cdecl;
94 mp4ff_meta_get_tool : function(f : mp4ff_t; var value : PChar) : Integer; cdecl;
95 mp4ff_meta_get_comment : function(f : mp4ff_t; var value : PChar) : Integer; cdecl;
96 mp4ff_meta_get_genre : function(f : mp4ff_t; var value : PChar) : Integer; cdecl;
97 mp4ff_meta_get_track : function(f : mp4ff_t; var value : PChar) : Integer; cdecl;
98 mp4ff_meta_get_disc : function(f : mp4ff_t; var value : PChar) : Integer; cdecl;
99 mp4ff_meta_get_totaltracks : function(f : mp4ff_t; var value : PChar) : Integer; cdecl;
100 mp4ff_meta_get_totaldiscs : function(f : mp4ff_t; var value : PChar) : Integer; cdecl;
101 mp4ff_meta_get_compilation : function(f : mp4ff_t; var value : PChar) : Integer; cdecl;
102 mp4ff_meta_get_tempo : function(f : mp4ff_t; var value : PChar) : Integer; cdecl;
103 mp4ff_meta_get_coverart : function(f : mp4ff_t; var value : PChar) : Integer; cdecl;
104
105function GetAACTrack(infile : mp4ff_t) : Integer;
106procedure Loadmp4ff(mp4ff : AnsiString);
107procedure UnLoadMp4ff;
108Function isMp4ffLoaded : Boolean;
109
110 //////////// from mcwNeAACDec.pas by Franklyn A. Harlow
111 Const
112 { object types for AAC }
113 MAIN = 1;
114 LC = 2;
115 SSR = 3;
116 LTP = 4;
117 HE_AAC = 5;
118 ER_LC = 17;
119 ER_LTP = 19;
120 LD = 23;
121 { special object type for DRM }
122 DRM_ER_LC = 27;
123 { header types }
124 RAW = 0;
125 ADIF = 1;
126 ADTS = 2;
127 LATM = 3;
128 { SBR signalling }
129 NO_SBR = 0;
130 SBR_UPSAMPLED = 1;
131 SBR_DOWNSAMPLED = 2;
132 NO_SBR_UPSAMPLED = 3;
133 { library output formats }
134 FAAD_FMT_16BIT = 1;
135 FAAD_FMT_24BIT = 2;
136 FAAD_FMT_32BIT = 3;
137 FAAD_FMT_FLOAT = 4;
138 FAAD_FMT_FIXED = FAAD_FMT_FLOAT;
139 FAAD_FMT_DOUBLE = 5;
140 { Capabilities }
141 { Can decode LC }
142 LC_DEC_CAP = 1 shl 0;
143 { Can decode MAIN }
144 MAIN_DEC_CAP = 1 shl 1;
145 { Can decode LTP }
146 LTP_DEC_CAP = 1 shl 2;
147 { Can decode LD }
148 LD_DEC_CAP = 1 shl 3;
149 { Can decode ER }
150 ERROR_RESILIENCE_CAP = 1 shl 4;
151 { Fixed point }
152 FIXED_POINT_CAP = 1 shl 5;
153 { Channel definitions }
154 FRONT_CHANNEL_CENTER = 1;
155 FRONT_CHANNEL_LEFT = 2;
156 FRONT_CHANNEL_RIGHT = 3;
157 SIDE_CHANNEL_LEFT = 4;
158 SIDE_CHANNEL_RIGHT = 5;
159 BACK_CHANNEL_LEFT = 6;
160 BACK_CHANNEL_RIGHT = 7;
161 BACK_CHANNEL_CENTER = 8;
162 LFE_CHANNEL = 9;
163 UNKNOWN_CHANNEL = 0;
164 { DRM channel definitions }
165 DRMCH_MONO = 1;
166 DRMCH_STEREO = 2;
167 DRMCH_SBR_MONO = 3;
168 DRMCH_SBR_STEREO = 4;
169 DRMCH_SBR_PS_STEREO = 5;
170 { A decode call can eat up to FAAD_MIN_STREAMSIZE bytes per decoded channel,
171 so at least so much bytes per channel should be available in this stream }
172 { 6144 bits/channel }
173 FAAD_MIN_STREAMSIZE = 768;
174
175Type
176 PNeAACDec = Pointer;
177
178 NeAAC_byte = {$IFDEF FPC}{$IFDEF CPU64}cuint32 {$ELSE}Byte {$ENDIF}{$ELSE}Byte {$ENDIF};
179 NeAAC_word = {$IFDEF FPC}{$IFDEF CPU64}cuint64{$ELSE}Word {$ENDIF}{$ELSE}Word {$ENDIF};
180 NeAAC_longword = {$IFDEF FPC}{$IFDEF CPU64}culong {$ELSE}LongWord{$ENDIF}{$ELSE}LongWord{$ENDIF};
181
182 NeAACDecConfiguration = record
183 defObjectType : NeAAC_byte;
184 defSampleRate : NeAAC_longword;
185 outputFormat : NeAAC_byte;
186 downMatrix : NeAAC_byte;
187 useOldADTSFormat : NeAAC_byte;
188 dontUpSampleImplicitSBR : NeAAC_byte;
189 end;
190 TNeAACDecConfiguration = NeAACDecConfiguration;
191 PNeAACDecConfiguration = ^NeAACDecConfiguration;
192
193 NeAACDecFrameInfo = record
194 bytesconsumed : NeAAC_longword;
195 samples : NeAAC_longword;
196 channels : NeAAC_byte;
197 error : NeAAC_byte;
198 samplerate : NeAAC_longword;
199 sbr : NeAAC_byte; //* SBR: 0: off, 1: on; upsample, 2: on; downsampled, 3: off; upsampled */
200 object_type : NeAAC_byte; //* MPEG-4 ObjectType */
201 header_type : NeAAC_byte; //* AAC header type; MP4 will be signalled as RAW also */
202 num_front_channels : NeAAC_byte; //* multichannel configuration */
203 num_side_channels : NeAAC_byte;
204 num_back_channels : NeAAC_byte;
205 num_lfe_channels : NeAAC_byte;
206 channel_position : array[0..63] of NeAAC_byte;
207 ps : NeAAC_byte; //* PS: 0: off, 1: on */
208 end;
209 TNeAACDecFrameInfo = NeAACDecFrameInfo;
210 PNeAACDecFrameInfo = ^NeAACDecFrameInfo;
211
212 mp4AudioSpecificConfig = record
213 objectTypeIndex : NeAAC_byte;
214 samplingFrequencyIndex : NeAAC_byte;
215 samplingFrequency : NeAAC_longword;
216 channelsConfiguration : NeAAC_byte;
217 frameLengthFlag : NeAAC_byte; //* GA Specific Info */
218 dependsOnCoreCoder : NeAAC_byte;
219 coreCoderDelay : NeAAC_word;
220 extensionFlag : NeAAC_byte;
221 aacSectionDataResilienceFlag : NeAAC_byte;
222 aacScalefactorDataResilienceFlag : NeAAC_byte;
223 aacSpectralDataResilienceFlag : NeAAC_byte;
224 epConfig : NeAAC_byte;
225 sbr_present_flag : NeAAC_byte;
226 forceUpSampling : NeAAC_byte;
227 downSampledSBR : NeAAC_byte;
228 end;
229 Tmp4AudioSpecificConfig = mp4AudioSpecificConfig;
230 Pmp4AudioSpecificConfig = ^mp4AudioSpecificConfig;
231
232 var
233 NeAACDecGetErrorMessage : function(ErrorCode : Byte) : PChar; cdecl;
234 NeAACDecGetCapabilities : function : LongWord; cdecl;
235 NeAACDecOpen : function : PNeAACDec; cdecl;
236 NeAACDecGetCurrentConfiguration : function( hDecoder : PNeAACDec) : PNeAACDecConfiguration; cdecl;
237 NeAACDecSetConfiguration : function( hDecoder : PNeAACDec; pConfig : PNeAACDecConfiguration) : Byte; cdecl;
238 NeAACDecInit : function( hDecoder : PNeAACDec; pBuffer : pcfloat; lwBufferLength : LongWord; var lwSampleRate : LongWord; var Channels : Byte) : LongInt; cdecl;
239 NeAACDecInit2 : function( hDecoder : PNeAACDec; pBuffer : pcfloat; SizeOfDecoderSpecificInfo : LongWord; var lwSampleRate : LongWord; var Channels : Byte) : Byte; cdecl;
240 NeAACDecPostSeekReset : procedure(hDecoder : PNeAACDec; Frame : LongInt); cdecl;
241 NeAACDecClose : procedure(hDecoder : PNeAACDec); cdecl;
242 NeAACDecDecode : function( hDecoder : PNeAACDec; hInfo : PNeAACDecFrameInfo; pBuffer : pcfloat; lwBufferLength : LongWord) : Pointer; cdecl;
243 NeAACDecDecode2 : function( hDecoder : PNeAACDec; hInfo : PNeAACDecFrameInfo; pBuffer : pcfloat; lwBufferLength : LongWord; var pSampleBuf : Pointer; lwSampleBufSize : LongWord) : Pointer; cdecl;
244 NeAACDecAudioSpecificConfig : function( pBuffer : pcfloat; lwBufferLength : LongWord; var mp4ASC : mp4AudioSpecificConfig) : Byte; cdecl;
245
246 procedure LoadNeAAC(NeAAC : AnsiString);
247 Procedure UnLoadNeAAC;
248 Function Is_NeAAC_Loaded : Boolean;
249
250//////////////////
251
252// from mcwAAC.pas from Franklyn A. Harlow
253Const
254 kNeAAC_OK = 1;
255 kNeAAC_FAIL = 0;
256
257Type
258
259 TAACIdata = array[0..2024*1024-1] of byte;
260
261 TAACInfo = class(TObject)
262 public
263 // libfaad control interface...
264 fsStream : TFileStream;
265 pDecoder : PNeAACDec;
266 hMP4 : mp4ff_t;
267
268 // output interface setup...
269 Channels : longword; // stereo = 2
270 BitsPerSample : longword; // ie short/smallint = 16
271 SampleRate : longword; // Frequency = 44100
272 outputFormat : byte; // See FAAD_FMT_16BIT etc...
273
274 Bitrate : longword; // 256000 = 256
275
276 TotalTime : double; // Length in Seconds
277
278 {$if not defined(fs32bit)}
279 TotalSamples : cint64;
280 Size : cint64; // in frames
281 Position : cint64; // in frames
282 {$else}
283 TotalSamples : cint;
284 Size : cint; // in frames
285 Position : cint; // in frames
286 {$endif}
287
288 // UoS interface
289 pData : pcfloat;
290 lwDataLen : longword;
291
292 // tag info...
293 Artist : AnsiString;
294 AlbumArtist : AnsiString;
295 Album : AnsiString;
296 Title : AnsiString;
297 Date : AnsiString;
298 Genre : AnsiString;
299 Track : AnsiString;
300 Comment : AnsiString;
301
302 // internal data...
303 cbs : mp4ff_callback_t;
304 _Buf : TAACIdata;
305 BufTmp : TAACIdata;
306 fTrack : longint;
307 fTimescale : longword; // Not actually used
308
309 fBufStart : longword;
310 fBufEnd : longword;
311 End;
312
313 Function aa_load(mp4ff, NeAAC: AnsiString): Boolean;
314 Procedure aa_Unload;
315 Function isLibAACLoaded : Boolean;
316
317 Function MP4OpenFile(fName : String; OutputFormat : Byte) : TAACInfo;
318 Procedure MP4CloseFile(var AACI: TAACInfo);
319 procedure MP4GetData(var AACI: TAACInfo; var Buffer: pcfloat; var Bytes: longword);
320 function MP4Seek(var AACI: TAACInfo; var SampleNum: longint) : Boolean;
321
322implementation
323
324var
325 // hNeAAC: {$IFDEF MSWINDOWS}longword{$ELSE}{$IFDEF CPU32}longword{$ELSE}PtrInt{$ENDIF}{$ENDIF};
326 hNeAAC:TLibHandle=dynlibs.NilHandle;
327 NeAACLoaded : Boolean;
328 Mp4ffLoaded : Boolean = False;
329 hMp4ff:TLibHandle=dynlibs.NilHandle;
330
331//////////// from mcwNeAACDec.pas By Franklyn A. Harlow
332
333function CBMP4Read(user_data : Pointer; buffer : pcfloat; length : LongWord) : LongWord; cdecl;
334begin
335 try
336 Result := LongWord(TAACInfo(user_data).fsStream.Read(buffer^, Integer(length)));
337 except
338 Result := 0;
339 end;
340end;
341
342function CBMP4Write(user_data : Pointer; buffer : pcfloat; length : LongWord) : LongWord; cdecl;
343begin
344 try
345 Result := LongWord(TAACInfo(user_data).fsStream.Write(buffer^, Integer(length)));
346 TAACInfo(user_data).fsStream.Position:=0;
347 except
348 Result := 0;
349 end;
350end;
351
352function CBMP4Seek(user_data : Pointer; Position : Int64) : LongWord; cdecl;
353begin
354 try
355 Result := LongWord(TAACInfo(user_data).fsStream.Seek(Position, soBeginning));
356 except
357 Result := 0;
358 end;
359end;
360
361function CBMP4Truncate(user_data : Pointer) : LongWord; cdecl;
362begin
363 Result := 0;
364end;
365
366//////////// from mcwAAC.pas By Franklyn A. Harlow
367
368Function aa_load(mp4ff, NeAAC: AnsiString): Boolean;
369Begin
370 // Safe To Call Multiple times, actual load of Lib checks to see if it is already loaded &
371 // returns true if it is...
372 LoadNeAAC(NeAAC);
373
374 Loadmp4ff(mp4ff);
375
376 Result:= Is_NeAAC_Loaded And isMp4ffLoaded;
377End;
378
379Procedure aa_Unload;
380Begin
381 UnLoadNeAAC();
382 UnLoadMp4ff();
383End;
384
385Function isLibAACLoaded : Boolean;
386Begin
387 Result:= Is_NeAAC_Loaded And isMp4ffLoaded;
388end;
389
390Function isFileAAC(fName : AnsiString): Boolean;
391Begin
392 Result:= LowerCase(ExtractFileExt(fName)) = '.m4a';
393end;
394
395Function MP4OpenFile(fName : String; OutputFormat : Byte) : TAACInfo;
396Var
397 pConfig : PNeAACDecConfiguration;
398 mp4ASC : mp4AudioSpecificConfig;
399
400 pBuf : pcfloat;
401 lwBufSize : longword;
402 lwBufSize2 : longword;
403 lwSampleRate : longword;
404 bChannels : byte;
405
406 bRet : Byte;
407 iRet : LongInt;
408 pID3 : PAnsiChar;
409 f : Double;
410Begin
411 Result:= nil;
412 if not FileExists(fName) then
413 Exit;
414 if Not isFileAAC(fName) then
415 Exit;
416 // writeln('MP4OpenFileBegin');
417
418 Result:= TAACInfo.Create;
419 // writeln('MP4OpenFile3');
420
421 Result.fsStream:= TFileStream.Create(fName, fmOpenRead or fmShareDenyWrite);
422
423 sleep(1);
424
425 // writeln('MP4OpenFile4');
426 Result.cbs.read := @CBMP4Read;
427 Result.cbs.write := @CBMP4Write;
428 Result.cbs.seek := @CBMP4Seek;
429 Result.cbs.truncate := @CBMP4Truncate;
430 Result.cbs.user_data := Pointer(Result);
431 // writeln('MP4OpenFile5');
432
433 Result.pDecoder := NeAACDecOpen();
434 // writeln('MP4OpenFile6');
435
436 pConfig := NeAACDecGetCurrentConfiguration(Result.pDecoder);
437 // writeln('MP4OpenFile7');
438 pConfig^.defObjectType := LC;
439 pConfig^.defSampleRate := 44100;
440 pConfig^.outputFormat := OutputFormat; // FAAD_FMT_FLOAT FAAD_FMT_16BIT FAAD_FMT_32BIT
441 pConfig^.downMatrix := 1;
442 pConfig^.dontUpSampleImplicitSBR := 0;
443
444 NeAACDecSetConfiguration(Result.pDecoder, pConfig) ;
445
446 pConfig := NeAACDecGetCurrentConfiguration(Result.pDecoder);
447 // writeln('MP4OpenFile9');
448
449 case pConfig^.outputFormat of
450 FAAD_FMT_16BIT : Result.BitsPerSample := 16;
451 FAAD_FMT_24BIT : Result.BitsPerSample := 24;
452 FAAD_FMT_32BIT : Result.BitsPerSample := 32;
453 FAAD_FMT_FLOAT : Result.BitsPerSample := 32;
454 FAAD_FMT_DOUBLE: Result.BitsPerSample := 64;
455 end;
456 // writeln('MP4OpenFile10');
457 Result.outputFormat:= pConfig^.outputFormat;
458
459 Result.hMP4 := mp4ff_open_read(@Result.cbs);
460 // writeln('MP4OpenFile11');
461
462 Result.fTrack := GetAACTrack(Result.hMP4);
463 // writeln('MP4OpenFile12');
464
465 pBuf:= nil;
466 iRet:= mp4ff_get_decoder_config(Result.hMP4, Result.fTrack, pBuf, lwBufSize);
467 // writeln('MP4OpenFile13');
468
469 lwBufSize2:= lwBufSize;
470 // writeln('MP4OpenFile14');
471
472 bRet:= NeAACDecInit2(Result.pDecoder, pBuf, lwBufSize, lwSampleRate, bChannels);
473 // writeln('MP4OpenFile15');
474
475 Result.SampleRate := mp4ff_get_sample_rate(Result.hMP4, Result.fTrack);
476 Result.Channels := mp4ff_get_channel_count(Result.hMP4, Result.fTrack);
477 Result.fTimescale := mp4ff_time_scale(Result.hMP4, Result.fTrack);
478 Result.Bitrate := mp4ff_get_avg_bitrate(Result.hMP4, Result.fTrack);
479 Result.Size := mp4ff_num_samples(Result.hMP4, Result.fTrack);
480 // writeln('MP4OpenFile16');
481
482 if pBuf <> nil then
483 begin
484 bRet:= NeAACDecAudioSpecificConfig(pBuf, lwBufSize2, mp4ASC);
485 // writeln('MP4OpenFile17');
486
487 if bRet <> 0 then
488 Begin
489 // unix x64, NeAACDecAudioSpecificConfig Fails correct read,
490 // But if both previous SampleRates match, we'll use them...
491 {$IFDEF unix}{$IFDEF CPU64}
492 if Result.SampleRate = lwSampleRate then
493 Begin
494 mp4ASC.sbr_present_flag := 0;
495 mp4ASC.samplingFrequency := lwSampleRate;
496 End;
497 {$ENDIF}{$ENDIF}
498 End;
499 // writeln('MP4OpenFile18');
500 mp4ff_free_decoder_config(pBuf);
501 // writeln('MP4OpenFile19');
502 end;
503
504 f := 1024.0;
505 if mp4ASC.sbr_present_flag = 1 then
506 f := f * 2.0;
507 Result.TotalTime := Result.Size * (f-1.0) / mp4ASC.samplingFrequency;
508 { ...End}
509 Result.TotalSamples := Trunc(Result.TotalTime * mp4ASC.samplingFrequency);
510 // writeln('MP4OpenFile20');
511 if mp4ASC.samplingFrequency > Result.SampleRate then
512 Result.SampleRate:= mp4ASC.samplingFrequency;
513
514 Result.Artist:= '';
515 iRet:= mp4ff_meta_get_writer(Result.hMP4, pID3);
516 if iRet = 1 then
517 Result.Artist:= pID3;
518
519 Result.AlbumArtist:= '';
520 iRet:= mp4ff_meta_get_artist(Result.hMP4, pID3);
521 if iRet = 1 then
522 Result.AlbumArtist:= pID3;
523
524 Result.Album:= '';
525 iRet:= mp4ff_meta_get_album(Result.hMP4, pID3);
526 if iRet = 1 then
527 Result.Album:= pID3;
528
529 Result.Title:= '';
530 iRet:= mp4ff_meta_get_title(Result.hMP4, pID3);
531 if iRet = 1 then
532 Result.Title:= pID3;
533
534 Result.Date:= '';
535 iRet:= mp4ff_meta_get_date(Result.hMP4, pID3);
536 if iRet = 1 then
537 Result.Date:= pID3;
538
539 Result.Genre:= '';
540 iRet:= mp4ff_meta_get_genre(Result.hMP4, pID3);
541 if iRet = 1 then
542 Result.Genre:= pID3;
543
544 Result.Track:= '';
545 iRet:= mp4ff_meta_get_track(Result.hMP4, pID3);
546 if iRet = 1 then
547 Result.Track:= pID3;
548
549 Result.Comment:= '';
550 iRet:= mp4ff_meta_get_comment(Result.hMP4, pID3);
551 if iRet = 1 then
552 Result.Comment:= pID3;
553
554 Result.Position := 0;
555 Result.fBufStart := 0;
556 Result.fBufEnd := 0;
557 // writeln('MP4OpenFile End');
558end;
559
560Procedure MP4CloseFile(var AACI: TAACInfo);
561Begin
562 // writeln('MP4CloseFile1');
563 NeAACDecClose(AACI.pDecoder);
564 sleep(50);
565 // writeln('MP4CloseFile2');
566 mp4ff_close(AACI.hMP4);
567 // writeln('MP4CloseFile3');
568 sleep(50);
569 end;
570
571procedure MP4GetData(var AACI: TAACInfo; var Buffer: pcfloat; var Bytes: longword);
572var
573 ReqBytes : longword;
574 CurBufSize : longword;
575 NewSampleBuf : Pointer;
576 NewBytesRead : longword;
577 NewBytesDecoded : longword;
578
579 Function readNextSample(var audioBuf : pcfloat; var audioSize : longword): longword;
580 Begin
581 audioSize := 0;
582 Result:= 0;
583 audioBuf := nil;
584 // writeln('readNextSample');
585 if AACI.Position > AACI.Size then
586 Begin
587 Result:= 0;
588 Exit;
589 end;
590 Result := mp4ff_read_sample(AACI.hMP4, AACI.fTrack, AACI.Position, audioBuf, audioSize);
591 Inc(AACI.Position);
592 end;
593
594 Function getNextChunk(var SampBuf : Pointer; var NBR : longword) : longword;
595 Var
596 pAB : pcfloat;
597 iAB : longword;
598 frameInfo: NeAACDecFrameInfo;
599 Begin
600 NBR:= 0;
601 // writeln('getNextChunk');
602 Result:= 0;
603 Result:= readNextSample(pAB, iAB);
604 if Result = 0 then Exit;
605 SampBuf := NeAACDecDecode(AACI.pDecoder, @frameInfo, pAB, iAB);
606 if pAB <> nil then
607 mp4ff_free_decoder_config(pAB);
608
609 NBR:= frameInfo.samples * (AACI.BitsPerSample div 8);
610 end;
611
612begin
613 // writeln('MP4GetData1');
614 ReqBytes:= Bytes;
615 // writeln('MP4GetDataBegin1-2');
616 CurBufSize:= AACI.fBufEnd - AACI.fBufStart;
617
618 While ReqBytes > CurBufSize do
619 Begin
620 // writeln('MP4GetData31');
621 // We need to put more data into Buffer...
622
623 // If We Have Left Over Data...
624 if CurBufSize > 0 then
625 Begin
626 // Save Existing Left over data..
627 Move(AACI._Buf[AACI.fBufStart], AACI.BufTmp[0], CurBufSize);
628 // Put Existing Data to Start of buffer...
629 Move(AACI.BufTmp[0], AACI._Buf[0], CurBufSize);
630 end;
631
632 // writeln('MP4GetData32');
633 // because we reshuffled buffers, AACI.fBufStart is now 0
634 AACI.fBufStart:= 0;
635 NewSampleBuf := nil;
636 // Read next block of data
637
638 NewBytesRead:= getNextChunk(NewSampleBuf, NewBytesDecoded);
639
640 // writeln('MP4GetData322');
641 if NewBytesRead = 0 then
642 begin
643 Buffer := nil;
644 Bytes := 0;
645 Exit;
646 end;
647 // writeln('MP4GetData33');
648 // Append new data to buffer
649 Move(NewSampleBuf^, AACI._Buf[CurBufSize], NewBytesDecoded);
650 // Update current unprocessed data count
651 CurBufSize:= CurBufSize + NewBytesDecoded;
652 // writeln('MP4GetData34');
653 end;
654
655 // writeln('MP4GetData4');
656
657 // set AACI.fBufEnd to last valid data byte in buffer
658 AACI.fBufEnd:= CurBufSize;
659
660 // writeln('MP4GetData5');
661
662 // If requested Byte count is more tha what we have, reduce requested count..
663 if Bytes > AACI.fBufEnd - AACI.fBufStart then
664 Bytes := AACI.fBufEnd - AACI.fBufStart;
665
666 // writeln('MP4GetData6');
667
668 // pass data back to calling function/procedure
669 Buffer := @AACI._Buf[AACI.fBufStart];
670
671 // writeln('MP4GetData7');
672
673 Inc(AACI.fBufStart, Bytes);
674
675 // writeln('MP4GetData8');
676
677end;
678
679function MP4Seek(var AACI: TAACInfo; var SampleNum: longint) : Boolean;
680begin
681 Result := False;
682 if (AACI.Size = 0) or (AACI.TotalSamples = 0) then
683 Exit;
684
685 if SampleNum > AACI.TotalSamples then
686 SampleNum := AACI.TotalSamples;
687
688 AACI.Position:= Trunc(SampleNum / AACI.TotalSamples * AACI.Size);
689 Result := True;
690end;
691
692procedure LoadNeAAC(NeAAC : AnsiString);
693var
694thelib: string;
695Begin
696 if Length(NeAAC) = 0 then thelib := libaa else thelib := NeAAC;
697 hNeAAC:= DynLibs.SafeLoadLibrary(PChar(thelib));
698 NeAACLoaded:= hNeAAC <> dynlibs.NilHandle;
699
700 Pointer(NeAACDecGetErrorMessage) :=
701 GetProcAddress(hNeAAC, PChar('NeAACDecGetErrorMessage'));
702 Pointer(NeAACDecGetCapabilities) :=
703 GetProcAddress(hNeAAC, PChar('NeAACDecGetCapabilities'));
704 Pointer(NeAACDecOpen) :=
705 GetProcAddress(hNeAAC, PChar('NeAACDecOpen'));
706 Pointer(NeAACDecGetCurrentConfiguration) :=
707 GetProcAddress(hNeAAC, PChar('NeAACDecGetCurrentConfiguration'));
708 Pointer(NeAACDecSetConfiguration) :=
709 GetProcAddress(hNeAAC, PChar('NeAACDecSetConfiguration'));
710 Pointer(NeAACDecInit) :=
711 GetProcAddress(hNeAAC, PChar('NeAACDecInit'));
712 Pointer(NeAACDecInit2) :=
713 GetProcAddress(hNeAAC, PChar('NeAACDecInit2'));
714 Pointer(NeAACDecPostSeekReset) :=
715 GetProcAddress(hNeAAC, PChar('NeAACDecPostSeekReset'));
716 Pointer(NeAACDecClose) :=
717 GetProcAddress(hNeAAC, PChar('NeAACDecClose'));
718 Pointer(NeAACDecDecode) :=
719 GetProcAddress(hNeAAC, PChar('NeAACDecDecode'));
720 Pointer(NeAACDecDecode2) :=
721 GetProcAddress(hNeAAC, PChar('NeAACDecDecode2'));
722 Pointer(NeAACDecPostSeekReset) :=
723 GetProcAddress(hNeAAC, PChar('NeAACDecPostSeekReset'));
724 Pointer(NeAACDecAudioSpecificConfig) :=
725 GetProcAddress(hNeAAC, PChar('NeAACDecAudioSpecificConfig'));
726end;
727
728Procedure UnLoadNeAAC;
729Begin
730 if NeAACLoaded then
731 DynLibs.UnloadLibrary(hNeAAC);
732 NeAACLoaded:= False;
733end;
734
735Function Is_NeAAC_Loaded : Boolean;
736Begin
737 Result:= NeAACLoaded;
738end;
739
740////////////////////////////// from mcwMP4FF.pas by Franklyn A. Harlow
741
742function GetAACTrack(infile : mp4ff_t) : Integer;
743var
744 i, rc, numTracks : Integer;
745 buff : pcfloat;
746 buff_size : LongWord;
747 mp4ASC : mp4AudioSpecificConfig;
748begin
749 numTracks := mp4ff_total_tracks(infile);
750 for i := 0 to numTracks - 1 do
751 begin
752 buff := nil;
753 buff_size:=0;
754 mp4ff_get_decoder_config(infile, i, buff, buff_size);
755 if buff <> nil then
756 begin
757 rc := NeAACDecAudioSpecificConfig(buff, buff_size, mp4ASC);
758 mp4ff_free_decoder_config(buff);
759 if rc < 0 then
760 continue;
761 Result := i;
762 Exit;
763 end;
764 end;
765 Result := -1;
766end;
767
768procedure UnLoadMp4ff;
769begin
770 if Mp4ffLoaded then
771
772 DynLibs.UnloadLibrary(hMp4ff);
773
774 Mp4ffLoaded := False;
775end;
776
777Function isMp4ffLoaded : Boolean;
778Begin
779Result:= Mp4ffLoaded;
780end;
781
782
783 procedure Loadmp4ff(mp4ff : AnsiString);
784 var
785thelib: string;
786begin
787 if Mp4ffLoaded then
788 Exit;
789 if Length(mp4ff) = 0 then thelib := libm4 else thelib := mp4ff;
790 hMp4ff := DynLibs.SafeLoadLibrary(PChar(thelib));
791 Mp4ffLoaded := hMp4ff <> dynlibs.NilHandle;
792
793 // writeln('hMp4ff' + inttostr(hMp4ff));
794
795 Pointer(mp4ff_open_read) :=
796 GetProcAddress(hMp4ff, pchar('mp4ff_open_read'));
797
798 // if Pointer(mp4ff_open_read) <> nil then
799 // writeln('mp4ff_open_read OK') else
800 // writeln('mp4ff_open_read NOT OK');
801
802 Pointer(mp4ff_open_read_metaonly) :=
803 GetProcAddress(hMp4ff, PChar('mp4ff_open_read_metaonly'));
804 Pointer(mp4ff_close) :=
805 GetProcAddress(hMp4ff, PChar('mp4ff_close'));
806 Pointer(mp4ff_get_sample_duration) :=
807 GetProcAddress(hMp4ff, PChar('mp4ff_get_sample_duration'));
808 Pointer(mp4ff_get_sample_duration_use_offsets) :=
809 GetProcAddress(hMp4ff, PChar('mp4ff_get_sample_duration_use_offsets'));
810 Pointer(mp4ff_get_sample_position) :=
811 GetProcAddress(hMp4ff, PChar('mp4ff_get_sample_position'));
812 Pointer(mp4ff_get_sample_offset) :=
813 GetProcAddress(hMp4ff, PChar('mp4ff_get_sample_offset'));
814 Pointer(mp4ff_find_sample) :=
815 GetProcAddress(hMp4ff, PChar('mp4ff_find_sample'));
816
817 Pointer(mp4ff_find_sample_use_offsets) :=
818 GetProcAddress(hMp4ff, PChar('mp4ff_find_sample_use_offsets'));
819 Pointer(mp4ff_set_sample_position) :=
820 GetProcAddress(hMp4ff, PChar('mp4ff_set_sample_position'));
821 Pointer(mp4ff_read_sample) :=
822 GetProcAddress(hMp4ff, PChar('mp4ff_read_sample'));
823 Pointer(mp4ff_read_sample_v2) :=
824 GetProcAddress(hMp4ff, PChar('mp4ff_read_sample_v2'));
825 Pointer(mp4ff_read_sample_getsize) :=
826 GetProcAddress(hMp4ff, PChar('mp4ff_read_sample_getsize'));
827 Pointer(mp4ff_get_sample_position) :=
828 GetProcAddress(hMp4ff, PChar('mp4ff_get_sample_position'));
829 Pointer(mp4ff_get_sample_offset) :=
830 GetProcAddress(hMp4ff, PChar('mp4ff_get_sample_offset'));
831 Pointer(mp4ff_find_sample) :=
832 GetProcAddress(hMp4ff, PChar('mp4ff_find_sample'));
833
834 Pointer(mp4ff_get_decoder_config) :=
835 GetProcAddress(hMp4ff, PChar('mp4ff_get_decoder_config'));
836 Pointer(mp4ff_get_track_type) :=
837 GetProcAddress(hMp4ff, PChar('mp4ff_get_track_type'));
838 Pointer(mp4ff_total_tracks) :=
839 GetProcAddress(hMp4ff, PChar('mp4ff_total_tracks'));
840 Pointer(mp4ff_num_samples) :=
841 GetProcAddress(hMp4ff, PChar('mp4ff_num_samples'));
842 Pointer(mp4ff_time_scale) :=
843 GetProcAddress(hMp4ff, PChar('mp4ff_time_scale'));
844 Pointer(mp4ff_get_avg_bitrate) :=
845 GetProcAddress(hMp4ff, PChar('mp4ff_get_avg_bitrate'));
846 Pointer(mp4ff_get_max_bitrate) :=
847 GetProcAddress(hMp4ff, PChar('mp4ff_get_max_bitrate'));
848 Pointer(mp4ff_get_track_duration) :=
849 GetProcAddress(hMp4ff, PChar('mp4ff_get_track_duration'));
850
851 Pointer(mp4ff_get_track_duration_use_offsets) :=
852 GetProcAddress(hMp4ff, PChar('mp4ff_get_track_duration_use_offsets'));
853 Pointer(mp4ff_get_sample_rate) :=
854 GetProcAddress(hMp4ff, PChar('mp4ff_get_sample_rate'));
855 Pointer(mp4ff_get_channel_count) :=
856 GetProcAddress(hMp4ff, PChar('mp4ff_get_channel_count'));
857 Pointer(mp4ff_get_audio_type) :=
858 GetProcAddress(hMp4ff, PChar('mp4ff_get_audio_type'));
859 Pointer(mp4ff_free_decoder_config) :=
860 GetProcAddress(hMp4ff, PChar('mp4ff_free_decoder_config'));
861 Pointer(mp4ff_meta_get_num_items) :=
862 GetProcAddress(hMp4ff, PChar('mp4ff_meta_get_num_items'));
863 Pointer(mp4ff_meta_get_by_index) :=
864 GetProcAddress(hMp4ff, PChar('mp4ff_meta_get_by_index'));
865 Pointer(mp4ff_meta_get_title) :=
866 GetProcAddress(hMp4ff, PChar('mp4ff_meta_get_title'));
867
868 Pointer(mp4ff_meta_get_artist) :=
869 GetProcAddress(hMp4ff, PChar('mp4ff_meta_get_artist'));
870 Pointer(mp4ff_meta_get_writer) :=
871 GetProcAddress(hMp4ff, PChar('mp4ff_meta_get_writer'));
872 Pointer(mp4ff_meta_get_album) :=
873 GetProcAddress(hMp4ff, PChar('mp4ff_meta_get_album'));
874 Pointer(mp4ff_meta_get_date) :=
875 GetProcAddress(hMp4ff, PChar('mp4ff_meta_get_date'));
876 Pointer(mp4ff_meta_get_tool) :=
877 GetProcAddress(hMp4ff, PChar('mp4ff_meta_get_tool'));
878 Pointer(mp4ff_meta_get_comment) :=
879 GetProcAddress(hMp4ff, PChar('mp4ff_meta_get_comment'));
880 Pointer(mp4ff_meta_get_genre) :=
881 GetProcAddress(hMp4ff, PChar('mp4ff_meta_get_genre'));
882 Pointer(mp4ff_meta_get_track) :=
883 GetProcAddress(hMp4ff, PChar('mp4ff_meta_get_track'));
884
885 Pointer(mp4ff_meta_get_disc) :=
886 GetProcAddress(hMp4ff, PChar('mp4ff_meta_get_disc'));
887 Pointer(mp4ff_meta_get_totaltracks) :=
888 GetProcAddress(hMp4ff, PChar('mp4ff_meta_get_totaltracks'));
889 Pointer(mp4ff_meta_get_totaldiscs) :=
890 GetProcAddress(hMp4ff, PChar('mp4ff_meta_get_totaldiscs'));
891 Pointer(mp4ff_meta_get_compilation) :=
892 GetProcAddress(hMp4ff, PChar('mp4ff_meta_get_compilation'));
893 Pointer(mp4ff_meta_get_tempo) :=
894 GetProcAddress(hMp4ff, PChar('mp4ff_meta_get_tempo'));
895 Pointer(mp4ff_meta_get_coverart) :=
896 GetProcAddress(hMp4ff, PChar('mp4ff_meta_get_coverart'));
897
898end;
899
900initialization
901 NeAACLoaded:= False;
902 SetExceptionMask(GetExceptionMask + [exZeroDivide] + [exInvalidOp] +
903 [exDenormalized] + [exOverflow] + [exPrecision]);
904
905finalization
906end.
Note: See TracBrowser for help on using the repository browser.