123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374 |
- program test;
- {$mode objfpc}
- uses
- classes, sysutils, ctypes, openal, mad, ogg, vorbis, a52, dts, modplug, matroska;
- var
- source : TStream;
- codec : Integer;
- codec_bs : Longword;
- codec_read : function(const Buffer: Pointer; const Count: Longword): Longword = nil;
- codec_rate : Longword;
- codec_chan : Longword;
- function source_read_func(datasource: pointer; ptr: pointer; size: cuint): cuint; cdecl;
- begin
- Result := TStream(datasource).Read(ptr^, size);
- end;
- function source_read_func_ogg(ptr: pointer; size, nmemb: csize_t; datasource: pointer): csize_t; cdecl;
- begin
- Result := TStream(datasource).Read(ptr^, size*nmemb);
- end;
- function source_seek_func(datasource: pointer; offset: clong; whence: cint): clong; cdecl;
- begin
- case whence of
- {SEEK_SET} 0: Result := TStream(datasource).Seek(offset, soFromBeginning);
- {SEEK_CUR} 1: Result := TStream(datasource).Seek(offset, soFromCurrent);
- {SEEK_END} 2: Result := TStream(datasource).Seek(offset, soFromEnd);
- else Result := 0;
- end;
- end;
- function source_seek_func_ogg(datasource: pointer; offset: ogg_int64_t; whence: cint): cint; cdecl;
- begin
- case whence of
- {SEEK_SET} 0: TStream(datasource).Seek(offset, soFromBeginning);
- {SEEK_CUR} 1: TStream(datasource).Seek(offset, soFromCurrent);
- {SEEK_END} 2: TStream(datasource).Seek(offset, soFromEnd);
- end;
- Result := 0;
- end;
- function source_close_func(datasource: pointer): cint; cdecl;
- begin
- TStream(datasource).Position := 0;
- Result := 0;
- end;
- function source_tell_func(datasource: pointer): clong; cdecl;
- begin
- Result := TStream(datasource).Position;
- end;
- // mad
- var
- mad_decoder: pmad_decoder;
- {procedure mad_reset;
- begin
- mad_stream_finish(m_stream);
- mad_stream_init(m_stream);
- source.Position := 0;
- end;}
- function mad_read(const Buffer: Pointer; const Count: Longword): Longword;
- var
- Res: cint;
- begin
- Res := mad_decoder_read(mad_decoder, Buffer, Count);
- if Res < 0 then
- Result := 0 else
- Result := Res;
- end;
- // oggvorbis
- var
- ogg_file : OggVorbis_File;
- ogg_callbacks : ov_callbacks;
- {procedure ogg_reset;
- begin
- ov_pcm_seek(ogg_file, 0);
- end;}
- function ogg_read(const Buffer: Pointer; const Count: Longword): Longword;
- var
- Res: clong;
- begin
- Res := ov_read_ext(ogg_file, Buffer, Count, false, 2, true);
- if Res < 0 then
- Result := 0 else
- Result := Res;
- end;
- // a52
- var
- a52_decoder : pa52_decoder;
- function a52_read(const Buffer: Pointer; const Count: Longword): Longword;
- var
- Res: cint;
- begin
- Res := a52_decoder_read(a52_decoder, Buffer, Count);
- if Res < 0 then
- Result := 0 else
- Result := Res;
- end;
- // dts
- var
- dts_decoder : pdts_decoder;
- function dts_read(const Buffer: Pointer; const Count: Longword): Longword;
- var
- Res: cint;
- begin
- //WriteLn('enter dts_decoder_read');
- Res := dts_decoder_read(dts_decoder, Buffer, Count);
- //WriteLn('leave dts_decoder_read ', Res);
- if Res < 0 then
- Result := 0 else
- Result := Res;
- end;
- // modplug
- var
- mod_file: PModPlugFile;
- function mod_read(const Buffer: Pointer; const Count: Longword): Longword;
- var
- Res: cint;
- begin
- Res := ModPlug_Read(mod_file, Buffer, Count);
- if Res < 0 then
- Result := 0 else
- Result := Res;
- end;
- // openal
- const
- al_format : array[1..2] of ALenum = (AL_FORMAT_MONO16, AL_FORMAT_STEREO16);
- // Note: if you lower the al_bufcount, then you have to modify the al_polltime also!
- al_bufcount = 4;
- al_polltime = 100;
- var
- al_device : PALCdevice;
- al_context : PALCcontext;
- al_source : ALuint;
- al_buffers : array[0..al_bufcount-1] of ALuint;
- al_bufsize : Longword;
- al_readbuf : Pointer;
- procedure alPlay;
- var
- i: Integer;
- begin
- alSourceStop(al_source);
- alSourceRewind(al_source);
- alSourcei(al_source, AL_BUFFER, 0);
- for i := 0 to al_bufcount - 1 do
- begin
- if codec_read(al_readbuf, al_bufsize) = 0 then
- Break;
- //alBufferData(al_buffers[i], al_format[codec_chan], al_readbuf, al_bufsize, codec_rate);
- alBufferWriteData_LOKI(al_buffers[i], al_format[codec_chan], al_readbuf, al_bufsize, codec_rate, al_format[codec_chan]);
- alSourceQueueBuffers(al_source, 1, @al_buffers[i]);
- end;
- // Under windows, AL_LOOPING = AL_TRUE breaks queueing, no idea why
- alSourcei(al_source, AL_LOOPING, AL_FALSE);
- alSourcePlay(al_source);
- end;
- procedure alStop;
- begin
- alSourceStop(al_source);
- alSourceRewind(al_source);
- alSourcei(al_source, AL_BUFFER, 0);
- end;
- function alProcess: Boolean;
- var
- processed : ALint;
- buffer : ALuint;
- begin
- alGetSourcei(al_source, AL_BUFFERS_PROCESSED, processed);
- while (processed > 0) and (processed <= al_bufcount) do
- begin
- Write('.');
- alSourceUnqueueBuffers(al_source, 1, @buffer);
- if codec_read(al_readbuf, al_bufsize) = 0 then
- begin
- alStop;
- Exit(False);
- end;
- //alBufferData(buffer, al_format[codec_chan], al_readbuf, al_bufsize, codec_rate);
- alBufferWriteData_LOKI(buffer, al_format[codec_chan], al_readbuf, al_bufsize, codec_rate, al_format[codec_chan]);
- alSourceQueueBuffers(al_source, 1, @buffer);
- Dec(processed);
- end;
- Result := True;
- end;
- var
- Filename: String;
- ov: pvorbis_info;
- tmp: pointer;
- begin
- // define codec
- WriteLn('Define codec');
- Writeln(' (1) mp3');
- Writeln(' (2) ogg');
- Writeln(' (3) ac3');
- Writeln(' (4) dts');
- Writeln(' (5) xm,mod,it,s3m');
- Writeln(' (6) mka');
- Write('Enter: '); ReadLn(codec);
- Write('File: '); ReadLn(Filename);
- {codec := 4;
- Filename := 'test.dts';}
- // load file
- source := TFileStream.Create(Filename, fmOpenRead);
- // inittialize codec
- case codec of
- 1: // mad
- begin
- mad_decoder := mad_decoder_init(source, @source_read_func, @source_seek_func, @source_close_func, @source_tell_func);
- codec_read := @mad_read;
- codec_rate := 44100;
- codec_chan := 2;
- codec_bs := 2*codec_chan;
- end;
- 2: // oggvorbis
- begin
- ogg_callbacks.read := @source_read_func_ogg;
- ogg_callbacks.seek := @source_seek_func_ogg;
- ogg_callbacks.close := @source_close_func;
- ogg_callbacks.tell := @source_tell_func;
- if ov_open_callbacks(source, ogg_file, nil, 0, ogg_callbacks) >= 0 then
- begin
- ov := ov_info(ogg_file, -1);
- codec_read := @ogg_read;
- codec_rate := ov^.rate;
- codec_chan := ov^.channels;
- codec_bs := 2*codec_chan;
- end;
- end;
- 3: // a52
- begin
- a52_decoder := a52_decoder_init(0, source, @source_read_func, @source_seek_func, @source_close_func, @source_tell_func);
- codec_read := @a52_read;
- codec_rate := 44100;//48000;
- codec_chan := 2;
- codec_bs := 2*codec_chan;
- end;
- 4: // a52
- begin
- dts_decoder := dts_decoder_init(0, source, @source_read_func, @source_seek_func, @source_close_func, @source_tell_func);
- codec_read := @dts_read;
- codec_rate := 44100;//48000;
- codec_chan := 2;
- codec_bs := 2*codec_chan;
- end;
- 5: // modplug
- begin
- GetMem(tmp, source.Size);
- source.Read(tmp^, source.Size);
- mod_file := ModPlug_Load(tmp, source.Size);
- FreeMem(tmp);
- codec_read := @mod_read;
- codec_rate := 44100;//48000;
- codec_chan := 2;
- codec_bs := 2*codec_chan;
- end;
- end;
- if not Assigned(codec_read) then
- Exit;
- //al_bufsize := 20000 - (20000 mod codec_bs);
- al_bufsize := 20000 - (20000 mod codec_bs);
- WriteLn('Codec Blocksize : ', codec_bs);
- WriteLn('Codec Rate : ', codec_rate);
- WriteLn('Codec Channels : ', codec_chan);
- WriteLn('OpenAL Buffers : ', al_bufcount);
- WriteLn('OpenAL Buffer Size : ', al_bufsize);
- // init openal
- al_device := alcOpenDevice(nil);
- al_context := alcCreateContext(al_device, nil);
- alcMakeContextCurrent(al_context);
- alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED);
- alGenSources(1, @al_source);
- alGenBuffers(al_bufcount, @al_buffers);
- GetMem(al_readbuf, al_bufsize);
- // play
- alPlay;
- while alProcess do
- Sleep(al_polltime);
- // finalize openal
- alDeleteSources(1, @al_source);
- alDeleteBuffers(al_bufcount, @al_buffers);
- alcDestroyContext(al_context);
- alcCloseDevice(al_device);
- FreeMem(al_readbuf);
- // finalize codec
- case codec of
- 1: // mad
- begin
- mad_decoder_free(mad_decoder);
- end;
- 2: // oggvorbis
- begin
- ov_clear(ogg_file);
- end;
- 3: // a52
- begin
- a52_decoder_free(a52_decoder);
- end;
- 4: // dts
- begin
- dts_decoder_free(dts_decoder);
- end;
- 5: // modplug
- begin
- ModPlug_Unload(mod_file);
- end;
- end;
- // close file
- source.Free;
- end.
|