aboutsummaryrefslogtreecommitdiffstats
path: root/Game
diff options
context:
space:
mode:
authortobigun <tobigun@b956fd51-792f-4845-bead-9b4dfca2ff2c>2008-01-11 13:52:44 +0000
committertobigun <tobigun@b956fd51-792f-4845-bead-9b4dfca2ff2c>2008-01-11 13:52:44 +0000
commitff1dc556936cef441e105a19aa9d1d3b9e0cc833 (patch)
tree0e846737508481a211c0615374316b826e18e51f /Game
parent4e4e55b6e62a225d7f70a8aa9342e91881decbc8 (diff)
downloadusdx-ff1dc556936cef441e105a19aa9d1d3b9e0cc833.tar.gz
usdx-ff1dc556936cef441e105a19aa9d1d3b9e0cc833.tar.xz
usdx-ff1dc556936cef441e105a19aa9d1d3b9e0cc833.zip
changed from ffmpeg-free (audio) to ffmpeg-enabled (if turned on in switches.inc) version.
BASS is used by default. git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@786 b956fd51-792f-4845-bead-9b4dfca2ff2c
Diffstat (limited to 'Game')
-rw-r--r--Game/Code/Classes/UAudio_FFMpeg.pas1005
-rw-r--r--Game/Code/Classes/UAudio_bass.pas703
-rw-r--r--Game/Code/Classes/UAudio_portaudio.pas427
-rw-r--r--Game/Code/Classes/UMedia_dummy.pas13
-rw-r--r--Game/Code/Classes/UMusic.pas112
-rw-r--r--Game/Code/Classes/UVideo.pas12
-rw-r--r--Game/Code/Classes/UVisualizer.pas15
-rw-r--r--Game/Code/UltraStar.dpr21
-rw-r--r--Game/Code/switches.inc131
9 files changed, 200 insertions, 2239 deletions
diff --git a/Game/Code/Classes/UAudio_FFMpeg.pas b/Game/Code/Classes/UAudio_FFMpeg.pas
deleted file mode 100644
index fb25b0f9..00000000
--- a/Game/Code/Classes/UAudio_FFMpeg.pas
+++ /dev/null
@@ -1,1005 +0,0 @@
-unit UAudio_FFMpeg;
-
-(*******************************************************************************
-
-This unit is primarily based upon -
- http://www.dranger.com/ffmpeg/ffmpegtutorial_all.html
-
- and tutorial03.c
-
- http://www.inb.uni-luebeck.de/~boehme/using_libavcodec.html
-
-*******************************************************************************)
-
-interface
-
-{$IFDEF FPC}
- {$MODE Delphi}
-{$ENDIF}
-
-{$I switches.inc}
-
-
-uses Classes,
- {$IFDEF win32}
- windows,
- {$ENDIF}
- Messages,
- SysUtils,
- {$IFNDEF FPC}
- Forms,
- {$ENDIF}
- SDL, // Used for Audio output Interface
- avcodec, // FFMpeg Audio file decoding
- avformat,
- avutil,
- ULog,
- UMusic;
-
-implementation
-
-uses
- {$IFDEF LAZARUS}
- lclintf,
- {$ifndef win32}
- libc, // not available in win32
- {$endif}
- {$ENDIF}
- portaudio,
- UIni,
- UMain,
- UThemes;
-
-
-type
- PPacketQueue = ^TPacketQueue;
- TPacketQueue = class
- private
- firstPkt,
- lastPkt : PAVPacketList;
- nbPackets : integer;
- size : integer;
- mutex : PSDL_Mutex;
- cond : PSDL_Cond;
- quit : boolean;
-
- public
- constructor Create();
-
- function Put(pkt : PAVPacket): integer;
- function Get(var pkt: TAVPacket; block: boolean): integer;
- end;
-
-type
- TStreamStatus = (sNotReady, sStopped, sPlaying, sSeeking, sPaused, sOpen);
-
-const
- StreamStatusStr: array[TStreamStatus] of string = ('Not ready', 'Stopped', 'Playing', 'Seeking', 'Paused', 'Open');
-
-type
- PAudioBuffer = ^TAudioBuffer;
- TAudioBuffer = array[0 .. (AVCODEC_MAX_AUDIO_FRAME_SIZE * 3 div 2)-1] of byte;
-
-const
- SDL_AUDIO_BUFFER_SIZE = 1024;
-
-type
- TFFMpegOutputStream = class(TAudioOutputStream)
- private
- parseThread: PSDL_Thread;
- packetQueue: TPacketQueue;
-
- status: TStreamStatus;
-
- // FFMpeg internal data
- pFormatCtx : PAVFormatContext;
- pCodecCtx : PAVCodecContext;
- pCodec : PAVCodec;
- ffmpegStreamID : Integer;
- ffmpegStream : PAVStream;
-
- // static vars for AudioDecodeFrame
- pkt : TAVPacket;
- audio_pkt_data : PChar;
- audio_pkt_size : integer;
-
- // static vars for AudioCallback
- audio_buf_index : cardinal;
- audio_buf_size : cardinal;
- audio_buf : TAudioBuffer;
-
- paStream : PPaStream;
- paFrameSize : integer;
- public
- constructor Create(); overload;
- constructor Create(pFormatCtx: PAVFormatContext;
- pCodecCtx: PAVCodecContext; pCodec: PAVCodec;
- ffmpegStreamID : Integer; ffmpegStream: PAVStream); overload;
-
- procedure Play();
- procedure Pause();
- procedure Stop();
- procedure Close();
-
- function AudioDecodeFrame(buffer : PUInt8; bufSize: integer): integer;
- end;
-
-type
- TAudio_FFMpeg = class( TInterfacedObject, IAudioPlayback )
- private
- MusicStream: TFFMpegOutputStream;
-
- StartSoundStream: TFFMpegOutputStream;
- BackSoundStream: TFFMpegOutputStream;
- SwooshSoundStream: TFFMpegOutputStream;
- ChangeSoundStream: TFFMpegOutputStream;
- OptionSoundStream: TFFMpegOutputStream;
- ClickSoundStream: TFFMpegOutputStream;
- DrumSoundStream: TFFMpegOutputStream;
- HihatSoundStream: TFFMpegOutputStream;
- ClapSoundStream: TFFMpegOutputStream;
- ShuffleSoundStream: TFFMpegOutputStream;
-
- //Custom Sounds
- CustomSounds: array of TCustomSoundEntry;
- Loaded: boolean;
- Loop: boolean;
-
- function FindAudioStreamID(pFormatCtx : PAVFormatContext): integer;
- public
- function GetName: String;
- procedure InitializePlayback;
- procedure SetVolume(Volume: integer);
- procedure SetMusicVolume(Volume: integer);
- procedure SetLoop(Enabled: boolean);
- function Open(Name: string): boolean; // true if succeed
- procedure Rewind;
- procedure MoveTo(Time: real);
- procedure Play;
- procedure Pause; //Pause Mod
- procedure Stop;
- procedure Close;
- function Finished: boolean;
- function Length: real;
- function getPosition: real;
- procedure PlayStart;
- procedure PlayBack;
- procedure PlaySwoosh;
- procedure PlayChange;
- procedure PlayOption;
- procedure PlayClick;
- procedure PlayDrum;
- procedure PlayHihat;
- procedure PlayClap;
- procedure PlayShuffle;
- procedure StopShuffle;
-
- function LoadSoundFromFile(Name: string): TFFMpegOutputStream;
-
- //Equalizer
- function GetFFTData: TFFTData;
-
- // Interface for Visualizer
- function GetPCMData(var data: TPCMData): Cardinal;
-
- //Custom Sounds
- function LoadCustomSound(const Filename: String): Cardinal;
- procedure PlayCustomSound(const Index: Cardinal );
- end;
-
-var
- test: TFFMpegOutputStream;
- it: integer;
-
-var
- singleton_MusicFFMpeg : IAudioPlayback = nil;
-
-
-function ParseAudio(data: Pointer): integer; cdecl; forward;
-procedure SDL_AudioCallback( userdata: Pointer; stream: PUInt8; len: Integer ); cdecl; forward;
-function Pa_AudioCallback(input: Pointer; output: Pointer; frameCount: Longword;
- timeInfo: PPaStreamCallbackTimeInfo; statusFlags: TPaStreamCallbackFlags;
- userData: Pointer): Integer; cdecl; forward;
-
-constructor TFFMpegOutputStream.Create();
-begin
- inherited;
-
- packetQueue := TPacketQueue.Create();
-
- FillChar(pkt, sizeof(TAVPacket), #0);
-
- status := sStopped;
-
- audio_pkt_data := nil;
- audio_pkt_size := 0;
-
- audio_buf_index := 0;
- audio_buf_size := 0;
-end;
-
-constructor TFFMpegOutputStream.Create(pFormatCtx: PAVFormatContext;
- pCodecCtx: PAVCodecContext; pCodec: PAVCodec;
- ffmpegStreamID : Integer; ffmpegStream: PAVStream);
-begin
- Create();
-
- Self.pFormatCtx := pFormatCtx;
- Self.pCodecCtx := pCodecCtx;
- Self.pCodec := pCodec;
- Self.ffmpegStreamID := ffmpegStreamID;
- Self.ffmpegStream := ffmpegStream;
-
- test := Self;
- it:=0;
-end;
-
-procedure TFFMpegOutputStream.Play();
-var
- err: TPaError;
-begin
- writeln('Play request');
- if(status = sStopped) then
- begin
- writeln('Play ok');
- status := sPlaying;
- Self.parseThread := SDL_CreateThread(@ParseAudio, Self);
- //SDL_PauseAudio(0);
-
- err := Pa_StartStream(Self.paStream);
- if(err <> paNoError) then
- begin
- Writeln('Play: '+ Pa_GetErrorText(err));
- end;
- end;
-end;
-
-procedure TFFMpegOutputStream.Pause();
-begin
-end;
-
-procedure TFFMpegOutputStream.Stop();
-begin
-end;
-
-procedure TFFMpegOutputStream.Close();
-begin
- // Close the codec
- avcodec_close(pCodecCtx);
-
- // Close the video file
- av_close_input_file(pFormatCtx);
-end;
-
-
-function TAudio_FFMpeg.GetName: String;
-begin
- result := 'FFMpeg';
-end;
-
-procedure TAudio_FFMpeg.InitializePlayback;
-begin
- Log.LogStatus('InitializePlayback', 'UAudio_FFMpeg');
-
- Loaded := false;
- Loop := false;
-
- av_register_all();
- //SDL_Init(SDL_INIT_AUDIO);
- Pa_Initialize();
-
- StartSoundStream := LoadSoundFromFile(SoundPath + 'Common start.mp3');
- BackSoundStream := LoadSoundFromFile(SoundPath + 'Common back.mp3');
- SwooshSoundStream := LoadSoundFromFile(SoundPath + 'menu swoosh.mp3');
- ChangeSoundStream := LoadSoundFromFile(SoundPath + 'select music change music 50.mp3');
- OptionSoundStream := LoadSoundFromFile(SoundPath + 'option change col.mp3');
- ClickSoundStream := LoadSoundFromFile(SoundPath + 'rimshot022b.mp3');
-
-// DrumSoundStream := LoadSoundFromFile(SoundPath + 'bassdrumhard076b.mp3');
-// HihatSoundStream := LoadSoundFromFile(SoundPath + 'hihatclosed068b.mp3');
-// ClapSoundStream := LoadSoundFromFile(SoundPath + 'claps050b.mp3');
-
-// ShuffleSoundStream := LoadSoundFromFile(SoundPath + 'Shuffle.mp3');
-end;
-
-
-procedure TAudio_FFMpeg.SetVolume(Volume: integer);
-begin
- //New: Sets Volume only for this Application
-(*
- BASS_SetConfig(BASS_CONFIG_GVOL_SAMPLE, Volume);
- BASS_SetConfig(BASS_CONFIG_GVOL_STREAM, Volume);
- BASS_SetConfig(BASS_CONFIG_GVOL_MUSIC, Volume);
-*)
-end;
-
-procedure TAudio_FFMpeg.SetMusicVolume(Volume: Integer);
-begin
- //Max Volume Prevention
- if Volume > 100 then
- Volume := 100;
-
- if Volume < 0 then
- Volume := 0;
-
-
- //Set Volume
-// BASS_ChannelSetAttributes (Bass, -1, Volume, -101);
-end;
-
-procedure TAudio_FFMpeg.SetLoop(Enabled: boolean);
-begin
- Loop := Enabled;
-end;
-
-function TAudio_FFMpeg.Open(Name: string): boolean;
-begin
- Loaded := false;
- if FileExists(Name) then
- begin
-// Bass := Bass_StreamCreateFile(false, pchar(Name), 0, 0, 0);
-
- Loaded := true;
- //Set Max Volume
- SetMusicVolume (100);
- end;
-
- Result := Loaded;
-end;
-
-procedure TAudio_FFMpeg.Rewind;
-begin
- if Loaded then
- begin
- end;
-end;
-
-procedure TAudio_FFMpeg.MoveTo(Time: real);
-var
- bytes: integer;
-begin
-// bytes := BASS_ChannelSeconds2Bytes(Bass, Time);
-// BASS_ChannelSetPosition(Bass, bytes);
-end;
-
-procedure TAudio_FFMpeg.Play;
-begin
- if MusicStream <> nil then
- if Loaded then
- begin
- if Loop then
- begin
- end;
- // start from beginning...
- // actually bass itself does not loop, nor does this TAudio_FFMpeg Class
- MusicStream.Play();
- end;
-end;
-
-procedure TAudio_FFMpeg.Pause; //Pause Mod
-begin
- if MusicStream <> nil then
- if Loaded then begin
- MusicStream.Pause(); // Pauses Song
- end;
-end;
-
-procedure TAudio_FFMpeg.Stop;
-begin
- if MusicStream <> nil then
- MusicStream.Stop();
-end;
-
-procedure TAudio_FFMpeg.Close;
-begin
- if MusicStream <> nil then
- MusicStream.Close();
-end;
-
-function TAudio_FFMpeg.Length: real;
-var
- bytes: integer;
-begin
- Result := 0;
- // Todo : why is Music stream always nil !?
-
- if assigned( MusicStream ) then
- begin
- Result := MusicStream.pFormatCtx^.duration / AV_TIME_BASE;
- end;
-end;
-
-function TAudio_FFMpeg.getPosition: real;
-var
- bytes: integer;
-begin
- Result := 0;
-
-(*
- bytes := BASS_ChannelGetPosition(BASS);
- Result := BASS_ChannelBytes2Seconds(BASS, bytes);
-*)
-end;
-
-function TAudio_FFMpeg.Finished: boolean;
-begin
- Result := false;
-
-(*
- if BASS_ChannelIsActive(BASS) = BASS_ACTIVE_STOPPED then
- begin
- Result := true;
- end;
-*)
-end;
-
-procedure TAudio_FFMpeg.PlayStart;
-begin
- if StartSoundStream <> nil then
- StartSoundStream.Play();
-end;
-
-procedure TAudio_FFMpeg.PlayBack;
-begin
- if BackSoundStream <> nil then
- BackSoundStream.Play();
-end;
-
-procedure TAudio_FFMpeg.PlaySwoosh;
-begin
- if SwooshSoundStream <> nil then
- SwooshSoundStream.Play();
-end;
-
-procedure TAudio_FFMpeg.PlayChange;
-begin
- if ChangeSoundStream <> nil then
- ChangeSoundStream.Play();
-end;
-
-procedure TAudio_FFMpeg.PlayOption;
-begin
- if OptionSoundStream <> nil then
- OptionSoundStream.Play();
-end;
-
-procedure TAudio_FFMpeg.PlayClick;
-begin
- if ClickSoundStream <> nil then
- ClickSoundStream.Play();
-end;
-
-procedure TAudio_FFMpeg.PlayDrum;
-begin
- if DrumSoundStream <> nil then
- DrumSoundStream.Play();
-end;
-
-procedure TAudio_FFMpeg.PlayHihat;
-begin
- if HihatSoundStream <> nil then
- HihatSoundStream.Play();
-end;
-
-procedure TAudio_FFMpeg.PlayClap;
-begin
- if ClapSoundStream <> nil then
- ClapSoundStream.Play();
-end;
-
-procedure TAudio_FFMpeg.PlayShuffle;
-begin
- if ShuffleSoundStream <> nil then
- ShuffleSoundStream.Play();
-end;
-
-procedure TAudio_FFMpeg.StopShuffle;
-begin
- if ShuffleSoundStream <> nil then
- ShuffleSoundStream.Stop();
-end;
-
-
-function TFFMpegOutputStream.AudioDecodeFrame(buffer : PUInt8; bufSize: integer): integer;
-var
- len1,
- data_size: integer;
-begin
- result := -1;
-
- if (buffer = nil) then
- exit;
-
- while true do
- begin
- while (audio_pkt_size > 0) do
- begin
-// writeln( 'got audio packet' );
- data_size := bufSize;
-
- if(pCodecCtx = nil) then begin
-// writeln('Das wars');
- exit;
- end;
-
- // TODO: should be avcodec_decode_audio2 but this wont link on my ubuntu box.
- len1 := avcodec_decode_audio(pCodecCtx, Pointer(buffer),
- data_size, audio_pkt_data, audio_pkt_size);
-
- //writeln('avcodec_decode_audio : ' + inttostr( len1 ));
-
- if(len1 < 0) then
- begin
- // if error, skip frame
-// writeln( 'Skip audio frame' );
- audio_pkt_size := 0;
- break;
- end;
-
- Inc(audio_pkt_data, len1);
- Dec(audio_pkt_size, len1);
-
- if (data_size <= 0) then
- begin
- // No data yet, get more frames
- continue;
- end;
-
- // We have data, return it and come back for more later
- result := data_size;
- exit;
- end;
-
- inc(it);
- if (pkt.data <> nil) then
- begin
- av_free_packet(pkt);
- end;
-
- if (packetQueue.quit) then
- begin
- result := -1;
- exit;
- end;
-// writeln(it);
- if (packetQueue.Get(pkt, true) < 0) then
- begin
- result := -1;
- exit;
- end;
-
- audio_pkt_data := PChar(pkt.data);
- audio_pkt_size := pkt.size;
-// writeln( 'Audio Packet Size - ' + inttostr(audio_pkt_size) );
- end;
-end;
-
-procedure SDL_AudioCallback(userdata: Pointer; stream: PUInt8; len: Integer); cdecl;
-var
- outStream : TFFMpegOutputStream;
- len1,
- audio_size : integer;
- pSrc : Pointer;
-begin
- outStream := TFFMpegOutputStream(userdata);
-
- while (len > 0) do
- with outStream do begin
- if (audio_buf_index >= audio_buf_size) then
- begin
- // We have already sent all our data; get more
- audio_size := AudioDecodeFrame(@audio_buf, sizeof(TAudioBuffer));
- //writeln('audio_decode_frame : '+ inttostr(audio_size));
-
- if(audio_size < 0) then
- begin
- // If error, output silence
- audio_buf_size := 1024;
- FillChar(audio_buf, audio_buf_size, #0);
- //writeln( 'Silence' );
- end
- else
- begin
- audio_buf_size := audio_size;
- end;
- audio_buf_index := 0;
- end;
-
- len1 := audio_buf_size - audio_buf_index;
- if (len1 > len) then
- len1 := len;
-
- pSrc := PChar(@audio_buf) + audio_buf_index;
- {$ifdef WIN32}
- CopyMemory(stream, pSrc , len1);
- {$else}
- memcpy(stream, pSrc , len1);
- {$endif}
-
- Dec(len, len1);
- Inc(stream, len1);
- Inc(audio_buf_index, len1);
- end;
-end;
-
-function Pa_AudioCallback(input: Pointer; output: Pointer; frameCount: Longword;
- timeInfo: PPaStreamCallbackTimeInfo; statusFlags: TPaStreamCallbackFlags;
- userData: Pointer): Integer; cdecl;
-var
- outStream : TFFMpegOutputStream;
- len1,
- audio_size : integer;
- pSrc : Pointer;
- len : integer;
-begin
- outStream := TFFMpegOutputStream(userData);
- len := frameCount * outStream.paFrameSize;
-
- while (len > 0) do
- with outStream do begin
- if (audio_buf_index >= audio_buf_size) then
- begin
- // We have already sent all our data; get more
- audio_size := AudioDecodeFrame(@audio_buf, sizeof(TAudioBuffer));
- //writeln('audio_decode_frame : '+ inttostr(audio_size));
-
- if(audio_size < 0) then
- begin
- // If error, output silence
- audio_buf_size := 1024;
- FillChar(audio_buf, audio_buf_size, #0);
- //writeln( 'Silence' );
- end
- else
- begin
- audio_buf_size := audio_size;
- end;
- audio_buf_index := 0; // Todo : jb - SegFault ?
- end;
-
- len1 := audio_buf_size - audio_buf_index;
- if (len1 > len) then
- len1 := len;
-
- pSrc := PChar(@audio_buf) + audio_buf_index;
- {$ifdef WIN32}
- CopyMemory(output, pSrc , len1);
- {$else}
- memcpy(output, pSrc , len1);
- {$endif}
-
- Dec(len, len1);
- Inc(PChar(output), len1);
- Inc(audio_buf_index, len1);
- end;
-
- result := paContinue;
-end;
-
-function TAudio_FFMpeg.FindAudioStreamID(pFormatCtx : PAVFormatContext): integer;
-var
- i : integer;
- streamID: integer;
- stream : PAVStream;
-begin
- // Find the first audio stream
- streamID := -1;
-
- for i := 0 to pFormatCtx^.nb_streams-1 do
- begin
- //Log.LogStatus('aFormatCtx.streams[i] : ' + inttostr(i), 'UAudio_FFMpeg');
- stream := pFormatCtx^.streams[i];
-
- if ( stream.codec^.codec_type = CODEC_TYPE_AUDIO ) then
- begin
- Log.LogStatus('Found Audio Stream', 'UAudio_FFMpeg');
- streamID := i;
- break;
- end;
- end;
-
- result := streamID;
-end;
-
-function ParseAudio(data: Pointer): integer; cdecl;
-var
- packet: TAVPacket;
- stream: TFFMpegOutputStream;
-begin
- stream := TFFMpegOutputStream(data);
-
- while (av_read_frame(stream.pFormatCtx, packet) >= 0) do
- begin
- //writeln( 'ffmpeg - av_read_frame' );
-
- if (packet.stream_index = stream.ffmpegStreamID) then
- begin
- //writeln( 'packet_queue_put' );
- stream.packetQueue.put(@packet);
- end
- else
- begin
- av_free_packet(packet);
- end;
- end;
-
- //Writeln('Done: ' + inttostr(stream.packetQueue.nbPackets));
-
- result := 0;
-end;
-
-
-function TAudio_FFMpeg.LoadSoundFromFile(Name: string): TFFMpegOutputStream;
-var
- pFormatCtx : PAVFormatContext;
- pCodecCtx : PAVCodecContext;
- pCodec : PAVCodec;
- ffmpegStreamID : Integer;
- ffmpegStream : PAVStream;
- wanted_spec,
- spec : TSDL_AudioSpec;
- csIndex : integer;
- stream : TFFMpegOutputStream;
- err : TPaError;
- // move this to a portaudio specific section
- paOutParams : TPaStreamParameters;
- paApiInfo : PPaHostApiInfo;
- paApi : TPaHostApiIndex;
- paOutDevice : TPaDeviceIndex;
- paOutDeviceInfo : PPaDeviceInfo;
-begin
- result := nil;
-
- if (not FileExists(Name)) then
- begin
- Log.LogStatus('LoadSoundFromFile: Sound not found "' + Name + '"', 'UAudio_FFMpeg');
- writeln('ERROR : LoadSoundFromFile: Sound not found "' + Name + '"', 'UAudio_FFMpeg');
- exit;
- end;
-
- // Open audio file
- if (av_open_input_file(pFormatCtx, PChar(Name), nil, 0, nil) > 0) then
- exit;
-
- // Retrieve stream information
- if (av_find_stream_info(pFormatCtx) < 0) then
- exit;
-
- dump_format(pFormatCtx, 0, pchar(Name), 0);
-
- ffmpegStreamID := FindAudioStreamID(pFormatCtx);
- if (ffmpegStreamID < 0) then
- exit;
-
- //Log.LogStatus('Audio Stream ID is : '+ inttostr(ffmpegStreamID), 'UAudio_FFMpeg');
-
- ffmpegStream := pFormatCtx.streams[ffmpegStreamID];
- pCodecCtx := ffmpegStream^.codec;
-
- pCodec := avcodec_find_decoder(pCodecCtx^.codec_id);
- if (pCodec = nil) then
- begin
- Log.LogStatus('Unsupported codec!', 'UAudio_FFMpeg');
- exit;
- end;
-
- avcodec_open(pCodecCtx, pCodec);
- //writeln( 'Opened the codec' );
-
- stream := TFFMpegOutputStream.Create(pFormatCtx, pCodecCtx, pCodec,
- ffmpegStreamID, ffmpegStream);
-
- {
- // Set SDL audio settings from codec info
- wanted_spec.freq := pCodecCtx^.sample_rate;
- wanted_spec.format := AUDIO_S16SYS;
- wanted_spec.channels := pCodecCtx^.channels;
- wanted_spec.silence := 0;
- wanted_spec.samples := SDL_AUDIO_BUFFER_SIZE;
- wanted_spec.callback := AudioCallback;
- wanted_spec.userdata := stream;
-
- // TODO: this works only one time (?)
- if (SDL_OpenAudio(@wanted_spec, @spec) < 0) then
- begin
- Log.LogStatus('SDL_OpenAudio: '+SDL_GetError(), 'UAudio_FFMpeg');
- stream.Free();
- exit;
- end;
- }
-
- paApi := Pa_HostApiTypeIdToHostApiIndex(paALSA);
- paApiInfo := Pa_GetHostApiInfo(paApi);
- paOutDevice := paApiInfo^.defaultOutputDevice;
- paOutDeviceInfo := Pa_GetDeviceInfo(paOutDevice);
-
- with paOutParams do begin
- device := paOutDevice;
- channelCount := pCodecCtx^.channels;
- sampleFormat := paInt16;
- suggestedLatency := paOutDeviceInfo^.defaultHighOutputLatency;
- hostApiSpecificStreamInfo := nil;
- end;
-
- stream.paFrameSize := sizeof(Smallint) * pCodecCtx^.channels;
-
- err := Pa_OpenStream(stream.paStream, nil, @paOutParams, pCodecCtx^.sample_rate,
- paFramesPerBufferUnspecified, //SDL_AUDIO_BUFFER_SIZE div stream.paFrameSize
- paNoFlag, @PA_AudioCallback, stream);
- if(err <> paNoError) then begin
- Log.LogStatus('Pa_OpenDefaultStream: '+Pa_GetErrorText(err), 'UAudio_FFMpeg');
- stream.Free();
- exit;
- end;
-
- Log.LogStatus('Opened audio device', 'UAudio_FFMpeg');
-
- //Add CustomSound
- csIndex := High(CustomSounds) + 1;
- SetLength (CustomSounds, csIndex + 1);
- CustomSounds[csIndex].Filename := Name;
- CustomSounds[csIndex].Stream := stream;
-
- result := stream;
-end;
-
-//Equalizer
-function TAudio_FFMpeg.GetFFTData: TFFTData;
-var
- data: TFFTData;
-begin
- //Get Channel Data Mono and 256 Values
-// BASS_ChannelGetData(Bass, @Result, BASS_DATA_FFT512);
- result := data;
-end;
-
-// Interface for Visualizer
-function TAudio_FFMpeg.GetPCMData(var data: TPCMData): Cardinal;
-begin
- result := 0;
-end;
-
-function TAudio_FFMpeg.LoadCustomSound(const Filename: String): Cardinal;
-var
- S: TFFMpegOutputStream;
- I: Integer;
- F: String;
-begin
- //Search for Sound in already loaded Sounds
- F := UpperCase(SoundPath + FileName);
- For I := 0 to High(CustomSounds) do
- begin
- if (UpperCase(CustomSounds[I].Filename) = F) then
- begin
- Result := I;
- Exit;
- end;
- end;
-
- S := LoadSoundFromFile(SoundPath + Filename);
- if (S <> nil) then
- Result := High(CustomSounds)
- else
- Result := 0;
-end;
-
-procedure TAudio_FFMpeg.PlayCustomSound(const Index: Cardinal );
-begin
- if Index <= High(CustomSounds) then
- (CustomSounds[Index].Stream as TFFMpegOutputStream).Play();
-end;
-
-
-constructor TPacketQueue.Create();
-begin
- inherited;
-
- firstPkt := nil;
- lastPkt := nil;
- nbPackets := 0;
- size := 0;
-
- mutex := SDL_CreateMutex();
- cond := SDL_CreateCond();
-end;
-
-function TPacketQueue.Put(pkt : PAVPacket): integer;
-var
- pkt1 : PAVPacketList;
-begin
- result := -1;
-
- if (av_dup_packet(pkt) < 0) then
- exit;
-
- pkt1 := av_malloc(sizeof(TAVPacketList));
- if (pkt1 = nil) then
- exit;
-
- pkt1^.pkt := pkt^;
- pkt1^.next := nil;
-
-
- SDL_LockMutex(Self.mutex);
- try
-
- if (Self.lastPkt = nil) then
- Self.firstPkt := pkt1
- else
- Self.lastPkt^.next := pkt1;
-
- Self.lastPkt := pkt1;
- inc(Self.nbPackets);
-
-// Writeln('Put: ' + inttostr(nbPackets));
-
- Self.size := Self.size + pkt1^.pkt.size;
- SDL_CondSignal(Self.cond);
-
- finally
- SDL_UnlockMutex(Self.mutex);
- end;
-
- result := 0;
-end;
-
-function TPacketQueue.Get(var pkt: TAVPacket; block: boolean): integer;
-var
- pkt1 : PAVPacketList;
-begin
- result := -1;
-
- SDL_LockMutex(Self.mutex);
- try
- while true do
- begin
- if (quit) then
- exit;
-
- pkt1 := Self.firstPkt;
-
- if (pkt1 <> nil) then
- begin
- Self.firstPkt := pkt1.next;
- if (Self.firstPkt = nil) then
- Self.lastPkt := nil;
- dec(Self.nbPackets);
-
-// Writeln('Get: ' + inttostr(nbPackets));
-
- Self.size := Self.size - pkt1^.pkt.size;
- pkt := pkt1^.pkt;
- av_free(pkt1);
-
- result := 1;
- break;
- end
- else
- if (not block) then
- begin
- result := 0;
- break;
- end
- else
- begin
- SDL_CondWait(Self.cond, Self.mutex);
- end;
- end;
- finally
- SDL_UnlockMutex(Self.mutex);
- end;
-end;
-
-
-
-initialization
- singleton_MusicFFMpeg := TAudio_FFMpeg.create();
-
- writeln( 'UAudio_FFMpeg - Register Playback' );
- AudioManager.add( IAudioPlayback( singleton_MusicFFMpeg ) );
-
-finalization
- AudioManager.Remove( IAudioPlayback( singleton_MusicFFMpeg ) );
-
-
-end.
diff --git a/Game/Code/Classes/UAudio_bass.pas b/Game/Code/Classes/UAudio_bass.pas
deleted file mode 100644
index 972d6df0..00000000
--- a/Game/Code/Classes/UAudio_bass.pas
+++ /dev/null
@@ -1,703 +0,0 @@
-unit UAudio_bass;
-
-interface
-
-{$IFDEF FPC}
- {$MODE Delphi}
-{$ENDIF}
-
-{$I switches.inc}
-
-
-uses Classes,
- {$IFDEF win32}
- windows,
- {$ENDIF}
- Messages,
- SysUtils,
- {$IFNDEF FPC}
- Forms,
- {$ENDIF}
- bass,
- ULog,
- UMusic;
-
-implementation
-
-uses
- {$IFDEF LAZARUS}
- lclintf,
- {$ENDIF}
- URecord,
- UIni,
- UMain,
- UCommon,
- UThemes;
-
-type
- TMPModes = (mpNotReady, mpStopped, mpPlaying, mpRecording, mpSeeking,
- mpPaused, mpOpen);
-
-const
- ModeStr: array[TMPModes] of string = ('Not ready', 'Stopped', 'Playing', 'Recording', 'Seeking', 'Paused', 'Open');
-
-type
- TBassOutputStream = class(TAudioOutputStream)
- Handle: HSTREAM;
-
- constructor Create(); overload;
- constructor Create(stream: HSTREAM); overload;
- end;
-
-type
-{$IFDEF UseBASSInput}
- TAudio_bass = class( TInterfacedObject, IAudioPlayback, IAudioInput)
-{$ELSE}
- TAudio_bass = class( TInterfacedObject, IAudioPlayback)
-{$ENDIF}
- private
- MusicStream: HSTREAM;
-
- StartSoundStream: HSTREAM;
- BackSoundStream: HSTREAM;
- SwooshSoundStream: HSTREAM;
- ChangeSoundStream: HSTREAM;
- OptionSoundStream: HSTREAM;
- ClickSoundStream: HSTREAM;
- DrumSoundStream: HSTREAM;
- HihatSoundStream: HSTREAM;
- ClapSoundStream: HSTREAM;
- ShuffleSoundStream: HSTREAM;
-
- //Custom Sounds
- CustomSounds: array of TCustomSoundEntry;
- Loaded: boolean;
- Loop: boolean;
-
- public
- function GetName: String;
-
- {IAudioOutput interface}
-
- procedure InitializePlayback;
- procedure SetVolume(Volume: integer);
- procedure SetMusicVolume(Volume: integer);
- procedure SetLoop(Enabled: boolean);
- function Open(Name: string): boolean; // true if succeed
- procedure Rewind;
- procedure MoveTo(Time: real);
- procedure Play;
- procedure Pause; //Pause Mod
- procedure Stop;
- procedure Close;
- function Finished: boolean;
- function Length: real;
- function getPosition: real;
- procedure PlayStart;
- procedure PlayBack;
- procedure PlaySwoosh;
- procedure PlayChange;
- procedure PlayOption;
- procedure PlayClick;
- procedure PlayDrum;
- procedure PlayHihat;
- procedure PlayClap;
- procedure PlayShuffle;
- procedure StopShuffle;
-
- function LoadSoundFromFile(var stream: HSTREAM; Name: string): boolean;
-
- //Equalizer
- function GetFFTData: TFFTData;
-
- // Interface for Visualizer
- function GetPCMData(var data: TPCMData): Cardinal;
-
- //Custom Sounds
- function LoadCustomSound(const Filename: String): Cardinal;
- procedure PlayCustomSound(const Index: Cardinal );
-
- {IAudioInput interface}
- {$IFDEF UseBASSInput}
- procedure InitializeRecord;
-
- procedure CaptureStart;
- procedure CaptureStop;
- procedure CaptureCard(Card: byte; CaptureSoundLeft, CaptureSoundRight: TSound);
- procedure StopCard(Card: byte);
- {$ENDIF}
- end;
-
-{$IFDEF UseBASSInput}
- TBassSoundCard = class(TGenericSoundCard)
- RecordStream: HSTREAM;
- end;
-{$ENDIF}
-
-
-var
- singleton_MusicBass : IAudioPlayback;
-
-
-constructor TBassOutputStream.Create();
-begin
- inherited;
-end;
-
-constructor TBassOutputStream.Create(stream: HSTREAM);
-begin
- Create();
- Handle := stream;
-end;
-
-
-function TAudio_bass.GetName: String;
-begin
- result := 'BASS';
-end;
-
-procedure TAudio_bass.InitializePlayback;
-var
- Pet: integer;
- S: integer;
-begin
-// Log.BenchmarkStart(4);
-// Log.LogStatus('Initializing Playback Subsystem', 'Music Initialize');
-
- Loaded := false;
- Loop := false;
-
- if not BASS_Init(1, 44100, 0, 0, nil) then
- begin
- Log.LogError('Could not initialize BASS', 'Error');
- Exit;
- end;
-
-// Log.BenchmarkEnd(4); Log.LogBenchmark('--> Bass Init', 4);
-
- // config playing buffer
-// BASS_SetConfig(BASS_CONFIG_UPDATEPERIOD, 10);
-// BASS_SetConfig(BASS_CONFIG_BUFFER, 100);
-
-// Log.LogStatus('Loading Sounds', 'Music Initialize');
-
-// Log.BenchmarkStart(4);
- LoadSoundFromFile(StartSoundStream, SoundPath + 'Common Start.mp3');
- LoadSoundFromFile(BackSoundStream, SoundPath + 'Common Back.mp3');
- LoadSoundFromFile(SwooshSoundStream, SoundPath + 'menu swoosh.mp3');
- LoadSoundFromFile(ChangeSoundStream, SoundPath + 'select music change music 50.mp3');
- LoadSoundFromFile(OptionSoundStream, SoundPath + 'option change col.mp3');
- LoadSoundFromFile(ClickSoundStream, SoundPath + 'rimshot022b.mp3');
-
-// LoadSoundFromFile(DrumSoundStream, SoundPath + 'bassdrumhard076b.mp3');
-// LoadSoundFromFile(HihatSoundStream, SoundPath + 'hihatclosed068b.mp3');
-// LoadSoundFromFile(ClapSoundStream, SoundPath + 'claps050b.mp3');
-
-// LoadSoundFromFile(ShuffleSoundStream, SoundPath + 'Shuffle.mp3');
-
-// Log.BenchmarkEnd(4);
-// Log.LogBenchmark('--> Loading Sounds', 4);
-end;
-
-procedure TAudio_bass.SetVolume(Volume: integer);
-begin
- //Old Sets Wave Volume
- //BASS_SetVolume(Volume);
- //New: Sets Volume only for this Application
-
- BASS_SetConfig(BASS_CONFIG_GVOL_SAMPLE, Volume);
- BASS_SetConfig(BASS_CONFIG_GVOL_STREAM, Volume);
- BASS_SetConfig(BASS_CONFIG_GVOL_MUSIC, Volume);
-end;
-
-procedure TAudio_bass.SetMusicVolume(Volume: Integer);
-begin
- //Max Volume Prevention
- if Volume > 100 then
- Volume := 100;
-
- if Volume < 0 then
- Volume := 0;
-
- //Set Volume
- BASS_ChannelSetAttributes (MusicStream, -1, Volume, -101);
-end;
-
-procedure TAudio_bass.SetLoop(Enabled: boolean);
-begin
- Loop := Enabled;
-end;
-
-function TAudio_bass.Open(Name: string): boolean;
-begin
- Loaded := false;
- if FileExists(Name) then
- begin
- MusicStream := Bass_StreamCreateFile(false, pchar(Name), 0, 0, 0);
-
- Loaded := true;
- //Set Max Volume
- SetMusicVolume (100);
- end;
-
- Result := Loaded;
-end;
-
-procedure TAudio_bass.Rewind;
-begin
- if Loaded then begin
- end;
-end;
-
-procedure TAudio_bass.MoveTo(Time: real);
-var
- bytes: integer;
-begin
- bytes := BASS_ChannelSeconds2Bytes(MusicStream, Time);
- BASS_ChannelSetPosition(MusicStream, bytes);
-end;
-
-procedure TAudio_bass.Play;
-begin
- if Loaded then
- begin
- if Loop then
- BASS_ChannelPlay(MusicStream, True); // start from beginning... actually bass itself does not loop, nor does this TAudio_bass Class
-
- BASS_ChannelPlay(MusicStream, False); // for setting position before playing
- end;
-end;
-
-procedure TAudio_bass.Pause; //Pause Mod
-begin
- if Loaded then begin
- BASS_ChannelPause(MusicStream); // Pauses Song
- end;
-end;
-
-procedure TAudio_bass.Stop;
-begin
- Bass_ChannelStop(MusicStream);
-end;
-
-procedure TAudio_bass.Close;
-begin
- Bass_StreamFree(MusicStream);
-end;
-
-function TAudio_bass.Length: real;
-var
- bytes: integer;
-begin
- Result := 60;
-
- bytes := BASS_ChannelGetLength(MusicStream);
- Result := BASS_ChannelBytes2Seconds(MusicStream, bytes);
-end;
-
-function TAudio_bass.getPosition: real;
-var
- bytes: integer;
-begin
- Result := 0;
-
- bytes := BASS_ChannelGetPosition(MusicStream);
- Result := BASS_ChannelBytes2Seconds(MusicStream, bytes);
-end;
-
-function TAudio_bass.Finished: boolean;
-begin
- Result := false;
-
- if BASS_ChannelIsActive(MusicStream) = BASS_ACTIVE_STOPPED then
- begin
- Result := true;
- end;
-end;
-
-procedure TAudio_bass.PlayStart;
-begin
- BASS_ChannelPlay(StartSoundStream, True);
-end;
-
-procedure TAudio_bass.PlayBack;
-begin
- BASS_ChannelPlay(BackSoundStream, True);// then
-end;
-
-procedure TAudio_bass.PlaySwoosh;
-begin
- BASS_ChannelPlay(SwooshSoundStream, True);
-end;
-
-procedure TAudio_bass.PlayChange;
-begin
- BASS_ChannelPlay(ChangeSoundStream, True);
-end;
-
-procedure TAudio_bass.PlayOption;
-begin
- BASS_ChannelPlay(OptionSoundStream, True);
-end;
-
-procedure TAudio_bass.PlayClick;
-begin
- BASS_ChannelPlay(ClickSoundStream, True);
-end;
-
-procedure TAudio_bass.PlayDrum;
-begin
- BASS_ChannelPlay(DrumSoundStream, True);
-end;
-
-procedure TAudio_bass.PlayHihat;
-begin
- BASS_ChannelPlay(HihatSoundStream, True);
-end;
-
-procedure TAudio_bass.PlayClap;
-begin
- BASS_ChannelPlay(ClapSoundStream, True);
-end;
-
-procedure TAudio_bass.PlayShuffle;
-begin
- BASS_ChannelPlay(ShuffleSoundStream, True);
-end;
-
-procedure TAudio_bass.StopShuffle;
-begin
- BASS_ChannelStop(ShuffleSoundStream);
-end;
-
-function TAudio_bass.LoadSoundFromFile(var stream: HSTREAM; Name: string): boolean;
-var
- L: Integer;
-begin
- if FileExists(Name) then
- begin
- Log.LogStatus('Loading Sound: "' + Name + '"', 'LoadSoundFromFile');
- try
- stream := BASS_StreamCreateFile(False, pchar(Name), 0, 0, 0);
-
- //Add CustomSound
- L := High(CustomSounds) + 1;
- SetLength (CustomSounds, L + 1);
- CustomSounds[L].Filename := Name;
- CustomSounds[L].Stream := TBassOutputStream.Create(stream);
- except
- Log.LogError('Failed to open using BASS', 'LoadSoundFromFile');
- end;
- end
- else
- begin
- Log.LogError('Sound not found: "' + Name + '"', 'LoadSoundFromFile');
- exit;
- end;
-end;
-
-//Equalizer
-function TAudio_bass.GetFFTData: TFFTData;
-var
- Data: TFFTData;
-begin
- //Get Channel Data Mono and 256 Values
- BASS_ChannelGetData(MusicStream, @Result, BASS_DATA_FFT512);
-end;
-
-{*
- * Copies interleaved PCM 16bit uint (maybe fake) stereo samples into data.
- * Returns the number of frames (= stereo/mono sample)
- *}
-function TAudio_bass.GetPCMData(var data: TPCMData): Cardinal;
-var
- info: BASS_CHANNELINFO;
- nBytes: DWORD;
-begin
- //Get Channel Data Mono and 256 Values
- BASS_ChannelGetInfo(MusicStream, info);
- ZeroMemory(@data, sizeof(TPCMData));
-
- if (info.chans = 1) then
- begin
- // mono file -> add stereo channel
- {
- nBytes := BASS_ChannelGetData(Bass, @data[0], samples*sizeof(Smallint));
- // interleave data
- //CopyMemory(@data[1], @data[0], samples*sizeof(Smallint));
- }
- result := 0;
- end
- else
- begin
- // stereo file
- nBytes := BASS_ChannelGetData(MusicStream, @data, sizeof(TPCMData));
- end;
- if(nBytes <= 0) then
- result := 0
- else
- result := nBytes div sizeof(TPCMStereoSample);
-end;
-
-function TAudio_bass.LoadCustomSound(const Filename: String): Cardinal;
-var
- S: hStream;
- I: Integer;
- F: String;
-begin
- //Search for Sound in already loaded Sounds
- F := UpperCase(SoundPath + FileName);
- For I := 0 to High(CustomSounds) do
- begin
- if (UpperCase(CustomSounds[I].Filename) = F) then
- begin
- Result := I;
- Exit;
- end;
- end;
-
- if LoadSoundFromFile(S, SoundPath + Filename) then
- Result := High(CustomSounds)
- else
- Result := 0;
-end;
-
-procedure TAudio_bass.PlayCustomSound(const Index: Cardinal );
-begin
- if Index <= High(CustomSounds) then
- with CustomSounds[Index].Stream as TBassOutputStream do
- begin
- BASS_ChannelPlay(Handle, True);
- end;
-end;
-
-{$IFDEF UseBASSInput}
-
-procedure TAudio_bass.InitializeRecord;
-var
- device: integer;
- Descr: string;
- input: integer;
- input2: integer;
- InputName: PChar;
- Flags: integer;
- mic: array[0..15] of integer;
- SC: integer; // soundcard
- SCI: integer; // soundcard input
- No: integer;
-
-function isDuplicate(Desc: String): Boolean;
-var
- I: Integer;
-begin
- Result := False;
- //Check for Soundcard with same Description
- For I := 0 to SC-1 do
- begin
- if (Recording.SoundCard[I].Description = Desc) then
- begin
- Result := True;
- Break;
- end;
- end;
-end;
-
-begin
- with Recording do
- begin
- // checks for recording devices and puts them into an array
- SetLength(SoundCard, 0);
-
- SC := 0;
- Descr := BASS_RecordGetDeviceDescription(SC);
-
- while (Descr <> '') do
- begin
- //If there is another SoundCard with the Same ID, Search an available Name
- if (IsDuplicate(Descr)) then
- begin
- No:= 1; //Count of SoundCards with same Name
- Repeat
- Inc(No)
- Until not IsDuplicate(Descr + ' (' + InttoStr(No) + ')');
-
- //Set Description
- Descr := Descr + ' (' + InttoStr(No) + ')';
- end;
-
- SetLength(SoundCard, SC+1);
-
- // TODO: free object on termination
- SoundCard[SC] := TBassSoundCard.Create();
- SoundCard[SC].Description := Descr;
-
- //Get Recording Inputs
- SCI := 0;
- BASS_RecordInit(SC);
-
- InputName := BASS_RecordGetInputName(SCI);
-
- {$IFDEF DARWIN}
- // Under MacOSX the SingStar Mics have an empty
- // InputName. So, we have to add a hard coded
- // Workaround for this problem
- if (InputName = nil) and (Pos( 'USBMIC Serial#', Descr) > 0) then
- begin
- InputName := 'Microphone';
- end;
- {$ENDIF}
-
- SetLength(SoundCard[SC].Input, 1);
- SoundCard[SC].Input[SCI].Name := InputName;
-
- // process each input
- while (InputName <> nil) do
- begin
- Flags := BASS_RecordGetInput(SCI);
- if (SCI >= 1) {AND (Flags AND BASS_INPUT_OFF = 0)} then
- begin
- SetLength(SoundCard[SC].Input, SCI+1);
- SoundCard[SC].Input[SCI].Name := InputName;
- end;
-
- //Set Mic Index
- if ((Flags and BASS_INPUT_TYPE_MIC) = 1) then
- SoundCard[SC].MicInput := SCI;
-
- Inc(SCI);
- InputName := BASS_RecordGetInputName(SCI);
- end;
-
- BASS_RecordFree;
-
- Inc(SC);
- Descr := BASS_RecordGetDeviceDescription(SC);
- end; // while
- end; // with Recording
-end;
-
-// TODO: code is used by all IAudioInput implementors
-// -> move to a common superclass (TAudioInput_Generic?)
-procedure TAudio_bass.CaptureStart;
-var
- S: integer;
- SC: integer;
- PlayerLeft, PlayerRight: integer;
- CaptureSoundLeft, CaptureSoundRight: TSound;
-begin
- for S := 0 to High(Recording.Sound) do
- Recording.Sound[S].BufferLong[0].Clear;
-
- for SC := 0 to High(Ini.CardList) do begin
- PlayerLeft := Ini.CardList[SC].ChannelL-1;
- PlayerRight := Ini.CardList[SC].ChannelR-1;
- if PlayerLeft >= PlayersPlay then PlayerLeft := -1;
- if PlayerRight >= PlayersPlay then PlayerRight := -1;
- if (PlayerLeft > -1) or (PlayerRight > -1) then begin
- if (PlayerLeft > -1) then
- CaptureSoundLeft := Recording.Sound[PlayerLeft]
- else
- CaptureSoundLeft := nil;
- if (PlayerRight > -1) then
- CaptureSoundRight := Recording.Sound[PlayerRight]
- else
- CaptureSoundRight := nil;
-
- CaptureCard(SC, CaptureSoundLeft, CaptureSoundRight);
- end;
- end;
-end;
-
-// TODO: code is used by all IAudioInput implementors
-// -> move to a common superclass (TAudioInput_Generic?)
-procedure TAudio_bass.CaptureStop;
-var
- SC: integer;
- PlayerLeft: integer;
- PlayerRight: integer;
-begin
-
- for SC := 0 to High(Ini.CardList) do begin
- PlayerLeft := Ini.CardList[SC].ChannelL-1;
- PlayerRight := Ini.CardList[SC].ChannelR-1;
- if PlayerLeft >= PlayersPlay then PlayerLeft := -1;
- if PlayerRight >= PlayersPlay then PlayerRight := -1;
- if (PlayerLeft > -1) or (PlayerRight > -1) then
- StopCard(SC);
- end;
-
-end;
-
-{*
- * Bass input capture callback.
- * Params:
- * stream - BASS input stream
- * buffer - buffer of captured samples
- * len - size of buffer in bytes
- * user - players associated with left/right channels
- *}
-function MicrophoneCallback(stream: HSTREAM; buffer: Pointer;
- len: Cardinal; Card: Cardinal): boolean; stdcall;
-begin
- Recording.HandleMicrophoneData(buffer, len, Recording.SoundCard[Card]);
- Result := true;
-end;
-
-{*
- * Start input-capturing on Soundcard specified by Card.
- * Params:
- * Card - soundcard index in Recording.SoundCard array
- * CaptureSoundLeft - sound(-buffer) used for left channel capture data
- * CaptureSoundRight - sound(-buffer) used for right channel capture data
- *}
-procedure TAudio_bass.CaptureCard(Card: byte; CaptureSoundLeft, CaptureSoundRight: TSound);
-var
- Error: integer;
- ErrorMsg: string;
- bassSoundCard: TBassSoundCard;
-begin
- if not BASS_RecordInit(Card) then
- begin
- Error := BASS_ErrorGetCode;
- ErrorMsg := IntToStr(Error);
- if Error = BASS_ERROR_DX then ErrorMsg := 'No DX5';
- if Error = BASS_ERROR_ALREADY then ErrorMsg := 'The device has already been initialized';
- if Error = BASS_ERROR_DEVICE then ErrorMsg := 'The device number specified is invalid';
- if Error = BASS_ERROR_DRIVER then ErrorMsg := 'There is no available device driver';
- Log.LogError('Error initializing record [' + IntToStr(Card) + ']');
- Log.LogError('TAudio_bass.CaptureCard: Error initializing record: ' + ErrorMsg);
- end
- else
- begin
- bassSoundCard := TBassSoundCard(Recording.SoundCard[Card]);
- bassSoundCard.CaptureSoundLeft := CaptureSoundLeft;
- bassSoundCard.CaptureSoundRight := CaptureSoundRight;
-
- // capture in 44.1kHz/stereo/16bit and a 20ms callback period
- bassSoundCard.RecordStream :=
- BASS_RecordStart(44100, 2, MakeLong(0, 20) , @MicrophoneCallback, Card);
- end;
-end;
-
-{*
- * Stop input-capturing on Soundcard specified by Card.
- * Params:
- * Card - soundcard index in Recording.SoundCard array
- *}
-procedure TAudio_bass.StopCard(Card: byte);
-begin
- BASS_RecordSetDevice(Card);
- BASS_RecordFree;
-end;
-
-{$ENDIF}
-
-
-initialization
- singleton_MusicBass := TAudio_bass.create();
- AudioManager.add( singleton_MusicBass );
-
-finalization
- AudioManager.Remove( singleton_MusicBass );
-
-end.
diff --git a/Game/Code/Classes/UAudio_portaudio.pas b/Game/Code/Classes/UAudio_portaudio.pas
deleted file mode 100644
index 47e54981..00000000
--- a/Game/Code/Classes/UAudio_portaudio.pas
+++ /dev/null
@@ -1,427 +0,0 @@
-unit UAudio_Portaudio;
-
-interface
-
-{$IFDEF FPC}
- {$MODE Delphi}
-{$ENDIF}
-
-{$I switches.inc}
-
-
-uses Classes,
- {$IFDEF win32}
- windows,
- {$ENDIF}
- Messages,
- SysUtils,
- {$IFNDEF FPC}
- Forms,
- {$ENDIF}
- portaudio,
- {$IFDEF UsePortmixer}
- portmixer,
- {$ENDIF}
- ULog,
- UMusic;
-
-implementation
-
-uses
- {$IFDEF LAZARUS}
- lclintf,
- {$ENDIF}
- URecord,
- UIni,
- UMain,
- UCommon,
- UThemes;
-{
-type
- TPaHostApiIndex = PaHostApiIndex;
- TPaDeviceIndex = PaDeviceIndex;
- PPaStream = ^PaStreamPtr;
- PPaStreamCallbackTimeInfo = ^PaStreamCallbackTimeInfo;
- TPaStreamCallbackFlags = PaStreamCallbackFlags;
- TPaHostApiTypeId = PaHostApiTypeId;
- PPaHostApiInfo = ^PaHostApiInfo;
- PPaDeviceInfo = ^PaDeviceInfo;
- TPaError = PaError;
- TPaStreamParameters = PaStreamParameters;
-}
-type
- TAudio_Portaudio = class( TInterfacedObject, IAudioInput )
- private
- function GetPreferredApiIndex(): TPaHostApiIndex;
- public
- function GetName: String;
- procedure InitializeRecord;
-
- procedure CaptureStart;
- procedure CaptureStop;
-
- procedure CaptureCard(Card: byte; CaptureSoundLeft, CaptureSoundRight: TSound);
- procedure StopCard(Card: byte);
- end;
-
- TPortaudioSoundCard = class(TGenericSoundCard)
- RecordStream: PPaStream;
- DeviceIndex: TPaDeviceIndex;
- end;
-
-function MicrophoneCallback(input: Pointer; output: Pointer; frameCount: Longword;
- timeInfo: PPaStreamCallbackTimeInfo; statusFlags: TPaStreamCallbackFlags;
- inputDevice: Pointer): Integer; cdecl; forward;
-
-var
- singleton_MusicPortaudio : IAudioInput;
-
-const
- sampleRate: Double = 44100.;
-
-{* the default API used by Portaudio is the least common denominator
- * and might lack efficiency. ApiPreferenceOrder defines the order of
- * preferred APIs to use. The first API-type in the list is tried first. If it's
- * not available the next is tried, ...
- * If none of the preferred APIs was found the default API is used.
- * Pascal doesn't permit zero-length static arrays, so you can use paDefaultApi
- * as an array's only member if you do not have any preferences.
- * paDefaultApi also terminates a preferences list but this is optional.
- *}
-const
- paDefaultApi = -1;
-var
- ApiPreferenceOrder:
-{$IF Defined(WIN32)}
- // Note1: Portmixer has no mixer support for paASIO and paWASAPI at the moment
- // Note2: Windows Default-API is MME
- //array[0..0] of TPaHostApiTypeId = ( paDirectSound, paMME );
- array[0..0] of TPaHostApiTypeId = ( paDirectSound );
-{$ELSEIF Defined(LINUX)}
- // Note1: Portmixer has no mixer support for paJACK at the moment
- // Note2: Not tested, but ALSA might be better than OSS.
- array[0..1] of TPaHostApiTypeId = ( paALSA, paOSS );
-{$ELSEIF Defined(DARWIN)}
- // Note: Not tested.
- //array[0..0] of TPaHostApiTypeId = ( paCoreAudio );
- array[0..0] of TPaHostApiTypeId = ( paDefaultApi );
-{$ELSE}
- array[0..0] of TPaHostApiTypeId = ( paDefaultApi );
-{$IFEND}
-
-function TAudio_Portaudio.GetName: String;
-begin
- result := 'Portaudio';
-end;
-
-function TAudio_Portaudio.GetPreferredApiIndex(): TPaHostApiIndex;
-var
- i: integer;
-begin
- result := -1;
-
- // select preferred sound-API
- for i:= 0 to High(ApiPreferenceOrder) do
- begin
- if(ApiPreferenceOrder[i] <> paDefaultApi) then begin
- // check if API is available
- result := Pa_HostApiTypeIdToHostApiIndex(ApiPreferenceOrder[i]);
- if(result >= 0) then
- break;
- end;
- end;
-
- // None of the preferred APIs is available -> use default
- if(result < 0) then begin
- result := Pa_GetDefaultHostApi();
- end;
-end;
-
-// TODO: should be a function with boolean return type
-procedure TAudio_Portaudio.InitializeRecord;
-var
- i: integer;
- apiIndex: TPaHostApiIndex;
- apiInfo: PPaHostApiInfo;
- deviceName: string;
- deviceIndex: TPaDeviceIndex;
- deviceInfo: PPaDeviceInfo;
- inputCnt: integer;
- inputName: string;
- SC: integer; // soundcard
- SCI: integer; // soundcard input
- err: TPaError;
- errMsg: string;
- paSoundCard: TPortaudioSoundCard;
- inputParams: TPaStreamParameters;
- stream: PPaStream;
- {$IFDEF UsePortmixer}
- mixer: PPxMixer;
- {$ENDIF}
-begin
- // TODO: call Pa_Terminate() on termination
- err := Pa_Initialize();
- if(err <> paNoError) then begin
- Log.CriticalError('Portaudio.InitializeRecord: ' + Pa_GetErrorText(err));
- //Log.LogError('Portaudio.InitializeRecord: ' + Pa_GetErrorText(err));
- // result := false;
- Exit;
- end;
-
- apiIndex := GetPreferredApiIndex();
- apiInfo := Pa_GetHostApiInfo(apiIndex);
-
- SC := 0;
-
- // init array-size to max. input-devices count
- SetLength(Recording.SoundCard, apiInfo^.deviceCount); // fix deviceCountL
- for i:= 0 to High(Recording.SoundCard) do
- begin
- // convert API-specific device-index to global index
- deviceIndex := Pa_HostApiDeviceIndexToDeviceIndex(apiIndex, i);
- deviceInfo := Pa_GetDeviceInfo(deviceIndex);
-
- // current device is no input device -> skip
- if(deviceInfo^.maxInputChannels <= 0) then
- continue;
-
- // TODO: free object on termination
- paSoundCard := TPortaudioSoundCard.Create();
- Recording.SoundCard[SC] := paSoundCard;
-
- // retrieve device-name
- deviceName := deviceInfo^.name;
- paSoundCard.Description := deviceName;
- paSoundCard.DeviceIndex := deviceIndex;
-
- // setup desired input parameters
- with inputParams do begin
- device := deviceIndex;
- channelCount := 2;
- sampleFormat := paInt16;
- suggestedLatency := deviceInfo^.defaultLowInputLatency;
- hostApiSpecificStreamInfo := nil;
- end;
-
- // check if device supports our input-format
- err := Pa_IsFormatSupported(@inputParams, nil, sampleRate);
- if(err <> 0) then begin
- // format not supported -> skip
- errMsg := Pa_GetErrorText(err);
- Log.LogError('Portaudio.InitializeRecord, device: "'+ deviceName +'" '
- + '('+ errMsg +')');
- paSoundCard.Free();
- continue;
- end;
-
- // TODO: retry with mono if stereo is not supported
- // TODO: retry with input-latency set to 20ms (defaultLowInputLatency might
- // not be set correctly in OSS)
-
- err := Pa_OpenStream(stream, @inputParams, nil, sampleRate,
- paFramesPerBufferUnspecified, paNoFlag, @MicrophoneCallback, nil);
- if(err <> paNoError) then begin
- // unable to open device -> skip
- errMsg := Pa_GetErrorText(err);
- Log.LogError('Portaudio.InitializeRecord, device: "'+ deviceName +'" '
- + '('+ errMsg +')');
- paSoundCard.Free();
- continue;
- end;
-
-
- {$IFDEF UsePortmixer}
-
- // use default mixer
- mixer := Px_OpenMixer(stream, 0);
-
- // get input count
- inputCnt := Px_GetNumInputSources(mixer);
- SetLength(paSoundCard.Input, inputCnt);
-
- // get input names
- for SCI := 0 to inputCnt-1 do
- begin
- inputName := Px_GetInputSourceName(mixer, SCI);
- paSoundCard.Input[SCI].Name := inputName;
- end;
-
- Px_CloseMixer(mixer);
-
- {$ELSE} // !UsePortmixer
-
- //Pa_StartStream(stream);
- // TODO: check if callback was called (this problem may occur on some devices)
- //Pa_StopStream(stream);
-
- Pa_CloseStream(stream);
-
- // create a standard input source
- SetLength(paSoundCard.Input, 1);
- paSoundCard.Input[0].Name := 'Standard';
-
- {$ENDIF}
-
- // use default input source
- paSoundCard.InputSelected := 0;
-
- Inc(SC);
- end;
-
- // adjust size to actual input-device count
- SetLength(Recording.SoundCard, SC);
-
- Log.LogStatus('#Soundcards: ' + inttostr(SC), 'Portaudio');
-
- {
- SoundCard[SC].InputSelected := Mic[Device];
- }
-end;
-
-// TODO: code is used by all IAudioInput implementors
-// -> move to a common superclass (TAudioInput_Generic?)
-procedure TAudio_Portaudio.CaptureStart;
-var
- S: integer;
- SC: integer;
- PlayerLeft, PlayerRight: integer;
- CaptureSoundLeft, CaptureSoundRight: TSound;
-begin
- for S := 0 to High(Recording.Sound) do
- Recording.Sound[S].BufferLong[0].Clear;
-
- for SC := 0 to High(Ini.CardList) do begin
- PlayerLeft := Ini.CardList[SC].ChannelL-1;
- PlayerRight := Ini.CardList[SC].ChannelR-1;
- if PlayerLeft >= PlayersPlay then PlayerLeft := -1;
- if PlayerRight >= PlayersPlay then PlayerRight := -1;
- if (PlayerLeft > -1) or (PlayerRight > -1) then begin
- if (PlayerLeft > -1) then
- CaptureSoundLeft := Recording.Sound[PlayerLeft]
- else
- CaptureSoundLeft := nil;
- if (PlayerRight > -1) then
- CaptureSoundRight := Recording.Sound[PlayerRight]
- else
- CaptureSoundRight := nil;
-
- CaptureCard(SC, CaptureSoundLeft, CaptureSoundRight);
- end;
- end;
-end;
-
-// TODO: code is used by all IAudioInput implementors
-// -> move to a common superclass (TAudioInput_Generic?)
-procedure TAudio_Portaudio.CaptureStop;
-var
- SC: integer;
- PlayerLeft: integer;
- PlayerRight: integer;
-begin
-
- for SC := 0 to High(Ini.CardList) do begin
- PlayerLeft := Ini.CardList[SC].ChannelL-1;
- PlayerRight := Ini.CardList[SC].ChannelR-1;
- if PlayerLeft >= PlayersPlay then PlayerLeft := -1;
- if PlayerRight >= PlayersPlay then PlayerRight := -1;
- if (PlayerLeft > -1) or (PlayerRight > -1) then
- StopCard(SC);
- end;
-
-end;
-
-{*
- * Portaudio input capture callback.
- *}
-function MicrophoneCallback(input: Pointer; output: Pointer; frameCount: Longword;
- timeInfo: PPaStreamCallbackTimeInfo; statusFlags: TPaStreamCallbackFlags;
- inputDevice: Pointer): Integer; cdecl;
-begin
- Recording.HandleMicrophoneData(input, frameCount*4, inputDevice);
- result := paContinue;
-end;
-
-{*
- * Start input-capturing on Soundcard specified by Card.
- * Params:
- * Card - soundcard index in Recording.SoundCard array
- * CaptureSoundLeft - sound(-buffer) used for left channel capture data
- * CaptureSoundRight - sound(-buffer) used for right channel capture data
- *}
-procedure TAudio_Portaudio.CaptureCard(Card: byte; CaptureSoundLeft, CaptureSoundRight: TSound);
-var
- Error: TPaError;
- ErrorMsg: string;
- inputParams: TPaStreamParameters;
- deviceInfo: PPaDeviceInfo;
- stream: PPaStream;
- paSoundCard: TPortaudioSoundCard;
-begin
- paSoundCard := TPortaudioSoundCard(Recording.SoundCard[Card]);
- paSoundCard.CaptureSoundLeft := CaptureSoundLeft;
- paSoundCard.CaptureSoundRight := CaptureSoundRight;
-
- // get input latency info
- deviceInfo := Pa_GetDeviceInfo(paSoundCard.DeviceIndex);
-
- // set input stream parameters
- with inputParams do begin
- device := paSoundCard.DeviceIndex;
- channelCount := 2;
- sampleFormat := paInt16;
- suggestedLatency := deviceInfo^.defaultLowInputLatency;
- hostApiSpecificStreamInfo := nil;
- end;
-
- Log.LogStatus(inttostr(paSoundCard.DeviceIndex), 'Portaudio');
- Log.LogStatus(floattostr(deviceInfo^.defaultLowInputLatency), 'Portaudio');
-
- // open input stream
- Error := Pa_OpenStream(stream, @inputParams, nil, sampleRate,
- paFramesPerBufferUnspecified, paNoFlag,
- @MicrophoneCallback, Pointer(paSoundCard));
- if(Error <> paNoError) then begin
- ErrorMsg := Pa_GetErrorText(Error);
- Log.CriticalError('TAudio_Portaudio.CaptureCard('+ IntToStr(Card) +'): Error opening stream: ' + ErrorMsg);
- //Halt;
- end;
-
- paSoundCard.RecordStream := stream;
-
- // start capture
- Error := Pa_StartStream(stream);
- if(Error <> paNoError) then begin
- Pa_CloseStream(stream);
- ErrorMsg := Pa_GetErrorText(Error);
- Log.CriticalError('TAudio_Portaudio.CaptureCard('+ IntToStr(Card) +'): Error starting stream: ' + ErrorMsg);
- //Halt;
- end;
-end;
-
-{*
- * Stop input-capturing on Soundcard specified by Card.
- * Params:
- * Card - soundcard index in Recording.SoundCard array
- *}
-procedure TAudio_Portaudio.StopCard(Card: byte);
-var
- stream: PPaStream;
- paSoundCard: TPortaudioSoundCard;
-begin
- paSoundCard := TPortaudioSoundCard(Recording.SoundCard[Card]);
- stream := paSoundCard.RecordStream;
- if(stream <> nil) then begin
- Pa_StopStream(stream);
- Pa_CloseStream(stream);
- end;
-end;
-
-
-initialization
- singleton_MusicPortaudio := TAudio_Portaudio.create();
- AudioManager.add( singleton_MusicPortaudio );
-
-finalization
- AudioManager.Remove( singleton_MusicPortaudio );
-
-end.
diff --git a/Game/Code/Classes/UMedia_dummy.pas b/Game/Code/Classes/UMedia_dummy.pas
index 52e3434e..c973512d 100644
--- a/Game/Code/Classes/UMedia_dummy.pas
+++ b/Game/Code/Classes/UMedia_dummy.pas
@@ -45,8 +45,8 @@ type
procedure Pause;
procedure Stop;
- procedure MoveTo(Time: real);
- function getPosition: real;
+ procedure SetPosition(Time: real);
+ function GetPosition: real;
procedure GetFrame(Time: Extended);
procedure DrawGL(Screen: integer);
@@ -82,8 +82,6 @@ type
procedure PlayShuffle;
procedure StopShuffle;
- function LoadSoundFromFile(var stream: TAudioOutputStream; Name: string): boolean;
-
function LoadCustomSound(const Filename: String): Cardinal;
procedure PlayCustomSound(const Index: Cardinal );
@@ -135,7 +133,7 @@ procedure Tmedia_dummy.Stop;
begin
end;
-procedure Tmedia_dummy.MoveTo(Time: real);
+procedure Tmedia_dummy.SetPosition(Time: real);
begin
end;
@@ -251,11 +249,6 @@ procedure Tmedia_dummy.StopShuffle;
begin
end;
-function Tmedia_dummy.LoadSoundFromFile(var stream: TAudioOutputStream; Name: string): boolean;
-begin
- result := false;
-end;
-
function Tmedia_dummy.LoadCustomSound(const Filename: String): Cardinal;
begin
result := 0;
diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas
index c2d616ec..bf366130 100644
--- a/Game/Code/Classes/UMusic.pas
+++ b/Game/Code/Classes/UMusic.pas
@@ -83,17 +83,72 @@ type
Source: array of string;
end;
+type
TFFTData = array[0..256] of Single;
TPCMStereoSample = array[0..1] of Smallint;
TPCMData = array[0..511] of TPCMStereoSample;
- TAudioOutputStream = class
+type
+ TStreamStatus = (sStopped, sPlaying, sPaused);
+const
+ StreamStatusStr: array[TStreamStatus] of string = ('Stopped', 'Playing', 'Paused');
+
+type
+ TAudioProcessingStream = class
+ public
+ procedure Close(); virtual; abstract;
+ end;
+
+ TAudioPlaybackStream = class(TAudioProcessingStream)
+ protected
+ function GetLoop(): boolean; virtual; abstract;
+ procedure SetLoop(Enabled: boolean); virtual; abstract;
+ function GetLength(): real; virtual; abstract;
+ function GetStatus(): TStreamStatus; virtual; abstract;
+ public
+ procedure Play(); virtual; abstract;
+ procedure Pause(); virtual; abstract;
+ procedure Stop(); virtual; abstract;
+
+ property Loop: boolean READ GetLoop WRITE SetLoop;
+ property Length: real READ GetLength;
+ property Status: TStreamStatus READ GetStatus;
end;
+ (*
+ TAudioMixerStream = class(TAudioProcessingStream)
+ procedure AddStream(stream: TAudioProcessingStream);
+ procedure RemoveStream(stream: TAudioProcessingStream);
+ procedure SetMasterVolume(volume: cardinal);
+ function GetMasterVolume(): cardinal;
+ procedure SetStreamVolume(stream: TAudioProcessingStream; volume: cardinal);
+ function GetStreamVolume(stream: TAudioProcessingStream): cardinal;
+ end;
+ *)
+
+ TAudioDecodeStream = class(TAudioProcessingStream)
+ protected
+ function GetLength(): real; virtual; abstract;
+ function GetChannelCount(): cardinal; virtual; abstract;
+ function GetSampleRate(): cardinal; virtual; abstract;
+ function GetPosition(): real; virtual; abstract;
+ procedure SetPosition(Time: real); virtual; abstract;
+ function IsEOF(): boolean; virtual; abstract;
+ public
+ function ReadData(Buffer: PChar; BufSize: integer): integer; virtual; abstract;
+
+ property Length: real READ GetLength;
+ property ChannelCount: cardinal READ GetChannelCount;
+ property SampleRate: cardinal READ GetSampleRate;
+ property Position: real READ GetPosition WRITE SetPosition;
+ property EOF: boolean READ IsEOF;
+ end;
+
+type
TCustomSoundEntry = record
Filename : String;
- Stream : TAudioOutputStream;
+ Stream : TAudioPlaybackStream;
end;
type
@@ -101,23 +156,23 @@ type
['{63A5EBC3-3F4D-4F23-8DFB-B5165FCE33DD}']
function GetName: String;
- function Open(Name: string): boolean; // true if succeed
+ function Open(Filename: string): boolean; // true if succeed
procedure Close;
procedure Play;
procedure Pause;
procedure Stop;
- procedure MoveTo(Time: real);
- function getPosition: real;
-
- property position : real READ getPosition WRITE MoveTo;
+ procedure SetPosition(Time: real);
+ function GetPosition: real;
+
+ property Position : real READ GetPosition WRITE SetPosition;
end;
IVideoPlayback = Interface( IGenericPlayback )
['{3574C40C-28AE-4201-B3D1-3D1F0759B131}']
procedure init();
-
+
procedure GetFrame(Time: Extended); // WANT TO RENAME THESE TO BE MORE GENERIC
procedure DrawGL(Screen: integer); // WANT TO RENAME THESE TO BE MORE GENERIC
@@ -150,9 +205,6 @@ type
procedure PlayShuffle;
procedure StopShuffle;
- // TODO
- //function LoadSoundFromFile(var stream: TAudioOutputStream; Name: string): boolean;
-
//Custom Sounds
function LoadCustomSound(const Filename: String): Cardinal;
procedure PlayCustomSound(const Index: Cardinal );
@@ -164,6 +216,24 @@ type
function GetPCMData(var data: TPCMData): Cardinal;
end;
+ IGenericDecoder = Interface
+ ['{557B0E9A-604D-47E4-B826-13769F3E10B7}']
+ function InitializeDecoder(): boolean;
+ //function IsSupported(const Filename: string): boolean;
+ end;
+
+ (*
+ IVideoDecoder = Interface( IGenericDecoder )
+ ['{2F184B2B-FE69-44D5-9031-0A2462391DCA}']
+ function Open(const Filename: string): TVideoDecodeStream;
+ end;
+ *)
+
+ IAudioDecoder = Interface( IGenericDecoder )
+ ['{AB47B1B6-2AA9-4410-BF8C-EC79561B5478}']
+ function Open(const Filename: string): TAudioDecodeStream;
+ end;
+
IAudioInput = Interface
['{A5C8DA92-2A0C-4AB2-849B-2F7448C6003A}']
function GetName: String;
@@ -191,6 +261,7 @@ function Visualization(): IVideoPlayback;
function VideoPlayback(): IVideoPlayback;
function AudioPlayback(): IAudioPlayback;
function AudioInput(): IAudioInput;
+function AudioDecoder(): IAudioDecoder;
function AudioManager: TInterfaceList;
@@ -207,6 +278,7 @@ var
singleton_Visualization : IVideoPlayback = nil;
singleton_AudioPlayback : IAudioPlayback = nil;
singleton_AudioInput : IAudioInput = nil;
+ singleton_AudioDecoder : IAudioDecoder = nil;
singleton_AudioManager : TInterfaceList = nil;
@@ -240,6 +312,11 @@ begin
result := singleton_AudioInput;
end;
+function AudioDecoder(): IAudioDecoder;
+begin
+ result := singleton_AudioDecoder;
+end;
+
procedure InitializeSound;
var
lTmpInterface : IInterface;
@@ -249,6 +326,7 @@ begin
singleton_AudioPlayback := nil;
singleton_AudioInput := nil;
+ singleton_AudioDecoder := nil;
singleton_VideoPlayback := nil;
singleton_Visualization := nil;
@@ -271,6 +349,13 @@ begin
singleton_AudioInput := IAudioInput( lTmpInterface );
end;
+ // if this interface is a Decoder, then set it as the default used
+ if ( AudioManager[iCount].QueryInterface( IAudioDecoder, lTmpInterface ) = 0 ) AND
+ ( true ) then
+ begin
+ singleton_AudioDecoder := IAudioDecoder( lTmpInterface );
+ end;
+
// if this interface is a Input, then set it as the default used
if ( AudioManager[iCount].QueryInterface( IVideoPlayback, lTmpInterface ) = 0 ) AND
( true ) then
@@ -293,6 +378,11 @@ begin
begin
end;
+ if AudioDecoder <> nil then
+ begin
+ AudioDecoder.InitializeDecoder;
+ end;
+
if AudioPlayback <> nil then
begin
AudioPlayback.InitializePlayback;
diff --git a/Game/Code/Classes/UVideo.pas b/Game/Code/Classes/UVideo.pas
index 4f6b566a..bbd03d84 100644
--- a/Game/Code/Classes/UVideo.pas
+++ b/Game/Code/Classes/UVideo.pas
@@ -45,9 +45,11 @@ uses SDL,
dialogs,
{$endif}
{$ENDIF}
+ (* FIXME
{$ifdef UseFFMpegAudio}
- UAudio_FFMpeg,
+ UAudioDecoder_FFMpeg,
{$endif}
+ *)
UIni,
UMusic,
UGraphic;
@@ -101,8 +103,8 @@ type
procedure Pause;
procedure Stop;
- procedure MoveTo(Time: real);
- function getPosition: real;
+ procedure SetPosition(Time: real);
+ function GetPosition: real;
procedure GetFrame(Time: Extended);
procedure DrawGL(Screen: integer);
@@ -626,7 +628,7 @@ procedure TVideoPlayback_ffmpeg.Stop;
begin
end;
-procedure TVideoPlayback_ffmpeg.MoveTo(Time: real);
+procedure TVideoPlayback_ffmpeg.SetPosition(Time: real);
begin
fVideoSkipTime := Time;
@@ -639,7 +641,7 @@ begin
end;
// what is this supposed to do? return VideoTime?
-function TVideoPlayback_ffmpeg.getPosition: real;
+function TVideoPlayback_ffmpeg.GetPosition: real;
begin
result := 0;
end;
diff --git a/Game/Code/Classes/UVisualizer.pas b/Game/Code/Classes/UVisualizer.pas
index 5fc4bb82..22c168a2 100644
--- a/Game/Code/Classes/UVisualizer.pas
+++ b/Game/Code/Classes/UVisualizer.pas
@@ -61,9 +61,7 @@ type
VisualTex : glUint;
PCMData : TPCMData;
- hRC : Integer;
- hDC : Integer;
-
+
RndPCMcount : integer;
projMatrix: array[0..3, 0..3] of GLdouble;
@@ -91,8 +89,8 @@ type
procedure Pause;
procedure Stop;
- procedure MoveTo(Time: real);
- function getPosition: real;
+ procedure SetPosition(Time: real);
+ function GetPosition: real;
procedure GetFrame(Time: Extended);
procedure DrawGL(Screen: integer);
@@ -150,12 +148,12 @@ begin
VisualizerStop();
end;
-procedure TVideoPlayback_ProjectM.MoveTo(Time: real);
+procedure TVideoPlayback_ProjectM.SetPosition(Time: real);
begin
pm.RandomPreset();
end;
-function TVideoPlayback_ProjectM.getPosition: real;
+function TVideoPlayback_ProjectM.GetPosition: real;
begin
result := 0;
end;
@@ -240,7 +238,6 @@ end;
procedure TVideoPlayback_ProjectM.GetFrame(Time: Extended);
var
- i: integer;
nSamples: cardinal;
stackDepth: Integer;
begin
@@ -269,7 +266,7 @@ begin
// this may happen with some presets ( on linux ) if there is a div by zero
// in projectM's getBeatVals() function (file: beat_detect.cc)
Log.LogStatus('Div by zero!', 'Visualizer');
- MoveTo( now );
+ SetPosition( now );
end;
//glGetIntegerv(GL_PROJECTION_STACK_DEPTH, @stackDepth);
diff --git a/Game/Code/UltraStar.dpr b/Game/Code/UltraStar.dpr
index b15c5bbf..236d0b1e 100644
--- a/Game/Code/UltraStar.dpr
+++ b/Game/Code/UltraStar.dpr
@@ -21,7 +21,7 @@ uses
{$ifdef UseBass}
bass in 'lib\bass\delphi\bass.pas',
{$endif}
- {$ifdef UsePortAudio}
+ {$ifdef UsePortaudio}
portaudio in 'lib\portaudio\delphi\portaudio.pas',
{$endif}
{$ifdef UsePortmixer}
@@ -47,6 +47,7 @@ uses
rational in 'lib\ffmpeg\rational.pas',
opt in 'lib\ffmpeg\opt.pas',
avio in 'lib\ffmpeg\avio.pas',
+ mathematics in 'lib\ffmpeg\mathematics.pas',
// swscale in 'lib\ffmpeg\swscale.pas',
{$ifdef UseProjectM_0_9}
@@ -142,14 +143,20 @@ uses
UVisualizer in 'Classes\UVisualizer.pas', // MUST be before Video... so video can override...
{$ENDIF}
UVideo in 'Classes\UVideo.pas',
-{$ifdef UseBass}
- UAudio_bass in 'Classes\UAudio_bass.pas',
+{$ifdef UseFFMpegDecoder}
+ UAudioDecoder_FFMpeg in 'Classes\UAudioDecoder_FFMpeg.pas', // MUST be before Playback-classes
{$endif}
-{$ifdef UsePortaudio}
- UAudio_portaudio in 'Classes\UAudio_portaudio.pas',
+{$ifdef UseBASSInput}
+ UAudioInput_Bass in 'Classes\UAudioInput_Bass.pas',
{$endif}
-{$ifdef UseFFMpegAudio}
- UAudio_FFMpeg in 'Classes\UAudio_FFMpeg.pas',
+{$ifdef UseBASSPlayback}
+ UAudioPlayback_Bass in 'Classes\UAudioPlayback_Bass.pas',
+{$endif}
+{$ifdef UsePortaudioInput}
+ UAudioInput_Portaudio in 'Classes\UAudioInput_Portaudio.pas',
+{$endif}
+{$ifdef UsePortaudioPlayback}
+ UAudioPlayback_Portaudio in 'Classes\UAudioPlayback_Portaudio.pas',
{$endif}
diff --git a/Game/Code/switches.inc b/Game/Code/switches.inc
index 84aebbf5..3980a801 100644
--- a/Game/Code/switches.inc
+++ b/Game/Code/switches.inc
@@ -1,62 +1,69 @@
-{$DEFINE DEBUG} // to-do : Remove b4 release
-
-// Comment by eddie:
-// The mac port currently also uses the WIN32 define.
-// Once I get the beast compiled, linked and running
-// I will change this.
-// There are some parts where the WIN32 define could not
-// be used. I changed the WIN32 to MSWINDOWS.
-// So, for Windows-only code use the MSWINDOWS define.
-
-
-{$IFDEF FPC}
- {$IFDEF DARWIN}
- {$H+}
- {$R-}
- {$DEFINE WIN32}
- {$DEFINE TRANSLATE}
- {$ELSE}
- {$DEFINE LAZARUS}
- {$ENDIF}
-
-// {$MODE DELPHI} // JB - This is not allowed by the free pascal compiler for some reason ( At least on linux )
-
- {$DEFINE DLL_CDECL}
- {$UNDEF UseSerialPort}
- {$UNDEF UseMIDIPort}
-{$ELSE}
- {$DEFINE Delphi}
- {$DEFINE DLL_STDCALL}
- {$UNDEF UseSerialPort}
- {$DEFINE UseMIDIPort}
-{$ENDIF}
-
-
-{$IFDEF win32}
- {$DEFINE UseBASSOutput}
- {$DEFINE UseBASSInput}
-
- //{$DEFINE UsePortaudio}
- //{$DEFINE UsePortmixer}
-
- {$DEFINE UseProjectM_0_9}
-
- {$IFDEF DEBUG}
- {$IFNDEF DARWIN}
- {$APPTYPE CONSOLE}
- {$ENDIF}
- {$ENDIF}
-{$ELSE}
- //{$DEFINE FFMpegAudio}
-// {$DEFINE UsePortaudio}
- {$DEFINE UseProjectM_0_9}
-{$ENDIF}
-
-{$IF Defined(UseBASSInput) or Defined(UseBASSOutput)}
- {$DEFINE UseBASS}
-{$IFEND}
-
-{$IF Defined(UseProjectM_0_9) or Defined(UseProjectM_1_0)}
- {$DEFINE UseProjectM}
-{$IFEND}
-
+{$DEFINE DEBUG} // to-do : Remove b4 release
+
+// Comment by eddie:
+// The mac port currently also uses the WIN32 define.
+// Once I get the beast compiled, linked and running
+// I will change this.
+// There are some parts where the WIN32 define could not
+// be used. I changed the WIN32 to MSWINDOWS.
+// So, for Windows-only code use the MSWINDOWS define.
+
+
+{$IFDEF FPC}
+ {$IFDEF DARWIN}
+ {$H+}
+ {$R-}
+ {$DEFINE WIN32}
+ {$DEFINE TRANSLATE}
+ {$ELSE}
+ {$DEFINE LAZARUS}
+ {$ENDIF}
+
+// {$MODE DELPHI} // JB - This is not allowed by the free pascal compiler for some reason ( At least on linux )
+
+ {$DEFINE DLL_CDECL}
+ {$UNDEF UseSerialPort}
+ {$UNDEF UseMIDIPort}
+{$ELSE}
+ {$DEFINE Delphi}
+ {$DEFINE DLL_STDCALL}
+ {$UNDEF UseSerialPort}
+ {$DEFINE UseMIDIPort}
+{$ENDIF}
+
+
+{$IFDEF win32}
+ {$DEFINE UseBASSPlayback}
+ {$DEFINE UseBASSInput}
+
+ //{$DEFINE UseFFMpegDecoder}
+ //{$DEFINE UsePortaudioPlayback}
+ //{$DEFINE UsePortaudioInput}
+ //{$DEFINE UsePortmixer}
+
+ {$DEFINE UseProjectM_0_9}
+ //{$DEFINE UseProjectM_1_0}
+
+ {$IFDEF DEBUG}
+ {$IFNDEF DARWIN}
+ {$APPTYPE CONSOLE}
+ {$ENDIF}
+ {$ENDIF}
+{$ELSE}
+ {$DEFINE UseFFMpegAudio}
+ {$DEFINE UsePortaudio}
+ {$DEFINE UseProjectM_0_9}
+{$ENDIF}
+
+{$IF Defined(UseBASSInput) or Defined(UseBASSPlayback)}
+ {$DEFINE UseBASS}
+{$IFEND}
+
+{$IF Defined(UsePortaudioInput) or Defined(UsePortaudioPlayback)}
+ {$DEFINE UsePortaudio}
+{$IFEND}
+
+{$IF Defined(UseProjectM_0_9) or Defined(UseProjectM_1_0)}
+ {$DEFINE UseProjectM}
+{$IFEND}
+