| 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;// madvar  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;// oggvorbisvar  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;// a52var  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;// dtsvar  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;// modplugvar  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;// openalconst  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.
 |