diff options
-rw-r--r-- | Game/Code/Classes/UAudio_bass.pas | 1364 | ||||
-rw-r--r-- | Game/Code/Classes/UAudio_portaudio.pas | 2 | ||||
-rw-r--r-- | Game/Code/Classes/UCommandLine.pas | 622 | ||||
-rw-r--r-- | Game/Code/Classes/UMain.pas | 5 | ||||
-rw-r--r-- | Game/Code/Classes/UMedia_dummy.pas | 37 | ||||
-rw-r--r-- | Game/Code/Classes/UMusic.pas | 58 | ||||
-rw-r--r-- | Game/Code/Classes/UVideo.pas | 18 | ||||
-rw-r--r-- | Game/Code/Classes/UVisualizer.pas | 55 | ||||
-rw-r--r-- | Game/Code/Screens/UScreenSing.pas | 27 |
9 files changed, 1109 insertions, 1079 deletions
diff --git a/Game/Code/Classes/UAudio_bass.pas b/Game/Code/Classes/UAudio_bass.pas index 69278cca..a7bace06 100644 --- a/Game/Code/Classes/UAudio_bass.pas +++ b/Game/Code/Classes/UAudio_bass.pas @@ -1,685 +1,679 @@ -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
-{$IFDEF UseBASSInput}
- TAudio_bass = class( TInterfacedObject, IAudioPlayback, IAudioInput)
-{$ELSE}
- TAudio_bass = class( TInterfacedObject, IAudioPlayback)
-{$ENDIF}
- private
- BassStart: hStream; // Wait, I've replaced this with BASS
- BassBack: hStream; // It has almost all features we need
- BassSwoosh: hStream;
- BassChange: hStream; // Almost? It aleady has them all :)
- BassOption: hStream;
- BassClick: hStream;
- BassDrum: hStream;
- BassHihat: hStream;
- BassClap: hStream;
- BassShuffle: hStream;
-
- //Custom Sounds
- CustomSounds: array of TCustomSoundEntry;
- Loaded: boolean;
- Loop: boolean;
-
- public
- Bass: hStream;
- 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 hStream: 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;
-
-function TAudio_bass.GetName: String;
-begin
- result := 'BASS';
-end;
-
-procedure TAudio_bass.InitializePlayback;
-var
- Pet: integer;
- S: integer;
-begin
- writeln( 'TAudio_bass.InitializePlayback' );
-// Log.BenchmarkStart(4);
-// Log.LogStatus('Initializing Playback Subsystem', 'Music Initialize');
-
- Loaded := false;
- Loop := false;
-
- writeln( 'TAudio_bass BASS_Init' );
- 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');
-
- writeln( 'TAudio_bass LoadSoundFromFile' );
-// Log.BenchmarkStart(4);
- LoadSoundFromFile(BassStart, SoundPath + 'Common Start.mp3');
- LoadSoundFromFile(BassBack, SoundPath + 'Common Back.mp3');
- LoadSoundFromFile(BassSwoosh, SoundPath + 'menu swoosh.mp3');
- LoadSoundFromFile(BassChange, SoundPath + 'select music change music 50.mp3');
- LoadSoundFromFile(BassOption, SoundPath + 'option change col.mp3');
- LoadSoundFromFile(BassClick, SoundPath + 'rimshot022b.mp3');
-
-// LoadSoundFromFile(BassDrum, SoundPath + 'bassdrumhard076b.mp3');
-// LoadSoundFromFile(BassHihat, SoundPath + 'hihatclosed068b.mp3');
-// LoadSoundFromFile(BassClap, SoundPath + 'claps050b.mp3');
-
-// LoadSoundFromFile(BassShuffle, 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
- // TODO : jb_linux replace with something other than bass
- BASS_ChannelSetAttributes (Bass, -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
- Bass := 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(Bass, Time);
- BASS_ChannelSetPosition(Bass, bytes);
-end;
-
-procedure TAudio_bass.Play;
-begin
- if Loaded then
- begin
- if Loop then
- BASS_ChannelPlay(Bass, True); // start from beginning... actually bass itself does not loop, nor does this TAudio_bass Class
-
- BASS_ChannelPlay(Bass, False); // for setting position before playing
- end;
-end;
-
-procedure TAudio_bass.Pause; //Pause Mod
-begin
- if Loaded then begin
- BASS_ChannelPause(Bass); // Pauses Song
- end;
-end;
-
-procedure TAudio_bass.Stop;
-begin
- Bass_ChannelStop(Bass);
-end;
-
-procedure TAudio_bass.Close;
-begin
- Bass_StreamFree(Bass);
-end;
-
-function TAudio_bass.Length: real;
-var
- bytes: integer;
-begin
- Result := 60;
-
- bytes := BASS_ChannelGetLength(Bass);
- Result := BASS_ChannelBytes2Seconds(Bass, bytes);
-end;
-
-function TAudio_bass.getPosition: real;
-var
- bytes: integer;
-begin
- Result := 0;
-
- bytes := BASS_ChannelGetPosition(BASS);
- Result := BASS_ChannelBytes2Seconds(BASS, bytes);
-end;
-
-function TAudio_bass.Finished: boolean;
-begin
- Result := false;
-
- if BASS_ChannelIsActive(BASS) = BASS_ACTIVE_STOPPED then
- begin
- Result := true;
- end;
-end;
-
-procedure TAudio_bass.PlayStart;
-begin
- BASS_ChannelPlay(BassStart, True);
-end;
-
-procedure TAudio_bass.PlayBack;
-begin
- BASS_ChannelPlay(BassBack, True);// then
-end;
-
-procedure TAudio_bass.PlaySwoosh;
-begin
- BASS_ChannelPlay(BassSwoosh, True);
-end;
-
-procedure TAudio_bass.PlayChange;
-begin
- BASS_ChannelPlay(BassChange, True);
-end;
-
-procedure TAudio_bass.PlayOption;
-begin
- BASS_ChannelPlay(BassOption, True);
-end;
-
-procedure TAudio_bass.PlayClick;
-begin
- BASS_ChannelPlay(BassClick, True);
-end;
-
-procedure TAudio_bass.PlayDrum;
-begin
- BASS_ChannelPlay(BassDrum, True);
-end;
-
-procedure TAudio_bass.PlayHihat;
-begin
- BASS_ChannelPlay(BassHihat, True);
-end;
-
-procedure TAudio_bass.PlayClap;
-begin
- BASS_ChannelPlay(BassClap, True);
-end;
-
-procedure TAudio_bass.PlayShuffle;
-begin
- BASS_ChannelPlay(BassShuffle, True);
-end;
-
-procedure TAudio_bass.StopShuffle;
-begin
- BASS_ChannelStop(BassShuffle);
-end;
-
-function TAudio_bass.LoadSoundFromFile(var hStream: hStream; Name: string): boolean;
-var
- L: Integer;
-begin
- if FileExists(Name) then
- begin
- Log.LogStatus('Loading Sound: "' + Name + '"', 'LoadSoundFromFile');
- try
- hStream := BASS_StreamCreateFile(False, pchar(Name), 0, 0, 0);
-
- //Add CustomSound
- L := High(CustomSounds) + 1;
- SetLength (CustomSounds, L + 1);
- CustomSounds[L].Filename := Name;
- CustomSounds[L].Handle := hStream;
- 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(Bass, @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(Bass, 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(Bass, @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
- BASS_ChannelPlay(CustomSounds[Index].Handle, True);
-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();
-
- writeln( 'UAudio_Bass - Register' );
- AudioManager.add( singleton_MusicBass );
-
-finalization
- writeln( 'UAudio_Bass - UnRegister' );
- AudioManager.Remove( singleton_MusicBass );
-
-end.
+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 +{$IFDEF UseBASSInput} + TAudio_bass = class( TInterfacedObject, IAudioPlayback, IAudioInput) +{$ELSE} + TAudio_bass = class( TInterfacedObject, IAudioPlayback) +{$ENDIF} + private + BassStart: hStream; // Wait, I've replaced this with BASS + BassBack: hStream; // It has almost all features we need + BassSwoosh: hStream; + BassChange: hStream; // Almost? It aleady has them all :) + BassOption: hStream; + BassClick: hStream; + BassDrum: hStream; + BassHihat: hStream; + BassClap: hStream; + BassShuffle: hStream; + + //Custom Sounds + CustomSounds: array of TCustomSoundEntry; + Loaded: boolean; + Loop: boolean; + + public + Bass: hStream; + 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 hStream: 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; + +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(BassStart, SoundPath + 'Common Start.mp3'); + LoadSoundFromFile(BassBack, SoundPath + 'Common Back.mp3'); + LoadSoundFromFile(BassSwoosh, SoundPath + 'menu swoosh.mp3'); + LoadSoundFromFile(BassChange, SoundPath + 'select music change music 50.mp3'); + LoadSoundFromFile(BassOption, SoundPath + 'option change col.mp3'); + LoadSoundFromFile(BassClick, SoundPath + 'rimshot022b.mp3'); + +// LoadSoundFromFile(BassDrum, SoundPath + 'bassdrumhard076b.mp3'); +// LoadSoundFromFile(BassHihat, SoundPath + 'hihatclosed068b.mp3'); +// LoadSoundFromFile(BassClap, SoundPath + 'claps050b.mp3'); + +// LoadSoundFromFile(BassShuffle, 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 + // TODO : jb_linux replace with something other than bass + BASS_ChannelSetAttributes (Bass, -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 + Bass := 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(Bass, Time); + BASS_ChannelSetPosition(Bass, bytes); +end; + +procedure TAudio_bass.Play; +begin + if Loaded then + begin + if Loop then + BASS_ChannelPlay(Bass, True); // start from beginning... actually bass itself does not loop, nor does this TAudio_bass Class + + BASS_ChannelPlay(Bass, False); // for setting position before playing + end; +end; + +procedure TAudio_bass.Pause; //Pause Mod +begin + if Loaded then begin + BASS_ChannelPause(Bass); // Pauses Song + end; +end; + +procedure TAudio_bass.Stop; +begin + Bass_ChannelStop(Bass); +end; + +procedure TAudio_bass.Close; +begin + Bass_StreamFree(Bass); +end; + +function TAudio_bass.Length: real; +var + bytes: integer; +begin + Result := 60; + + bytes := BASS_ChannelGetLength(Bass); + Result := BASS_ChannelBytes2Seconds(Bass, bytes); +end; + +function TAudio_bass.getPosition: real; +var + bytes: integer; +begin + Result := 0; + + bytes := BASS_ChannelGetPosition(BASS); + Result := BASS_ChannelBytes2Seconds(BASS, bytes); +end; + +function TAudio_bass.Finished: boolean; +begin + Result := false; + + if BASS_ChannelIsActive(BASS) = BASS_ACTIVE_STOPPED then + begin + Result := true; + end; +end; + +procedure TAudio_bass.PlayStart; +begin + BASS_ChannelPlay(BassStart, True); +end; + +procedure TAudio_bass.PlayBack; +begin + BASS_ChannelPlay(BassBack, True);// then +end; + +procedure TAudio_bass.PlaySwoosh; +begin + BASS_ChannelPlay(BassSwoosh, True); +end; + +procedure TAudio_bass.PlayChange; +begin + BASS_ChannelPlay(BassChange, True); +end; + +procedure TAudio_bass.PlayOption; +begin + BASS_ChannelPlay(BassOption, True); +end; + +procedure TAudio_bass.PlayClick; +begin + BASS_ChannelPlay(BassClick, True); +end; + +procedure TAudio_bass.PlayDrum; +begin + BASS_ChannelPlay(BassDrum, True); +end; + +procedure TAudio_bass.PlayHihat; +begin + BASS_ChannelPlay(BassHihat, True); +end; + +procedure TAudio_bass.PlayClap; +begin + BASS_ChannelPlay(BassClap, True); +end; + +procedure TAudio_bass.PlayShuffle; +begin + BASS_ChannelPlay(BassShuffle, True); +end; + +procedure TAudio_bass.StopShuffle; +begin + BASS_ChannelStop(BassShuffle); +end; + +function TAudio_bass.LoadSoundFromFile(var hStream: hStream; Name: string): boolean; +var + L: Integer; +begin + if FileExists(Name) then + begin + Log.LogStatus('Loading Sound: "' + Name + '"', 'LoadSoundFromFile'); + try + hStream := BASS_StreamCreateFile(False, pchar(Name), 0, 0, 0); + + //Add CustomSound + L := High(CustomSounds) + 1; + SetLength (CustomSounds, L + 1); + CustomSounds[L].Filename := Name; + CustomSounds[L].Handle := hStream; + 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(Bass, @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(Bass, 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(Bass, @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 + BASS_ChannelPlay(CustomSounds[Index].Handle, True); +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 index 941d90d1..47e54981 100644 --- a/Game/Code/Classes/UAudio_portaudio.pas +++ b/Game/Code/Classes/UAudio_portaudio.pas @@ -419,11 +419,9 @@ end; initialization singleton_MusicPortaudio := TAudio_Portaudio.create(); - writeln( 'UAudio_Portaudio - Register' ); AudioManager.add( singleton_MusicPortaudio ); finalization - writeln( 'UAudio_Portaudio - UnRegister' ); AudioManager.Remove( singleton_MusicPortaudio ); end. diff --git a/Game/Code/Classes/UCommandLine.pas b/Game/Code/Classes/UCommandLine.pas index 01ece795..6a5a4808 100644 --- a/Game/Code/Classes/UCommandLine.pas +++ b/Game/Code/Classes/UCommandLine.pas @@ -1,294 +1,328 @@ -unit UCommandLine;
-
-interface
-
-{$IFDEF FPC}
- {$MODE Delphi}
-{$ENDIF}
-
-{$I switches.inc}
-
-
-type
- //-----------
- // TCMDParams - Class Reaads Infos from ParamStr and set some easy Interface Variables
- //-----------
- TCMDParams = class
- private
- sLanguage: String;
- sResolution: String;
- public
- //Some Boolean Variables Set when Reading Infos
- Debug: Boolean;
- Benchmark: Boolean;
- NoLog: Boolean;
- FullScreen: Boolean;
- Joypad: Boolean;
-
- //Some Value Variables Set when Reading Infos {-1: Not Set, others: Value}
- Depth: Integer;
- Screens: Integer;
-
- //Some Strings Set when Reading Infos {Length=0 Not Set}
- SongPath: String;
- ConfigFile: String;
- ScoreFile: String;
-
- //Pseudo Integer Values
- Function GetLanguage: Integer;
- Property Language: Integer read GetLanguage;
-
- Function GetResolution: Integer;
- Property Resolution: Integer read GetResolution;
-
- //Some Procedures for Reading Infos
- Constructor Create;
-
- Procedure ResetVariables;
- Procedure ReadParamInfo;
- end;
-
-var
- Params: TCMDParams;
-
-implementation
-
-uses SysUtils;
-// uINI -- Nasty requirement... ( removed with permission of blindy )
-
-
-//-------------
-// Constructor - Create class, Reset Variables and Read Infos
-//-------------
-Constructor TCMDParams.Create;
-begin
- ResetVariables;
- ReadParamInfo;
-end;
-
-//-------------
-// ResetVariables - Reset Class Variables
-//-------------
-Procedure TCMDParams.ResetVariables;
-begin
- Debug := False;
- Benchmark := False;
- NoLog := False;
- FullScreen := False;
- Joypad := False;
-
- //Some Value Variables Set when Reading Infos {-1: Not Set, others: Value}
- sResolution := '';
- sLanguage := '';
- Depth := -1;
- Screens := -1;
-
- //Some Strings Set when Reading Infos {Length=0 Not Set}
- SongPath := '';
- ConfigFile := '';
- ScoreFile := '';
-end;
-
-//-------------
-// ReadParamInfo - Read Infos from Parameters
-//-------------
-Procedure TCMDParams.ReadParamInfo;
-var
- I: Integer;
- PCount: Integer;
- Command: String;
-begin
- PCount := ParamCount;
- //Log.LogError('ParamCount: ' + Inttostr(PCount));
-
- //Check all Parameters
- For I := 1 to PCount do
- begin
- Command := Paramstr(I);
- //Log.LogError('Start parsing Command: ' + Command);
- //Is String Parameter ?
- if (Length(Command) > 1) AND (Command[1] = '-') then
- begin
- //Remove - from Command
- Command := Lowercase(Trim(Copy(Command, 2, Length(Command) - 1)));
- //Log.LogError('Command prepared: ' + Command);
-
- //Check Command
-
- // Boolean Triggers:
- if (Command = 'debug') then
- Debug := True
- else if (Command = 'benchmark') then
- Benchmark := True
- else if (Command = 'nolog') then
- NoLog := True
- else if (Command = 'fullscreen') then
- Fullscreen := True
- else if (Command = 'joypad') then
- Joypad := True
-
- //Integer Variables
- else if (Command = 'depth') then
- begin
- //Check if there is another Parameter to get the Value from
- if (PCount > I) then
- begin
- Command := ParamStr(I + 1);
-
- //Check for valid Value
- If (Command = '16') then
- Depth := 0
- Else If (Command = '32') then
- Depth := 1;
- end;
- end
-
- else if (Command = 'screens') then
- begin
- //Check if there is another Parameter to get the Value from
- if (PCount > I) then
- begin
- Command := ParamStr(I + 1);
-
- //Check for valid Value
- If (Command = '1') then
- Screens := 0
- Else If (Command = '2') then
- Screens := 1;
- end;
- end
-
- //Pseudo Integer Values
- else if (Command = 'language') then
- begin
- //Check if there is another Parameter to get the Value from
- if (PCount > I) then
- begin
- //Write Value to String
- sLanguage := Lowercase(ParamStr(I + 1));
- end;
- end
-
- else if (Command = 'resolution') then
- begin
- //Check if there is another Parameter to get the Value from
- if (PCount > I) then
- begin
- //Write Value to String
- sResolution := Lowercase(ParamStr(I + 1));
- end;
- end
-
- //String Values
- else if (Command = 'songpath') then
- begin
- //Check if there is another Parameter to get the Value from
- if (PCount > I) then
- begin
- //Write Value to String
- SongPath := ParamStr(I + 1);
- end;
- end
-
- else if (Command = 'configfile') then
- begin
- //Check if there is another Parameter to get the Value from
- if (PCount > I) then
- begin
- //Write Value to String
- ConfigFile := ParamStr(I + 1);
-
- //is this a relative PAth -> then add Gamepath
- if Not ((Length(ConfigFile) > 2) AND (ConfigFile[2] = ':')) then
- ConfigFile := ExtractFilePath(ParamStr(0)) + Configfile;
- end;
- end
-
- else if (Command = 'scorefile') then
- begin
- //Check if there is another Parameter to get the Value from
- if (PCount > I) then
- begin
- //Write Value to String
- ScoreFile := ParamStr(I + 1);
- end;
- end;
-
- end;
-
- end;
-
-{ Log.LogError('Values: ');
-
- if Debug then
- Log.LogError('Debug');
-
- if Benchmark then
- Log.LogError('Benchmark');
-
- if NoLog then
- Log.LogError('NoLog');
-
- if Fullscreen then
- Log.LogError('FullScreen');
-
- if JoyStick then
- Log.LogError('Joystick');
-
-
- Log.LogError('Screens: ' + Inttostr(Screens));
- Log.LogError('Depth: ' + Inttostr(Depth));
-
- Log.LogError('Resolution: ' + Inttostr(Resolution));
- Log.LogError('Resolution: ' + Inttostr(Language));
-
- Log.LogError('sResolution: ' + sResolution);
- Log.LogError('sLanguage: ' + sLanguage);
-
- Log.LogError('ConfigFile: ' + ConfigFile);
- Log.LogError('SongPath: ' + SongPath);
- Log.LogError('ScoreFile: ' + ScoreFile); }
-
-end;
-
-//-------------
-// GetLanguage - Get Language ID from saved String Information
-//-------------
-Function TCMDParams.GetLanguage: Integer;
-var
- I: integer;
-begin
- Result := -1;
-{* JB - 12sep07 to remove uINI dependency
-
- //Search for Language
- For I := 0 to high(ILanguage) do
- if (LowerCase(ILanguage[I]) = sLanguage) then
- begin
- Result := I;
- Break;
- end;
-*}
-end;
-
-//-------------
-// GetResolution - Get Resolution ID from saved String Information
-//-------------
-Function TCMDParams.GetResolution: Integer;
-var
- I: integer;
-begin
- Result := -1;
-{* JB - 12sep07 to remove uINI dependency
-
- //Search for Resolution
- For I := 0 to high(IResolution) do
- if (LowerCase(IResolution[I]) = sResolution) then
- begin
- Result := I;
- Break;
- end;
-*}
-end;
-
-end.
+unit UCommandLine; + +interface + +{$IFDEF FPC} + {$MODE Delphi} +{$ENDIF} + +{$I switches.inc} + + +type + //----------- + // TCMDParams - Class Reaads Infos from ParamStr and set some easy Interface Variables + //----------- + TCMDParams = class + private + sLanguage: String; + sResolution: String; + public + //Some Boolean Variables Set when Reading Infos + Debug: Boolean; + Benchmark: Boolean; + NoLog: Boolean; + FullScreen: Boolean; + Joypad: Boolean; + + //Some Value Variables Set when Reading Infos {-1: Not Set, others: Value} + Depth: Integer; + Screens: Integer; + + //Some Strings Set when Reading Infos {Length=0 Not Set} + SongPath: String; + ConfigFile: String; + ScoreFile: String; + + procedure showhelp(); + + //Pseudo Integer Values + Function GetLanguage: Integer; + Property Language: Integer read GetLanguage; + + Function GetResolution: Integer; + Property Resolution: Integer read GetResolution; + + //Some Procedures for Reading Infos + Constructor Create; + + Procedure ResetVariables; + Procedure ReadParamInfo; + end; + +var + Params: TCMDParams; + +const + cHelp = 'help'; + cMediaInterfaces = 'showinterfaces'; + + +implementation + +uses SysUtils; +// uINI -- Nasty requirement... ( removed with permission of blindy ) + + +//------------- +// Constructor - Create class, Reset Variables and Read Infos +//------------- +Constructor TCMDParams.Create; +begin + + if FindCmdLineSwitch( cHelp ) then + showhelp(); + + ResetVariables; + ReadParamInfo; +end; + +procedure TCMDParams.showhelp(); + + function s( aString : String ) : string; + begin + result := aString + StringofChar( ' ', 15 - length( aString ) ); + end; + +begin + + writeln( '' ); + writeln( '**************************************************************' ); + writeln( ' UltraStar Deluxe - Command line switches ' ); + writeln( '**************************************************************' ); + writeln( '' ); + writeln( ' '+s( 'Switch' ) +' : Purpose' ); + writeln( ' ----------------------------------------------------------' ); + writeln( ' '+s( cMediaInterfaces ) + ' : Show in-use media interfaces' ); + writeln( '' ); + + halt(); +end; + +//------------- +// ResetVariables - Reset Class Variables +//------------- +Procedure TCMDParams.ResetVariables; +begin + Debug := False; + Benchmark := False; + NoLog := False; + FullScreen := False; + Joypad := False; + + //Some Value Variables Set when Reading Infos {-1: Not Set, others: Value} + sResolution := ''; + sLanguage := ''; + Depth := -1; + Screens := -1; + + //Some Strings Set when Reading Infos {Length=0 Not Set} + SongPath := ''; + ConfigFile := ''; + ScoreFile := ''; +end; + +//------------- +// ReadParamInfo - Read Infos from Parameters +//------------- +Procedure TCMDParams.ReadParamInfo; +var + I: Integer; + PCount: Integer; + Command: String; +begin + PCount := ParamCount; + //Log.LogError('ParamCount: ' + Inttostr(PCount)); + + + //Check all Parameters + For I := 1 to PCount do + begin + Command := Paramstr(I); + //Log.LogError('Start parsing Command: ' + Command); + //Is String Parameter ? + if (Length(Command) > 1) AND (Command[1] = '-') then + begin + //Remove - from Command + Command := Lowercase(Trim(Copy(Command, 2, Length(Command) - 1))); + //Log.LogError('Command prepared: ' + Command); + + //Check Command + + // Boolean Triggers: + if (Command = 'debug') then + Debug := True + else if (Command = 'benchmark') then + Benchmark := True + else if (Command = 'nolog') then + NoLog := True + else if (Command = 'fullscreen') then + Fullscreen := True + else if (Command = 'joypad') then + Joypad := True + + //Integer Variables + else if (Command = 'depth') then + begin + //Check if there is another Parameter to get the Value from + if (PCount > I) then + begin + Command := ParamStr(I + 1); + + //Check for valid Value + If (Command = '16') then + Depth := 0 + Else If (Command = '32') then + Depth := 1; + end; + end + + else if (Command = 'screens') then + begin + //Check if there is another Parameter to get the Value from + if (PCount > I) then + begin + Command := ParamStr(I + 1); + + //Check for valid Value + If (Command = '1') then + Screens := 0 + Else If (Command = '2') then + Screens := 1; + end; + end + + //Pseudo Integer Values + else if (Command = 'language') then + begin + //Check if there is another Parameter to get the Value from + if (PCount > I) then + begin + //Write Value to String + sLanguage := Lowercase(ParamStr(I + 1)); + end; + end + + else if (Command = 'resolution') then + begin + //Check if there is another Parameter to get the Value from + if (PCount > I) then + begin + //Write Value to String + sResolution := Lowercase(ParamStr(I + 1)); + end; + end + + //String Values + else if (Command = 'songpath') then + begin + //Check if there is another Parameter to get the Value from + if (PCount > I) then + begin + //Write Value to String + SongPath := ParamStr(I + 1); + end; + end + + else if (Command = 'configfile') then + begin + //Check if there is another Parameter to get the Value from + if (PCount > I) then + begin + //Write Value to String + ConfigFile := ParamStr(I + 1); + + //is this a relative PAth -> then add Gamepath + if Not ((Length(ConfigFile) > 2) AND (ConfigFile[2] = ':')) then + ConfigFile := ExtractFilePath(ParamStr(0)) + Configfile; + end; + end + + else if (Command = 'scorefile') then + begin + //Check if there is another Parameter to get the Value from + if (PCount > I) then + begin + //Write Value to String + ScoreFile := ParamStr(I + 1); + end; + end; + + end; + + end; + +{ Log.LogError('Values: '); + + if Debug then + Log.LogError('Debug'); + + if Benchmark then + Log.LogError('Benchmark'); + + if NoLog then + Log.LogError('NoLog'); + + if Fullscreen then + Log.LogError('FullScreen'); + + if JoyStick then + Log.LogError('Joystick'); + + + Log.LogError('Screens: ' + Inttostr(Screens)); + Log.LogError('Depth: ' + Inttostr(Depth)); + + Log.LogError('Resolution: ' + Inttostr(Resolution)); + Log.LogError('Resolution: ' + Inttostr(Language)); + + Log.LogError('sResolution: ' + sResolution); + Log.LogError('sLanguage: ' + sLanguage); + + Log.LogError('ConfigFile: ' + ConfigFile); + Log.LogError('SongPath: ' + SongPath); + Log.LogError('ScoreFile: ' + ScoreFile); } + +end; + +//------------- +// GetLanguage - Get Language ID from saved String Information +//------------- +Function TCMDParams.GetLanguage: Integer; +var + I: integer; +begin + Result := -1; +{* JB - 12sep07 to remove uINI dependency + + //Search for Language + For I := 0 to high(ILanguage) do + if (LowerCase(ILanguage[I]) = sLanguage) then + begin + Result := I; + Break; + end; +*} +end; + +//------------- +// GetResolution - Get Resolution ID from saved String Information +//------------- +Function TCMDParams.GetResolution: Integer; +var + I: integer; +begin + Result := -1; +{* JB - 12sep07 to remove uINI dependency + + //Search for Resolution + For I := 0 to high(IResolution) do + if (LowerCase(IResolution[I]) = sResolution) then + begin + Result := I; + Break; + end; +*} +end; + +end. diff --git a/Game/Code/Classes/UMain.pas b/Game/Code/Classes/UMain.pas index 67ec2ea8..b97408d4 100644 --- a/Game/Code/Classes/UMain.pas +++ b/Game/Code/Classes/UMain.pas @@ -120,7 +120,10 @@ procedure ClearScores(PlayerNum: integer); implementation -uses USongs, UJoystick, math, UCommandLine, ULanguage, SDL_ttf, +uses USongs, + UJoystick, + math, + UCommandLine, ULanguage, SDL_ttf, USkins, UCovers, UCatCovers, UDataBase, UPlaylist, UDLLManager, UParty, UCore, UGraphicClasses, UPluginDefs, UPlatform; diff --git a/Game/Code/Classes/UMedia_dummy.pas b/Game/Code/Classes/UMedia_dummy.pas index a5cc4b5a..697dc2f9 100644 --- a/Game/Code/Classes/UMedia_dummy.pas +++ b/Game/Code/Classes/UMedia_dummy.pas @@ -171,37 +171,9 @@ begin result := data; end; -var count: integer = 0; - function Tmedia_dummy.GetPCMData(var data: TPCMData): Cardinal; -var i: integer; -begin - // Produce some fake PCM data - if ( count mod 500 = 0 ) then - begin - for i := 0 to 511 do begin - data[0][i] := 0; - data[1][i] := 0; - end; - end - else begin - for i := 0 to 511 do begin - if ( i mod 2 = 0 ) then begin - data[0][i] := floor(Random * power(2.,14)); - data[1][i] := floor(Random * power(2.,14)); - end - else begin; - data[0][i] := floor(Random * power(2.,14)); - data[1][i] := floor(Random * power(2.,14)); - end; - if ( i mod 2 = 1 ) then begin - data[0][i] := -data[0][i]; - data[1][i] := -data[1][i]; - end; - end; - end; - Inc(count); - result := 512; +begin + result := 0; end; // IAudioPlayback @@ -293,16 +265,11 @@ procedure Tmedia_dummy.PlayCustomSound(const Index: Cardinal ); begin end; - - initialization singleton_dummy := Tmedia_dummy.create(); - - writeln( 'UMedia_dummy - Register' ); AudioManager.add( singleton_dummy ); finalization - writeln( 'UMedia_dummy - UnRegister' ); AudioManager.Remove( singleton_dummy ); end. diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas index 2cdcc707..7e1aa839 100644 --- a/Game/Code/Classes/UMusic.pas +++ b/Game/Code/Classes/UMusic.pas @@ -109,21 +109,12 @@ type procedure MoveTo(Time: real); function getPosition: real; - - property position : real READ getPosition WRITE MoveTo; + + property position : real READ getPosition WRITE MoveTo; end; IVideoPlayback = Interface( IGenericPlayback ) ['{3574C40C-28AE-4201-B3D1-3D1F0759B131}'] -(* - procedure FFmpegOpenFile(FileName: pAnsiChar); - procedure FFmpegClose; - - procedure FFmpegGetFrame(Time: Extended); - procedure FFmpegDrawGL(Screen: integer); - procedure FFmpegTogglePause; - procedure FFmpegSkip(Time: Single); -*) procedure init(); procedure GetFrame(Time: Extended); // WANT TO RENAME THESE TO BE MORE GENERIC @@ -141,16 +132,10 @@ type 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; -// procedure Stop; -// procedure Close; - function Finished: boolean; - function Length: real; -// function getPosition: real; + function Finished: boolean; + function Length: real; procedure PlayStart; procedure PlayBack; @@ -211,7 +196,8 @@ function AudioManager: TInterfaceList; implementation uses - sysutils; + sysutils, + UCommandLine; // uLog; var @@ -264,7 +250,6 @@ begin singleton_VideoPlayback := nil; singleton_Visualization := nil; - writeln( 'InitializeSound , Enumerate Registered Audio Interfaces' ); for iCount := 0 to AudioManager.Count - 1 do begin if assigned( AudioManager[iCount] ) then @@ -273,7 +258,6 @@ begin if ( AudioManager[iCount].QueryInterface( IAudioPlayback, lTmpInterface ) = 0 ) AND ( true ) then -// ( not assigned( singleton_AudioPlayback ) ) then begin singleton_AudioPlayback := IAudioPlayback( lTmpInterface ); end; @@ -281,17 +265,13 @@ begin // if this interface is a Input, then set it as the default used if ( AudioManager[iCount].QueryInterface( IAudioInput, lTmpInterface ) = 0 ) AND ( true ) then -// ( not assigned( singleton_AudioInput ) ) then begin singleton_AudioInput := IAudioInput( lTmpInterface ); - Writeln(singleton_AudioInput.GetName); end; // if this interface is a Input, then set it as the default used if ( AudioManager[iCount].QueryInterface( IVideoPlayback, lTmpInterface ) = 0 ) AND - //( AudioManager[iCount].QueryInterface( IVideoVisualization, lTmpInterface ) <> 0 ) AND ( true ) then -// ( not assigned( singleton_VideoPlayback ) ) then begin singleton_VideoPlayback := IVideoPlayback( lTmpInterface ); end; @@ -306,38 +286,44 @@ begin end; + if VideoPlayback <> nil then begin - writeln( 'Registered Video Playback Interface : ' + VideoPlayback.GetName ); end; if AudioPlayback <> nil then begin - writeln( 'Registered Audio Playback Interface : ' + AudioPlayback.GetName ); - // Log.LogStatus('Initializing Playback ('+AudioPlayback.GetName+')', 'InitializeSound'); AudioPlayback.InitializePlayback; end; if AudioInput <> nil then begin - writeln( 'Registered Audio Input Interface : ' + AudioInput.GetName ); - -// Log.LogStatus('Initializing Record ('+AudioPlayback.GetName+')', 'InitializeSound'); AudioInput.InitializeRecord; end; - writeln( 'InitializeSound DONE' ); + if FindCmdLineSwitch( cMediaInterfaces ) then + begin + writeln( '' ); + writeln( '--------------------------------------------------------------' ); + writeln( ' In-use Media Interfaces ' ); + writeln( '--------------------------------------------------------------' ); + writeln( 'Registered Audio Playback Interface : ' + AudioPlayback.GetName ); + writeln( 'Registered Audio Input Interface : ' + AudioInput.GetName ); + writeln( 'Registered Video Playback Interface : ' + VideoPlayback.GetName ); + writeln( 'Registered Visualization Interface : ' + Visualization.GetName ); + writeln( '--------------------------------------------------------------' ); + writeln( '' ); + halt; + end; end; initialization begin - writeln('Init AudioManager'); singleton_AudioManager := TInterfaceList.Create(); end; finalization - writeln('Finalize AudioManager'); singleton_AudioManager.clear; FreeAndNil( singleton_AudioManager ); diff --git a/Game/Code/Classes/UVideo.pas b/Game/Code/Classes/UVideo.pas index 62351e2d..644c62a8 100644 --- a/Game/Code/Classes/UVideo.pas +++ b/Game/Code/Classes/UVideo.pas @@ -161,7 +161,7 @@ begin writeln( ' aFormatCtx.nb_streams : ' + inttostr( aFormatCtx.nb_streams ) ); writeln( ' length( aFormatCtx.streams ) : ' + inttostr( length(aFormatCtx.streams) ) ); - + i := 0; while ( i < aFormatCtx.nb_streams ) do // while ( i < length(aFormatCtx.streams)-1 ) do @@ -415,22 +415,15 @@ end; constructor TVideoPlayback_ffmpeg.create(); begin - writeln( 'UVideo_FFMpeg - TVideoPlayback_ffmpeg.create()' ); - - writeln( 'UVideo_FFMpeg - av_register_all' ); av_register_all; fVideoOpened := False; fVideoPaused := False; - end; procedure TVideoPlayback_ffmpeg.init(); begin - writeln( 'UVideo_FFMpeg - glGenTextures(1, PglUint(@fVideoTex))' ); glGenTextures(1, PglUint(@fVideoTex)); - - writeln( 'UVideo_FFMpeg - SetLength(fTexData,0)' ); SetLength(fTexData,0); end; @@ -453,10 +446,10 @@ begin TimeDifference := 0; VideoFormatContext := 0; - writeln( aFileName ); - +// writeln( aFileName ); + errnum := av_open_input_file(VideoFormatContext, pchar( aFileName ), Nil, 0, Nil); - writeln( 'Errnum : ' +inttostr( errnum )); +// writeln( 'Errnum : ' +inttostr( errnum )); if(errnum <> 0) then begin {$ifdef DebugDisplay} @@ -684,11 +677,8 @@ end; initialization singleton_VideoFFMpeg := TVideoPlayback_ffmpeg.create(); - - writeln( 'UVideo_FFMpeg - Register Playback' ); AudioManager.add( singleton_VideoFFMpeg ); - finalization AudioManager.Remove( singleton_VideoFFMpeg ); diff --git a/Game/Code/Classes/UVisualizer.pas b/Game/Code/Classes/UVisualizer.pas index fa737d81..6548e2b7 100644 --- a/Game/Code/Classes/UVisualizer.pas +++ b/Game/Code/Classes/UVisualizer.pas @@ -56,10 +56,14 @@ type hRC : Integer; hDC : Integer; + RndPCMcount : integer; + procedure VisualizerStart; procedure VisualizerStop; procedure VisualizerTogglePause; + + function GetRandomPCMData(var data: TPCMData): Cardinal; public constructor create(); procedure init(); @@ -82,13 +86,12 @@ type constructor TVideoPlayback_ProjectM.create(); begin + RndPCMcount := 0; end; procedure TVideoPlayback_ProjectM.init(); begin - writeln( 'TVideoPlayback_ProjectM - INITIALIZE !!!!!!!!' ); - VisualizerStarted := False; VisualizerPaused := False; @@ -232,6 +235,10 @@ begin // get audio data nSamples := AudioPlayback.GetPCMData(PcmData); + + if nSamples = 0 then + nSamples := GetRandomPCMData(PcmData); + addPCM16Data(PPCM16Data(@PcmData), nSamples); // store OpenGL state (might be messed up otherwise) @@ -244,7 +251,15 @@ begin glPushMatrix(); // let projectM render a frame - renderFrame(pm); + try + renderFrame(pm); + except + // This happens with some presets... ( and only some times also .. moreso on linux ) + // if we have an "Invalid Floating Point Error" while rendering a frame... then change preset. + MoveTo( now ); + + // hmm have to be careful, that we dont get to many here... coz it could keep failing.. and trying again. + end; glFlush(); {$IFDEF UseTexture} @@ -323,11 +338,41 @@ begin {$ENDIF} end; +function TVideoPlayback_ProjectM.GetRandomPCMData(var data: TPCMData): Cardinal; +var + i: integer; +begin + // Produce some fake PCM data + if ( RndPCMcount mod 500 = 0 ) then + begin + for i := 0 to 511 do begin + data[0][i] := 0; + data[1][i] := 0; + end; + end + else begin + for i := 0 to 511 do begin + if ( i mod 2 = 0 ) then begin + data[0][i] := floor(Random * power(2.,14)); + data[1][i] := floor(Random * power(2.,14)); + end + else begin; + data[0][i] := floor(Random * power(2.,14)); + data[1][i] := floor(Random * power(2.,14)); + end; + if ( i mod 2 = 1 ) then begin + data[0][i] := -data[0][i]; + data[1][i] := -data[1][i]; + end; + end; + end; + Inc( RndPCMcount ); + result := 512; +end; + initialization singleton_VideoProjectM := TVideoPlayback_ProjectM.create(); - - writeln( 'UVideoProjectM - Register Playback' ); AudioManager.add( singleton_VideoProjectM ); finalization diff --git a/Game/Code/Screens/UScreenSing.pas b/Game/Code/Screens/UScreenSing.pas index 75246d09..31e9f511 100644 --- a/Game/Code/Screens/UScreenSing.pas +++ b/Game/Code/Screens/UScreenSing.pas @@ -165,14 +165,14 @@ begin if fShowVisualization then fCurrentVideoPlaybackEngine.play; -
+ end; SDLK_TAB: //Change Visualization Preset begin - if fShowVisualization then
- fCurrentVideoPlaybackEngine.MoveTo( now ); // move to a random position
- end;
+ if fShowVisualization then + fCurrentVideoPlaybackEngine.MoveTo( now ); // move to a random position + end; SDLK_RETURN: begin @@ -1144,13 +1144,18 @@ begin if ShowFinish and ( AktSong.VideoLoaded or fShowVisualization ) then // if ShowFinish then begin - try +// try // UpdateSmpeg; // this only draws // todo: find a way to determine, when a new frame is needed // toto: same for the need to skip frames - fCurrentVideoPlaybackEngine.GetFrame(Czas.Teraz); - fCurrentVideoPlaybackEngine.DrawGL(ScreenAct); + if assigned( fCurrentVideoPlaybackEngine ) then + begin + fCurrentVideoPlaybackEngine.GetFrame(Czas.Teraz); + fCurrentVideoPlaybackEngine.DrawGL(ScreenAct); + end; + +(* except on E : Exception do begin @@ -1170,6 +1175,8 @@ begin end; end; end; +*) + end; // draw static menu (FG) @@ -1332,6 +1339,12 @@ begin if Ini.EffectSing=1 then GoldenRec.SpawnPerfectLineTwinkle; //PerfectLineTwinkle Mod end + + + // if we are shoing a visualization... change to a new preset after each sentence.. + // Maybe we should make this less often or something... just a + if fShowVisualization then + fCurrentVideoPlaybackEngine.MoveTo( now ); // move to a random position end; //Called on Sentence Change S= New Current Sentence |