123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233 |
- {
- * Copyright (c) 2012 Andrey Kemka
- *
- * This software is provided 'as-is', without any express or
- * implied warranty. In no event will the authors be held
- * liable for any damages arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute
- * it freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented;
- * you must not claim that you wrote the original software.
- * If you use this software in a product, an acknowledgment
- * in the product documentation would be appreciated but
- * is not required.
- *
- * 2. Altered source versions must be plainly marked as such,
- * and must not be misrepresented as being the original software.
- *
- * 3. This notice may not be removed or altered from any
- * source distribution.
- }
- unit zglModPlug;
- {$I zglCustomConfig.cfg}
- {$IFDEF FPC}
- {$MODE DELPHI}
- {$PACKRECORDS C}
- {$MINENUMSIZE 4}
- {$ENDIF}
- interface
- uses
- {$IFDEF USE_ZENGL_STATIC}
- zgl_types,
- zgl_application,
- zgl_main,
- zgl_sound,
- zgl_log,
- zgl_file,
- zgl_memory,
- zgl_utils
- {$ELSE}
- zglHeader
- {$ENDIF}
- ;
- const
- {$IFDEF WINDOWS}
- libmodplug = 'libmodplug.dll';
- {$ENDIF}
- {$IFDEF LINUX}
- libmodplug = 'libmodplug.so';
- {$ENDIF}
- {$IFDEF MACOSX}
- libmodplug = 'libmodplug.dylib';
- {$ENDIF}
- MAX_FORMATS = 22;
- procedure InitModPlug;
- procedure FreeModPlug;
- implementation
- const
- MODPLUG_ENABLE_OVERSAMPLING = 1 shl 0;
- MODPLUG_ENABLE_NOISE_REDUCTION = 1 shl 1;
- MODPLUG_ENABLE_REVERB = 1 shl 2;
- MODPLUG_ENABLE_MEGABASS = 1 shl 3;
- MODPLUG_ENABLE_SURROUND = 1 shl 4;
- MODPLUG_RESAMPLE_NEAREST = 0;
- MODPLUG_RESAMPLE_LINEAR = 1;
- MODPLUG_RESAMPLE_SPLINE = 2;
- MODPLUG_RESAMPLE_FIR = 3;
- type
- PModPlugFile = ^ModPlugFile;
- ModPlugFile = record
- end;
- var
- Decoders : array[ 0..MAX_FORMATS - 1 ] of zglTSoundDecoder;
- FORMATS : array[ 0..MAX_FORMATS - 1 ] of UTF8String = ( 'MOD', 'IT', 'S3M', 'XM', 'IT', '669', 'AMF', 'AMS', 'DBM', 'DMF', 'DSM', 'FAR',
- 'MDL', 'MED', 'MTM', 'OKT', 'PTM', 'STM', 'ULT', 'UMX', 'MT2', 'PSM' );
- mpLoad : Boolean;
- mpInit : Boolean;
- mpLibrary : {$IFDEF WIN32} LongWord {$ELSE} Pointer {$ENDIF};
- ModPlug_Load : function(data: pointer; size: longint): PModPlugFile; cdecl;
- ModPlug_Unload : procedure(_file: PModPlugFile); cdecl;
- ModPlug_Read : function(_file: PModPlugFile; buffer: pointer; size: longint): longint; cdecl;
- ModPlug_Seek : procedure(_file: PModPlugFile; millisecond: longint); cdecl;
- ModPlug_GetLength : function(_file: PModPlugFile): longint; cdecl;
- function mp_DecoderOpen( var Stream : zglTSoundStream; const FileName : UTF8String ) : Boolean;
- var
- mem : zglTMemory;
- begin
- if not mpLoad Then InitModPlug();
- if not mpInit Then exit;
- mem_LoadFromFile( mem, FileName );
- PModPlugFile( Stream._data ) := ModPlug_Load( mem.Memory, mem.Size );
- mem_Free( mem );
- if Assigned( Stream._data ) Then
- begin
- Result := TRUE;
- Stream.Bits := 16;
- Stream.Frequency := 44100;
- Stream.Channels := 2;
- Stream.Duration := ModPlug_GetLength( PModPlugFile( Stream._data ) );
- Stream.BufferSize := 64 * 1024;
- zgl_GetMem( Pointer( Stream.Buffer ), Stream.BufferSize );
- end else
- Result := FALSE;
- end;
- function mp_DecoderOpenMem( var Stream : zglTSoundStream; const Memory : zglTMemory ) : Boolean;
- begin
- if not mpLoad Then InitModPlug;
- if not mpInit Then exit;
- PModPlugFile( Stream._data ) := ModPlug_Load( Memory.Memory, Memory.Size );
- if Assigned( Stream._data ) Then
- begin
- Result := TRUE;
- Stream.Bits := 16;
- Stream.Frequency := 44100;
- Stream.Channels := 2;
- Stream.Duration := ModPlug_GetLength( PModPlugFile( Stream._data ) );
- Stream.BufferSize := 64 * 1024;
- zgl_GetMem( Pointer( Stream.Buffer ), Stream.BufferSize );
- end else
- Result := FALSE;
- end;
- function mp_DecoderRead( var Stream : zglTSoundStream; Buffer : PByteArray; Bytes : LongWord; out _End : Boolean ) : LongWord;
- begin
- if not mpInit Then exit;
- Result := ModPlug_Read( PModPlugFile( Stream._data ), @Buffer[ 0 ], Bytes );
- _End := Result = 0;
- end;
- procedure mp_DecoderLoop( var Stream : zglTSoundStream );
- begin
- if not mpInit Then exit;
- ModPlug_Seek( PModPlugFile( Stream._data ), 0 );
- end;
- procedure mp_DecoderClose( var Stream : zglTSoundStream );
- begin
- if not mpInit Then exit;
- ModPlug_Unload( PModPlugFile( Stream._data ) );
- Stream._data := nil;
- end;
- procedure InitModPlug;
- begin
- {$IFDEF LINUX}
- {$IFNDEF ANDROID}
- mpLibrary := dlopen( PAnsiChar( './' + libmodplug + '.1' ), $001 );
- if mpLibrary = LIB_ERROR Then mpLibrary := dlopen( PAnsiChar( libmodplug + '.1' ), $001 );
- if mpLibrary = LIB_ERROR Then mpLibrary := dlopen( PAnsiChar( libmodplug + '.0' ), $001 );
- {$ELSE}
- mpLibrary := dlopen( libmodplug, $001 );
- {$ENDIF}
- {$ENDIF}
- {$IFDEF WINDOWS}
- mpLibrary := dlopen( libmodplug );
- {$ENDIF}
- {$IFDEF MACOSX}
- mpLibrary := dlopen( PAnsiChar( PAnsiChar( zgl_Get( DIRECTORY_APPLICATION ) ) + 'Contents/Frameworks/' + libmodplug ), $001 );
- {$ENDIF}
- if mpLibrary <> LIB_ERROR Then
- begin
- ModPlug_Load := dlsym( mpLibrary, 'ModPlug_Load' );
- ModPlug_Unload := dlsym( mpLibrary, 'ModPlug_Unload' );
- ModPlug_Read := dlsym( mpLibrary, 'ModPlug_Read' );
- ModPlug_Seek := dlsym( mpLibrary, 'ModPlug_Seek' );
- ModPlug_GetLength := dlsym( mpLibrary, 'ModPlug_GetLength' );
- log_Add( 'ModPlug: Successful initialized' );
- mpInit := TRUE;
- end else
- begin
- log_Add( 'ModPlug: Error while loading ' + libmodplug );
- mpInit := FALSE;
- end;
- mpLoad := TRUE;
- end;
- procedure FreeModPlug;
- begin
- mpInit := FALSE;
- dlclose( mpLibrary );
- end;
- var
- i : Integer;
- initialization
- for i := 0 to MAX_FORMATS - 1 do
- begin
- Decoders[ i ].Ext := FORMATS[ i ];
- Decoders[ i ].Open := @mp_DecoderOpen;
- Decoders[ i ].OpenMem := @mp_DecoderOpenMem;
- Decoders[ i ].Read := @mp_DecoderRead;
- Decoders[ i ].Seek := nil;
- Decoders[ i ].Loop := @mp_DecoderLoop;
- Decoders[ i ].Close := @mp_DecoderClose;
- zgl_Reg( SND_FORMAT_EXTENSION, @FORMATS[ i, 1 ] );
- zgl_Reg( SND_FORMAT_FILE_LOADER, nil );
- zgl_Reg( SND_FORMAT_MEM_LOADER, nil );
- zgl_Reg( SND_FORMAT_DECODER, @Decoders[ i ] );
- end;
- finalization
- if mpInit Then
- FreeModPlug();
- end.
|