diff options
author | tobigun <tobigun@b956fd51-792f-4845-bead-9b4dfca2ff2c> | 2008-02-05 20:36:19 +0000 |
---|---|---|
committer | tobigun <tobigun@b956fd51-792f-4845-bead-9b4dfca2ff2c> | 2008-02-05 20:36:19 +0000 |
commit | dee94f5dae9e6b5ae6c7b54a12a567745abc8dc3 (patch) | |
tree | 21767870a9f01fe8df91fd3ce5331e2fe89862fc /Game/Code | |
parent | 2e6592ceadb3e3c910164c76595e7ae435b8823a (diff) | |
download | usdx-dee94f5dae9e6b5ae6c7b54a12a567745abc8dc3.tar.gz usdx-dee94f5dae9e6b5ae6c7b54a12a567745abc8dc3.tar.xz usdx-dee94f5dae9e6b5ae6c7b54a12a567745abc8dc3.zip |
General:
- cleanup and adaption of SingDrawOscilloscope
Portaudio/SDL audio output:
- stuttering in portaudio output has been fixed (SDL_MixBuffers cannot be used
without initializing the SDL audio stuff first, so it is not usable with portaudio.
Now SDL is used for audio-output instead of portaudio (although the file-name is
UAudioPlayback_Portaudio.pas at the moment).
- cleaner file closing
- volume adjustment
UMusic:
- cleanup of the audio-interfaces
- introduced TNoteType = (ntFreestyle, ntNormal, ntGolden)
- some bug-fixes
- introduced TSoundLibrary. This is library for all in-game sounds used
by USDX. Instead of calling AudioPlayer.PlaySwoosh you should call
AudioPlayer.PlaySound(SoundLib.Swoosh) now. You might call SoundLib.Swoosh.Play
too, but this is not recommended at the moment because SoundLib.Swoosh could be nil
if the file was not found.
The SoundLibrary approach is much cleaner than the previous one. The AudioPlayer does
not have to specify a Play... and Stop... method for every available sound anymore.
In addition it is not an AudioPlayers responsibility to init the in-game sounds.
URecord:
- polish to english translation of some variables
- CaptureSoundLeft/Right is CaptureChannel[0/1] now
- TSoundCardInput -> TAudioInputDeviceSource
- TGenericSoundCard.Input -> TGenericSoundCard.Source
- autocorrelation algorithm more readable now
- Clean-up of the audio-input interface
- moved cloned code of the input-classes to one base class (TAudioInputBase)
- Cleaner finalization
- Start-/StopCapture will not crash anymore in the recording-options menu
- Fixed several bugs in the autocorrelation stuff (e.g. wrong usage of $10000)
- SzczytJest (now ToneValid) was not used correctly. ToneValid is set to true if
a valid tone was found (= the sound was louder than the threshold -> no background noise).
If i remember correctly the sound was accepted although the tone was invalid. So the old
data was used although noone was singing. This resulted in some sort of ghost-singer effect.
UIni:
- moved TIni.Card to TScreenOptionsRecord.Card because it is not stored in the ini-file and will not be in the future.
- TIni.CardList ist now TIni.InputDeviceConfig. The name cardlist was misleading because it just specifies input- but no output-devices. In addition a soundcard can have multiple input-devices (at least in linux).
- bugfix on InputDeviceConfig (formerly CardList) usage. USDX expected that the indices of the corresponding elements in TIni.InputDeviceConfig[] and TAudioInputProcessor.Device[] were the same. This is wrong. If device 2 was defined at first place in the ini and device 1 at the second, the indices of the two arrays didn't match (they were swapped) erroneously. To fix this and to support the item listed below the index to TIni.InputDeviceConfig[] is now stored in TAudioInputDevice.CfgIndex.
NOTE: InputDeviceConfig[] contains configurations of non-available (unplugged) devices. Iterate over TAudioInputProcessor.Device[] for available devices.
- configurations of external devices that are not plugged in will not be deleted anymore.
- multiple definitions of one device in the ini-file will not crash USDX anymore
- CardList[I].ChannelL/R now are InputDeviceConfig[I].ChannelToPlayerMap[0/1]. I think the new name is more intuitive because it maps a channel to a player number. Now the both vars are joint to one array. Now it is possible to use loops to process them and we might support more than two input channels on one device in the future (if such devices exist)
git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@827 b956fd51-792f-4845-bead-9b4dfca2ff2c
Diffstat (limited to '')
39 files changed, 4771 insertions, 4684 deletions
diff --git a/Game/Code/Classes/UAudioDecoder_FFMpeg.pas b/Game/Code/Classes/UAudioDecoder_FFMpeg.pas index c705d603..646e9eef 100644 --- a/Game/Code/Classes/UAudioDecoder_FFMpeg.pas +++ b/Game/Code/Classes/UAudioDecoder_FFMpeg.pas @@ -17,36 +17,33 @@ interface {$MODE Delphi} {$ENDIF} -{$I switches.inc} - - -uses Classes, - {$IFDEF win32} - windows, - {$ENDIF} - SysUtils, - SDL, - avcodec, // FFMpeg Audio file decoding - avformat, - avutil, - avio, // used for url_ferror - mathematics, // used for av_rescale_q - ULog, - UMusic; +{$I ../switches.inc} + + +uses + Classes, + {$IFDEF win32} + windows, + {$ENDIF} + SysUtils, + UMusic; implementation uses - {$IFDEF LAZARUS} - lclintf, - {$ifndef win32} - libc, - {$endif} - {$ENDIF} - UIni, - UMain, - UThemes, - UConfig; + {$ifndef win32} + libc, + {$endif} + UIni, + UMain, + avcodec, // FFMpeg Audio file decoding + avformat, + avutil, + avio, // used for url_ferror + mathematics, // used for av_rescale_q + SDL, + ULog, + UConfig; type @@ -106,12 +103,12 @@ type ffmpegStreamIndex : Integer; ffmpegStream : PAVStream; - // "static" vars for DecodeFrame + // state-vars for DecodeFrame pkt : TAVPacket; audio_pkt_data : PChar; audio_pkt_size : integer; - // "static" vars for AudioCallback + // state-vars for AudioCallback audio_buf_index : cardinal; audio_buf_size : cardinal; audio_buf : TAudioBuffer; @@ -127,8 +124,7 @@ type procedure Close(); override; function GetLength(): real; override; - function GetChannelCount(): cardinal; override; - function GetSampleRate(): cardinal; override; + function GetAudioFormatInfo(): TAudioFormatInfo; override; function GetPosition: real; override; procedure SetPosition(Time: real); override; function IsEOF(): boolean; override; @@ -169,7 +165,7 @@ begin audio_buf_index := 0; audio_buf_size := 0; - FillChar(pkt, sizeof(TAVPacket), #0); + FillChar(pkt, sizeof(TAVPacket), 0); Self.pFormatCtx := pFormatCtx; Self.pCodecCtx := pCodecCtx; @@ -221,14 +217,12 @@ begin result := pFormatCtx^.duration / AV_TIME_BASE; end; -function TFFMpegDecodeStream.GetChannelCount(): cardinal; -begin - result := pCodecCtx^.channels; -end; - -function TFFMpegDecodeStream.GetSampleRate(): cardinal; +function TFFMpegDecodeStream.GetAudioFormatInfo(): TAudioFormatInfo; begin - result := pCodecCtx^.sample_rate; + result.Channels := pCodecCtx^.channels; + result.SampleRate := pCodecCtx^.sample_rate; + //result.Format := pCodecCtx^.sample_fmt; // sample_fmt not yet used by FFMpeg + result.Format := asfS16; // use FFMpeg's standard format end; function TFFMpegDecodeStream.IsEOF(): boolean; @@ -260,7 +254,7 @@ begin SDL_mutexP(lock); seekPos := Trunc(Time * AV_TIME_BASE); // FIXME: seek_flags = rel < 0 ? AVSEEK_FLAG_BACKWARD : 0 - seekFlags := 0; + seekFlags := 0;//AVSEEK_FLAG_BACKWARD; seekRequest := true; SDL_CondSignal(resumeCond); SDL_mutexV(lock); @@ -279,9 +273,9 @@ begin while (true) do begin + //SafeWriteLn('Hallo'); SDL_mutexP(stream.lock); - // wait if end-of-file reached if (eofState) then begin @@ -309,18 +303,19 @@ begin // TODO: Do we need this? // The position is converted to AV_TIME_BASE and then to the stream-specific base. // Why not convert to the stream-specific one from the beginning. - seekTarget := av_rescale_q(stream.seekPos, AV_TIME_BASE_Q, stream.ffmpegStream^.time_base);
- if(av_seek_frame(stream.pFormatCtx, stream.ffmpegStreamIndex,
- seekTarget, stream.seekFlags) = 0) then
- begin
- Log.LogStatus(stream.pFormatCtx^.filename + ': error while seeking', 'UAudioDecoder_FFMpeg');
- end
- else
- begin
- stream.packetQueue.Flush();
- stream.packetQueue.Put(@FlushPacket);
- end;
- stream.seekRequest := false;
+ seekTarget := av_rescale_q(stream.seekPos, AV_TIME_BASE_Q, stream.ffmpegStream^.time_base); + if(av_seek_frame(stream.pFormatCtx, stream.ffmpegStreamIndex, + seekTarget, stream.seekFlags) < 0) then + begin + // this will crash in FPC due to a bug + //Log.LogStatus({stream.pFormatCtx^.filename +} ': error while seeking', 'UAudioDecoder_FFMpeg'); + end + else + begin + stream.packetQueue.Flush(); + stream.packetQueue.Put(@FlushPacket); + end; + stream.seekRequest := false; end; SDL_mutexV(stream.lock); @@ -340,8 +335,10 @@ begin {$ELSE} pbIOCtx := @stream.pFormatCtx^.pb; {$IFEND} + if(url_feof(pbIOCtx) <> 0) then begin + SafeWriteLn('feof'); eofState := true; continue; end; @@ -349,24 +346,25 @@ begin // check for errors if(url_ferror(pbIOCtx) = 0) then begin + SafeWriteLn('Errorf'); // no error -> wait for user input - SDL_Delay(100);
- continue;
- end
- else
- begin
- // an error occured -> abort
- // TODO: eof or quit?
- eofState := true;
- continue;
- end;
- end;
- - //writeln( 'ffmpeg - av_read_frame' ); + SDL_Delay(100); + continue; + end + else + begin + // an error occured -> abort + // TODO: eof or quit? + eofState := true; + continue; + end; + end; + + //SafeWriteLn( 'ffmpeg - av_read_frame' ); if(packet.stream_index = stream.ffmpegStreamIndex) then begin - //writeln( 'packet_queue_put' ); + //SafeWriteLn( 'packet_queue_put' ); stream.packetQueue.put(@packet); end else @@ -375,7 +373,7 @@ begin end; end; - //Writeln('Done: ' + inttostr(stream.packetQueue.nbPackets)); + SafeWriteLn('Done: ' + inttostr(stream.packetQueue.nbPackets)); result := 0; end; @@ -394,21 +392,25 @@ begin begin while (audio_pkt_size > 0) do begin - //writeln( 'got audio packet' ); + //SafeWriteLn( 'got audio packet' ); data_size := bufSize; - // TODO: should be avcodec_decode_audio2 but this wont link on my ubuntu box. + {$IF LIBAVCODEC_VERSION >= 51030000} // 51.30.0 + len1 := avcodec_decode_audio2(pCodecCtx, @buffer, + data_size, audio_pkt_data, audio_pkt_size); + {$ELSE} // FIXME: with avcodec_decode_audio a package could contain several frames // this is not handled yet len1 := avcodec_decode_audio(pCodecCtx, @buffer, data_size, audio_pkt_data, audio_pkt_size); + {$IFEND} - //writeln('avcodec_decode_audio : ' + inttostr( len1 )); + //SafeWriteLn('avcodec_decode_audio : ' + inttostr( len1 )); if(len1 < 0) then begin - // if error, skip frame - //writeln( 'Skip audio frame' ); + // if error, skip frame + SafeWriteLn( 'Skip audio frame' ); audio_pkt_size := 0; break; end; @@ -444,6 +446,7 @@ begin if (audio_pkt_data = PChar(FlushPacket.data)) then begin avcodec_flush_buffers(pCodecCtx); + SafeWriteLn('Flush'); continue; end; @@ -452,11 +455,12 @@ begin begin // end-of-file reached -> set EOF-flag SetEOF(true); + SafeWriteLn('EOF'); // note: buffer is not (even partially) filled -> no data to return exit; end; - //writeln( 'Audio Packet Size - ' + inttostr(audio_pkt_size) ); + //SafeWriteLn( 'Audio Packet Size - ' + inttostr(audio_pkt_size) ); end; end; @@ -480,14 +484,14 @@ begin begin // We have already sent all our data; get more audio_size := DecodeFrame(audio_buf, sizeof(TAudioBuffer)); - //writeln('audio_decode_frame : '+ inttostr(audio_size)); + //SafeWriteLn('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' ); + //SafeWriteLn( 'Silence' ); end else begin @@ -531,11 +535,11 @@ begin // init end-of-file package av_init_packet(EOFPacket); - EOFPacket.data := Pointer(PChar('EOF'));
+ EOFPacket.data := Pointer(PChar('EOF')); // init flush package av_init_packet(FlushPacket); - FlushPacket.data := Pointer(PChar('FLUSH'));
+ FlushPacket.data := Pointer(PChar('FLUSH')); result := true; end; @@ -611,7 +615,7 @@ begin end; avcodec_open(pCodecCtx, pCodec); - //writeln( 'Opened the codec' ); + //WriteLn( 'Opened the codec' ); stream := TFFMpegDecodeStream.Create(pFormatCtx, pCodecCtx, pCodec, ffmpegStreamID, ffmpegStream); @@ -671,7 +675,7 @@ begin Self.lastPkt := pkt1; inc(Self.nbPackets); - //Writeln('Put: ' + inttostr(nbPackets)); + //SafeWriteLn('Put: ' + inttostr(nbPackets)); Self.size := Self.size + pkt1^.pkt.size; SDL_CondSignal(Self.cond); @@ -705,7 +709,7 @@ begin Self.lastPkt := nil; dec(Self.nbPackets); - //Writeln('Get: ' + inttostr(nbPackets)); + //SafeWriteLn('Get: ' + inttostr(nbPackets)); Self.size := Self.size - pkt1^.pkt.size; pkt := pkt1^.pkt; @@ -734,22 +738,23 @@ procedure TPacketQueue.Flush(); var pkt, pkt1: PAVPacketList; begin - SDL_LockMutex(Self.mutex);
-
- pkt := Self.firstPkt;
- while(pkt <> nil) do
- begin
- pkt1 := pkt^.next;
- av_free_packet(@pkt^.pkt);
- av_freep(pkt);
- pkt := pkt1;
- end;
- Self.lastPkt := nil;
- Self.firstPkt := nil;
- Self.nbPackets := 0;
- Self.size := 0;
-
- SDL_UnlockMutex(Self.mutex);
+ SDL_LockMutex(Self.mutex); + + pkt := Self.firstPkt; + while(pkt <> nil) do + begin + pkt1 := pkt^.next; + av_free_packet(@pkt^.pkt); + // Note: param must be a pointer to a pointer! + av_freep(@pkt); + pkt := pkt1; + end; + Self.lastPkt := nil; + Self.firstPkt := nil; + Self.nbPackets := 0; + Self.size := 0; + + SDL_UnlockMutex(Self.mutex); end; diff --git a/Game/Code/Classes/UAudioInput_Bass.pas b/Game/Code/Classes/UAudioInput_Bass.pas index 75a5aee5..6d661258 100644 --- a/Game/Code/Classes/UAudioInput_Bass.pas +++ b/Game/Code/Classes/UAudioInput_Bass.pas @@ -1,287 +1,203 @@ -unit UAudioInput_Bass; - -interface - -{$IFDEF FPC} - {$MODE Delphi} -{$ENDIF} - -{$I switches.inc} - - -uses Classes, - {$IFDEF win32} - windows, - {$ENDIF} - SysUtils, - bass, - ULog, - UMusic; - -implementation - -uses - {$IFDEF LAZARUS} - lclintf, - {$ENDIF} - URecord, - UIni, - UMain, - UCommon, - UThemes; - -type - TAudioInput_Bass = class( TInterfacedObject, IAudioInput) - private - public - function GetName: String; - - {IAudioInput interface} - procedure InitializeRecord; - - procedure CaptureStart; - procedure CaptureStop; - procedure CaptureCard(Card: byte; CaptureSoundLeft, CaptureSoundRight: TSound); - procedure StopCard(Card: byte); - end; - - TBassSoundCard = class(TGenericSoundCard) - RecordStream: HSTREAM; - end; - -var - singleton_AudioInputBass : IAudioInput; - - -function TAudioInput_Bass.GetName: String; -begin - result := 'BASS_Input'; -end; - -procedure TAudioInput_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 (AudioInputProcessor.SoundCard[I].Description = Desc) then - begin - Result := True; - Break; - end; - end; -end; - -begin - with AudioInputProcessor 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 TAudioInput_Bass.CaptureStart; -var - S: integer; - SC: integer; - PlayerLeft, PlayerRight: integer; - CaptureSoundLeft, CaptureSoundRight: TSound; -begin - for S := 0 to High(AudioInputProcessor.Sound) do - AudioInputProcessor.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 := AudioInputProcessor.Sound[PlayerLeft] - else - CaptureSoundLeft := nil; - if (PlayerRight > -1) then - CaptureSoundRight := AudioInputProcessor.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 TAudioInput_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 - AudioInputProcessor.HandleMicrophoneData(buffer, len, AudioInputProcessor.SoundCard[Card]); - Result := true; -end; - -{* - * Start input-capturing on Soundcard specified by Card. - * Params: - * Card - soundcard index in AudioInputProcessor.SoundCard array - * CaptureSoundLeft - sound(-buffer) used for left channel capture data - * CaptureSoundRight - sound(-buffer) used for right channel capture data - *} -procedure TAudioInput_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(AudioInputProcessor.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 AudioInputProcessor.SoundCard array - *} -procedure TAudioInput_Bass.StopCard(Card: byte); -begin - BASS_RecordSetDevice(Card); - BASS_RecordFree; -end; - - -initialization - singleton_AudioInputBass := TAudioInput_Bass.create(); - AudioManager.add( singleton_AudioInputBass ); - -finalization - AudioManager.Remove( singleton_AudioInputBass ); - -end. +unit UAudioInput_Bass;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+
+uses
+ Classes,
+ SysUtils,
+ URecord,
+ UMusic;
+
+implementation
+
+uses
+ UMain,
+ UIni,
+ ULog,
+ UAudioCore_Bass,
+ Windows,
+ bass;
+
+type
+ TAudioInput_Bass = class(TAudioInputBase)
+ public
+ function GetName: String; override;
+ function InitializeRecord: boolean; override;
+ destructor Destroy; override;
+ end;
+
+ TBassInputDevice = class(TAudioInputDevice)
+ public
+ DeviceIndex: integer; // index in TAudioInputProcessor.Device[]
+ BassDeviceID: integer; // DeviceID used by BASS
+ RecordStream: HSTREAM;
+
+ procedure Start(); override;
+ procedure Stop(); override;
+ end;
+
+var
+ singleton_AudioInputBass : IAudioInput;
+
+
+{ Global }
+
+{*
+ * 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
+ AudioInputProcessor.HandleMicrophoneData(buffer, len,
+ AudioInputProcessor.Device[Card]);
+ Result := true;
+end;
+
+
+{ TBassInputDevice }
+
+{*
+ * Start input-capturing on this device.
+ * TODO: call BASS_RecordInit only once
+ *}
+procedure TBassInputDevice.Start();
+const
+ captureFreq = 44100;
+begin
+ // recording already started -> stop first
+ if (RecordStream <> 0) then
+ Stop();
+
+ // TODO: Call once. Otherwise it's to slow
+ if not BASS_RecordInit(BassDeviceID) then
+ begin
+ Log.LogError('TBassInputDevice.Start: Error initializing device['+IntToStr(DeviceIndex)+']: ' +
+ TAudioCore_Bass.ErrorGetString());
+ Exit;
+ end;
+
+ SampleRate := captureFreq;
+
+ // capture in 44.1kHz/stereo/16bit and a 20ms callback period
+ RecordStream := BASS_RecordStart(captureFreq, 2, MakeLong(0, 20),
+ @MicrophoneCallback, DeviceIndex);
+ if (RecordStream = 0) then
+ begin
+ BASS_RecordFree;
+ Exit;
+ end;
+end;
+
+{*
+ * Stop input-capturing on this device.
+ *}
+procedure TBassInputDevice.Stop();
+begin
+ if (RecordStream = 0) then
+ Exit;
+ // TODO: Don't free the device. Do this on close
+ if (BASS_RecordSetDevice(BassDeviceID)) then
+ BASS_RecordFree;
+ RecordStream := 0;
+end;
+
+
+{ TAudioInput_Bass }
+
+function TAudioInput_Bass.GetName: String;
+begin
+ result := 'BASS_Input';
+end;
+
+function TAudioInput_Bass.InitializeRecord(): boolean;
+var
+ Descr: PChar;
+ SourceName: PChar;
+ Flags: integer;
+ BassDeviceID: integer;
+ BassDevice: TBassInputDevice;
+ DeviceIndex: integer;
+ SourceIndex: integer;
+begin
+ result := false;
+
+ DeviceIndex := 0;
+ BassDeviceID := 0;
+ SetLength(AudioInputProcessor.Device, 0);
+
+ // checks for recording devices and puts them into an array
+ while true do
+ begin
+ Descr := BASS_RecordGetDeviceDescription(BassDeviceID);
+ if (Descr = nil) then
+ break;
+
+ SetLength(AudioInputProcessor.Device, DeviceIndex+1);
+
+ // TODO: free object on termination
+ BassDevice := TBassInputDevice.Create();
+ AudioInputProcessor.Device[DeviceIndex] := BassDevice;
+
+ BassDevice.DeviceIndex := DeviceIndex;
+ BassDevice.BassDeviceID := BassDeviceID;
+ BassDevice.Description := UnifyDeviceName(Descr, DeviceIndex);
+
+ // get input sources
+ SourceIndex := 0;
+ BASS_RecordInit(BassDeviceID);
+ BassDevice.MicInput := 0;
+
+ // process each input
+ while true do
+ begin
+ SourceName := BASS_RecordGetInputName(SourceIndex);
+ if (SourceName = nil) then
+ break;
+
+ SetLength(BassDevice.Source, SourceIndex+1);
+ BassDevice.Source[SourceIndex].Name :=
+ UnifyDeviceSourceName(SourceName, BassDevice.Description);
+
+ // set mic index
+ Flags := BASS_RecordGetInput(SourceIndex);
+ if ((Flags and BASS_INPUT_TYPE_MIC) <> 0) then
+ BassDevice.MicInput := SourceIndex;
+
+ Inc(SourceIndex);
+ end;
+
+ BASS_RecordFree;
+
+ Inc(DeviceIndex);
+ Inc(BassDeviceID);
+ end;
+
+ result := true;
+end;
+
+destructor TAudioInput_Bass.Destroy;
+begin
+ inherited;
+end;
+
+
+initialization
+ singleton_AudioInputBass := TAudioInput_Bass.create();
+ AudioManager.add( singleton_AudioInputBass );
+
+finalization
+ AudioManager.Remove( singleton_AudioInputBass );
+
+end.
diff --git a/Game/Code/Classes/UAudioInput_Portaudio.pas b/Game/Code/Classes/UAudioInput_Portaudio.pas index 8073a7f3..c969a1b3 100644 --- a/Game/Code/Classes/UAudioInput_Portaudio.pas +++ b/Game/Code/Classes/UAudioInput_Portaudio.pas @@ -6,60 +6,43 @@ interface {$MODE Delphi} {$ENDIF} -{$I switches.inc} +{$I ../switches.inc} -uses Classes, - SysUtils, - portaudio, - {$IFDEF UsePortmixer} - portmixer, - {$ENDIF} - ULog, - UMusic; +uses + Classes, + SysUtils, + 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; -} + URecord, + UIni, + ULog, + UMain, + {$IFDEF UsePortmixer} + portmixer, + {$ENDIF} + portaudio; + type - TAudioInput_Portaudio = class( TInterfacedObject, IAudioInput ) + TAudioInput_Portaudio = class(TAudioInputBase) 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); + function GetName: String; override; + function InitializeRecord: boolean; override; + destructor Destroy; override; end; - TPortaudioSoundCard = class(TGenericSoundCard) - RecordStream: PPaStream; - DeviceIndex: TPaDeviceIndex; + TPortaudioInputDevice = class(TAudioInputDevice) + public + RecordStream: PPaStream; + PaDeviceIndex: TPaDeviceIndex; + + procedure Start(); override; + procedure Stop(); override; end; function MicrophoneCallback(input: Pointer; output: Pointer; frameCount: Longword; @@ -69,9 +52,6 @@ function MicrophoneCallback(input: Pointer; output: Pointer; frameCount: Longwor var singleton_AudioInputPortaudio : 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 @@ -102,6 +82,62 @@ var array[0..0] of TPaHostApiTypeId = ( paDefaultApi ); {$IFEND} + +{ TPortaudioInputDevice } + +procedure TPortaudioInputDevice.Start(); +var + Error: TPaError; + ErrorMsg: string; + inputParams: TPaStreamParameters; + deviceInfo: PPaDeviceInfo; +begin + // get input latency info + deviceInfo := Pa_GetDeviceInfo(PaDeviceIndex); + + // set input stream parameters + with inputParams do begin + device := PaDeviceIndex; + channelCount := 2; + sampleFormat := paInt16; + suggestedLatency := deviceInfo^.defaultLowInputLatency; + hostApiSpecificStreamInfo := nil; + end; + + Log.LogStatus(inttostr(PaDeviceIndex), 'Portaudio'); + Log.LogStatus(floattostr(deviceInfo^.defaultLowInputLatency), 'Portaudio'); + + // open input stream + Error := Pa_OpenStream(RecordStream, @inputParams, nil, SampleRate, + paFramesPerBufferUnspecified, paNoFlag, + @MicrophoneCallback, Pointer(Self)); + if(Error <> paNoError) then begin + ErrorMsg := Pa_GetErrorText(Error); + Log.CriticalError('TPortaudioInputDevice.Start(): Error opening stream: ' + ErrorMsg); + //Halt; + end; + + // start capture + Error := Pa_StartStream(RecordStream); + if(Error <> paNoError) then begin + Pa_CloseStream(RecordStream); + ErrorMsg := Pa_GetErrorText(Error); + Log.CriticalError('TPortaudioInputDevice.Start(): Error starting stream: ' + ErrorMsg); + //Halt; + end; +end; + +procedure TPortaudioInputDevice.Stop(); +begin + if assigned(RecordStream) then begin + Pa_StopStream(RecordStream); + Pa_CloseStream(RecordStream); + end; +end; + + +{ TAudioInput_Portaudio } + function TAudioInput_Portaudio.GetName: String; begin result := 'Portaudio'; @@ -130,8 +166,7 @@ begin end; end; -// TODO: should be a function with boolean return type -procedure TAudioInput_Portaudio.InitializeRecord; +function TAudioInput_Portaudio.InitializeRecord(): boolean; var i: integer; apiIndex: TPaHostApiIndex; @@ -139,37 +174,42 @@ var deviceName: string; deviceIndex: TPaDeviceIndex; deviceInfo: PPaDeviceInfo; - inputCnt: integer; - inputName: string; + sourceCnt: integer; + sourceName: string; SC: integer; // soundcard - SCI: integer; // soundcard input + SCI: integer; // soundcard source err: TPaError; errMsg: string; - paSoundCard: TPortaudioSoundCard; + paDevice: TPortaudioInputDevice; inputParams: TPaStreamParameters; stream: PPaStream; {$IFDEF UsePortmixer} mixer: PPxMixer; {$ENDIF} +const + captureFreq = 44100; begin - // TODO: call Pa_Terminate() on termination + result := false; + + writeln('0'); + err := Pa_Initialize(); if(err <> paNoError) then begin - Log.CriticalError('Portaudio.InitializeRecord: ' + Pa_GetErrorText(err)); - //Log.LogError('Portaudio.InitializeRecord: ' + Pa_GetErrorText(err)); - // result := false; + Log.LogError('Portaudio.InitializeRecord: ' + Pa_GetErrorText(err)); Exit; end; - + writeln('1'); apiIndex := GetPreferredApiIndex(); apiInfo := Pa_GetHostApiInfo(apiIndex); SC := 0; + writeln('2'); // init array-size to max. input-devices count - SetLength(AudioInputProcessor.SoundCard, apiInfo^.deviceCount); // fix deviceCountL - for i:= 0 to High(AudioInputProcessor.SoundCard) do + SetLength(AudioInputProcessor.Device, apiInfo^.deviceCount); + for i:= 0 to High(AudioInputProcessor.Device) do begin + writeln('25'); // convert API-specific device-index to global index deviceIndex := Pa_HostApiDeviceIndexToDeviceIndex(apiIndex, i); deviceInfo := Pa_GetDeviceInfo(deviceIndex); @@ -178,14 +218,13 @@ begin if(deviceInfo^.maxInputChannels <= 0) then continue; - // TODO: free object on termination - paSoundCard := TPortaudioSoundCard.Create(); - AudioInputProcessor.SoundCard[SC] := paSoundCard; + paDevice := TPortaudioInputDevice.Create(); + AudioInputProcessor.Device[SC] := paDevice; // retrieve device-name deviceName := deviceInfo^.name; - paSoundCard.Description := deviceName; - paSoundCard.DeviceIndex := deviceIndex; + paDevice.Description := deviceName; + paDevice.PaDeviceIndex := deviceIndex; // setup desired input parameters with inputParams do begin @@ -196,29 +235,32 @@ begin hostApiSpecificStreamInfo := nil; end; + paDevice.SampleRate := captureFreq; + // check if device supports our input-format - err := Pa_IsFormatSupported(@inputParams, nil, sampleRate); + err := Pa_IsFormatSupported(@inputParams, nil, paDevice.SampleRate); if(err <> 0) then begin // format not supported -> skip errMsg := Pa_GetErrorText(err); Log.LogError('Portaudio.InitializeRecord, device: "'+ deviceName +'" ' + '('+ errMsg +')'); - paSoundCard.Free(); + paDevice.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) + // use TPaDeviceInfo.defaultSampleRate - err := Pa_OpenStream(stream, @inputParams, nil, sampleRate, + err := Pa_OpenStream(stream, @inputParams, nil, paDevice.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(); + paDevice.Free(); continue; end; @@ -229,14 +271,14 @@ begin mixer := Px_OpenMixer(stream, 0); // get input count - inputCnt := Px_GetNumInputSources(mixer); - SetLength(paSoundCard.Input, inputCnt); + sourceCnt := Px_GetNumInputSources(mixer); + SetLength(paDevice.Source, sourceCnt); // get input names - for SCI := 0 to inputCnt-1 do + for SCI := 0 to sourceCnt-1 do begin - inputName := Px_GetInputSourceName(mixer, SCI); - paSoundCard.Input[SCI].Name := inputName; + sourceName := Px_GetInputSourceName(mixer, SCI); + paDevice.Source[SCI].Name := sourceName; end; Px_CloseMixer(mixer); @@ -247,80 +289,46 @@ begin // 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'; + SetLength(paDevice.Source, 1); + paDevice.Source[0].Name := 'Standard'; {$ENDIF} + // close test-stream + Pa_CloseStream(stream); + // use default input source - paSoundCard.InputSelected := 0; + paDevice.SourceSelected := 0; Inc(SC); end; + writeln('3'); // adjust size to actual input-device count - SetLength(AudioInputProcessor.SoundCard, SC); + SetLength(AudioInputProcessor.Device, SC); Log.LogStatus('#Soundcards: ' + inttostr(SC), 'Portaudio'); { SoundCard[SC].InputSelected := Mic[Device]; } + result := true; end; -// TODO: code is used by all IAudioInput implementors -// -> move to a common superclass (TAudioInput_Generic?) -procedure TAudioInput_Portaudio.CaptureStart; -var - S: integer; - SC: integer; - PlayerLeft, PlayerRight: integer; - CaptureSoundLeft, CaptureSoundRight: TSound; -begin - for S := 0 to High(AudioInputProcessor.Sound) do - AudioInputProcessor.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 := AudioInputProcessor.Sound[PlayerLeft] - else - CaptureSoundLeft := nil; - if (PlayerRight > -1) then - CaptureSoundRight := AudioInputProcessor.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 TAudioInput_Portaudio.CaptureStop; +destructor TAudioInput_Portaudio.Destroy; var - SC: integer; - PlayerLeft: integer; - PlayerRight: integer; + i: integer; + paSoundCard: TPortaudioInputDevice; 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); + Pa_Terminate(); + for i := 0 to High(AudioInputProcessor.Device) do + begin + AudioInputProcessor.Device[i].Free(); end; + AudioInputProcessor.Device := nil; + inherited Destroy; end; {* @@ -334,81 +342,6 @@ begin 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 TAudioInput_Portaudio.CaptureCard(Card: byte; CaptureSoundLeft, CaptureSoundRight: TSound); -var - Error: TPaError; - ErrorMsg: string; - inputParams: TPaStreamParameters; - deviceInfo: PPaDeviceInfo; - stream: PPaStream; - paSoundCard: TPortaudioSoundCard; -begin - paSoundCard := TPortaudioSoundCard(AudioInputProcessor.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 TAudioInput_Portaudio.StopCard(Card: byte); -var - stream: PPaStream; - paSoundCard: TPortaudioSoundCard; -begin - paSoundCard := TPortaudioSoundCard(AudioInputProcessor.SoundCard[Card]); - stream := paSoundCard.RecordStream; - if(stream <> nil) then begin - Pa_StopStream(stream); - Pa_CloseStream(stream); - end; -end; - initialization singleton_AudioInputPortaudio := TAudioInput_Portaudio.create(); diff --git a/Game/Code/Classes/UAudioPlayback_Bass.pas b/Game/Code/Classes/UAudioPlayback_Bass.pas index 87ff183d..266a5ec3 100644 --- a/Game/Code/Classes/UAudioPlayback_Bass.pas +++ b/Game/Code/Classes/UAudioPlayback_Bass.pas @@ -9,35 +9,31 @@ interface {$I switches.inc} -uses Classes, - {$IFDEF win32} - windows, - {$ENDIF} - SysUtils, - bass, - ULog, - UMusic; +uses + Classes, + SysUtils, + UMusic; implementation uses - {$IFDEF LAZARUS} - lclintf, - {$ENDIF} - URecord, - UIni, - UMain, - UCommon, - UThemes; + UIni, + UMain, + ULog, + UAudioCore_Bass, + bass; type - TBassOutputStream = class(TAudioPlaybackStream) + TBassPlaybackStream = class(TAudioPlaybackStream) private Handle: HSTREAM; + Loop: boolean; public constructor Create(); overload; constructor Create(stream: HSTREAM); overload; + procedure Reset(); + procedure Play(); override; procedure Pause(); override; procedure Stop(); override; @@ -46,41 +42,33 @@ type procedure SetLoop(Enabled: boolean); override; function GetLength(): real; override; function GetStatus(): TStreamStatus; override; + function GetVolume(): integer; override; + procedure SetVolume(volume: integer); override; + + function GetPosition: real; + procedure SetPosition(Time: real); + + function IsLoaded(): boolean; end; type TAudioPlayback_Bass = class( TInterfacedObject, IAudioPlayback) 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; + MusicStream: TBassPlaybackStream; + function Load(Filename: string): TBassPlaybackStream; public function GetName: String; {IAudioOutput interface} - procedure InitializePlayback; + function InitializePlayback(): boolean; procedure SetVolume(Volume: integer); procedure SetMusicVolume(Volume: integer); procedure SetLoop(Enabled: boolean); - function Open(Name: string): boolean; // true if succeed - + function Open(Filename: string): boolean; // true if succeed + procedure Rewind; procedure Play; procedure Pause; //Pause Mod @@ -91,79 +79,106 @@ type function GetPosition: real; procedure SetPosition(Time: 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; + procedure GetFFTData(var data: TFFTData); // Interface for Visualizer function GetPCMData(var data: TPCMData): Cardinal; - //Custom Sounds - function LoadCustomSound(const Filename: String): Cardinal; - procedure PlayCustomSound(const Index: Cardinal ); + // Sounds + function OpenSound(const Filename: String): TAudioPlaybackStream; + procedure PlaySound(stream: TAudioPlaybackStream);
+ procedure StopSound(stream: TAudioPlaybackStream); end; var singleton_AudioPlaybackBass : IAudioPlayback; -constructor TBassOutputStream.Create(); +constructor TBassPlaybackStream.Create(); begin inherited; + Reset(); end; -constructor TBassOutputStream.Create(stream: HSTREAM); +constructor TBassPlaybackStream.Create(stream: HSTREAM); begin Create(); Handle := stream; end; -procedure TBassOutputStream.Play(); +procedure TBassPlaybackStream.Reset(); +begin + Loop := false; + if (Handle <> 0) then + Bass_StreamFree(Handle); + Handle := 0; +end; + +procedure TBassPlaybackStream.Play(); begin - BASS_ChannelPlay(Handle, True); + BASS_ChannelPlay(Handle, Loop); end; -procedure TBassOutputStream.Pause(); +procedure TBassPlaybackStream.Pause(); begin - //if (Loaded) then BASS_ChannelPause(Handle); end; -procedure TBassOutputStream.Stop(); +procedure TBassPlaybackStream.Stop(); begin BASS_ChannelStop(Handle); end; -procedure TBassOutputStream.Close(); +procedure TBassPlaybackStream.Close(); begin - Bass_StreamFree(Handle); + Reset(); end; -function TBassOutputStream.GetLoop(): boolean; +function TBassPlaybackStream.GetVolume(): integer; begin - // TODO - result := false; + Result := 0; + BASS_ChannelSetAttributes(Handle, PInteger(nil)^, Result, PInteger(nil)^); +end; + +procedure TBassPlaybackStream.SetVolume(volume: integer); +begin + // clamp volume + if volume < 0 then + volume := 0; + if volume > 100 then + volume := 100; + // set volume + BASS_ChannelSetAttributes(Handle, -1, volume, -101); end; -procedure TBassOutputStream.SetLoop(Enabled: boolean); +function TBassPlaybackStream.GetPosition: real; +var + bytes: integer; +begin + bytes := BASS_ChannelGetPosition(Handle); + Result := BASS_ChannelBytes2Seconds(Handle, bytes); +end; + +procedure TBassPlaybackStream.SetPosition(Time: real); +var + bytes: integer; begin - // TODO + bytes := BASS_ChannelSeconds2Bytes(Handle, Time); + BASS_ChannelSetPosition(Handle, bytes); end; -function TBassOutputStream.GetLength(): real; +function TBassPlaybackStream.GetLoop(): boolean; +begin + result := Loop; +end; + +procedure TBassPlaybackStream.SetLoop(Enabled: boolean); +begin + Loop := Enabled; +end; + +function TBassPlaybackStream.GetLength(): real; var bytes: integer; begin @@ -171,37 +186,45 @@ begin Result := BASS_ChannelBytes2Seconds(Handle, bytes); end; -function TBassOutputStream.GetStatus(): TStreamStatus; +function TBassPlaybackStream.GetStatus(): TStreamStatus; var state: DWORD; begin state := BASS_ChannelIsActive(Handle); case state of BASS_ACTIVE_PLAYING: - result := sPlaying; + result := ssPlaying; BASS_ACTIVE_PAUSED: - result := sPaused; + result := ssPaused; + BASS_ACTIVE_STALLED: + result := ssBlocked; + BASS_ACTIVE_STOPPED: + result := ssStopped; else - result := sStopped; + result := ssUnknown; end; end; +function TBassPlaybackStream.IsLoaded(): boolean; +begin + Result := (Handle <> 0); +end; + function TAudioPlayback_Bass.GetName: String; begin result := 'BASS_Playback'; end; -procedure TAudioPlayback_Bass.InitializePlayback; +function TAudioPlayback_Bass.InitializePlayback(): boolean; var Pet: integer; S: integer; begin -// Log.BenchmarkStart(4); -// Log.LogStatus('Initializing Playback Subsystem', 'Music Initialize'); + result := false; - Loaded := false; - Loop := false; + //Log.BenchmarkStart(4); + //Log.LogStatus('Initializing Playback Subsystem', 'Music Initialize'); if not BASS_Init(1, 44100, 0, 0, nil) then begin @@ -209,30 +232,32 @@ begin Exit; end; -// Log.BenchmarkEnd(4); Log.LogBenchmark('--> Bass Init', 4); + //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'); + //BASS_SetConfig(BASS_CONFIG_UPDATEPERIOD, 10); + //BASS_SetConfig(BASS_CONFIG_BUFFER, 100); -// 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'); + result := true; +end; -// LoadSoundFromFile(DrumSoundStream, SoundPath + 'bassdrumhard076b.mp3'); -// LoadSoundFromFile(HihatSoundStream, SoundPath + 'hihatclosed068b.mp3'); -// LoadSoundFromFile(ClapSoundStream, SoundPath + 'claps050b.mp3'); +function TAudioPlayback_Bass.Load(Filename: string): TBassPlaybackStream; +var + L: Integer; + stream: HSTREAM; +begin + Result := nil; -// LoadSoundFromFile(ShuffleSoundStream, SoundPath + 'Shuffle.mp3'); + //Log.LogStatus('Loading Sound: "' + Filename + '"', 'LoadSoundFromFile'); + stream := BASS_StreamCreateFile(False, pchar(Filename), 0, 0, 0); + if (stream = 0) then + begin + Log.LogError('Failed to open "' + Filename + '", ' + + TAudioCore_Bass.ErrorGetString(BASS_ErrorGetCode()), 'TAudioPlayback_Bass.Load'); + Exit; + end; -// Log.BenchmarkEnd(4); -// Log.LogBenchmark('--> Loading Sounds', 4); + Result := TBassPlaybackStream.Create(stream); end; procedure TAudioPlayback_Bass.SetVolume(Volume: integer); @@ -240,7 +265,6 @@ 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); @@ -248,193 +272,102 @@ end; procedure TAudioPlayback_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); + if assigned(MusicStream) then + MusicStream.SetVolume(Volume); end; procedure TAudioPlayback_Bass.SetLoop(Enabled: boolean); begin - Loop := Enabled; + if assigned(MusicStream) then + MusicStream.Loop := Enabled; end; -function TAudioPlayback_Bass.Open(Name: string): boolean; +function TAudioPlayback_Bass.Open(Filename: string): boolean; +var + stream: HSTREAM; begin - Loaded := false; - if FileExists(Name) then - begin - MusicStream := Bass_StreamCreateFile(false, pchar(Name), 0, 0, 0); + Result := false; - Loaded := true; - //Set Max Volume - SetMusicVolume (100); - end; + // free old MusicStream + if assigned(MusicStream) then + MusicStream.Free; - Result := Loaded; -end; + MusicStream := Load(Filename); + if not assigned(MusicStream) then + Exit; -procedure TAudioPlayback_Bass.Rewind; -begin - if Loaded then begin - end; + //Set Max Volume + SetMusicVolume(100); + + Result := true; end; -procedure TAudioPlayback_Bass.SetPosition(Time: real); -var - bytes: integer; +procedure TAudioPlayback_Bass.Rewind; begin - bytes := BASS_ChannelSeconds2Bytes(MusicStream, Time); - BASS_ChannelSetPosition(MusicStream, bytes); + SetPosition(0); end; procedure TAudioPlayback_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; + if assigned(MusicStream) then + MusicStream.Play(); end; -procedure TAudioPlayback_Bass.Pause; //Pause Mod +procedure TAudioPlayback_Bass.Pause; begin - if Loaded then begin - BASS_ChannelPause(MusicStream); // Pauses Song - end; + if assigned(MusicStream) then + MusicStream.Pause(); end; procedure TAudioPlayback_Bass.Stop; begin - Bass_ChannelStop(MusicStream); + if assigned(MusicStream) then + MusicStream.Stop(); end; procedure TAudioPlayback_Bass.Close; begin - Bass_StreamFree(MusicStream); + if assigned(MusicStream) then + MusicStream.Close(); end; function TAudioPlayback_Bass.Length: real; var bytes: integer; begin - bytes := BASS_ChannelGetLength(MusicStream); - Result := BASS_ChannelBytes2Seconds(MusicStream, bytes); -end; - -function TAudioPlayback_Bass.getPosition: real; -var - bytes: integer; -begin - bytes := BASS_ChannelGetPosition(MusicStream); - Result := BASS_ChannelBytes2Seconds(MusicStream, bytes); -end; - -function TAudioPlayback_Bass.Finished: boolean; -begin - Result := false; - - if BASS_ChannelIsActive(MusicStream) = BASS_ACTIVE_STOPPED then - begin - Result := true; - end; -end; - -procedure TAudioPlayback_Bass.PlayStart; -begin - BASS_ChannelPlay(StartSoundStream, True); -end; - -procedure TAudioPlayback_Bass.PlayBack; -begin - BASS_ChannelPlay(BackSoundStream, True);// then -end; - -procedure TAudioPlayback_Bass.PlaySwoosh; -begin - BASS_ChannelPlay(SwooshSoundStream, True); -end; - -procedure TAudioPlayback_Bass.PlayChange; -begin - BASS_ChannelPlay(ChangeSoundStream, True); -end; - -procedure TAudioPlayback_Bass.PlayOption; -begin - BASS_ChannelPlay(OptionSoundStream, True); -end; - -procedure TAudioPlayback_Bass.PlayClick; -begin - BASS_ChannelPlay(ClickSoundStream, True); -end; - -procedure TAudioPlayback_Bass.PlayDrum; -begin - BASS_ChannelPlay(DrumSoundStream, True); -end; - -procedure TAudioPlayback_Bass.PlayHihat; -begin - BASS_ChannelPlay(HihatSoundStream, True); -end; - -procedure TAudioPlayback_Bass.PlayClap; -begin - BASS_ChannelPlay(ClapSoundStream, True); + if assigned(MusicStream) then + Result := MusicStream.GetLength() + else + Result := -1; end; -procedure TAudioPlayback_Bass.PlayShuffle; +function TAudioPlayback_Bass.GetPosition: real; begin - BASS_ChannelPlay(ShuffleSoundStream, True); + if assigned(MusicStream) then + Result := MusicStream.GetPosition() + else + Result := -1; end; -procedure TAudioPlayback_Bass.StopShuffle; +procedure TAudioPlayback_Bass.SetPosition(Time: real); begin - BASS_ChannelStop(ShuffleSoundStream); + if assigned(MusicStream) then + MusicStream.SetPosition(Time); end; -function TAudioPlayback_Bass.LoadSoundFromFile(var stream: HSTREAM; Name: string): boolean; -var - L: Integer; +function TAudioPlayback_Bass.Finished: boolean; 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 + if assigned(MusicStream) then + Result := (MusicStream.GetStatus() = ssStopped) else - begin - Log.LogError('Sound not found: "' + Name + '"', 'LoadSoundFromFile'); - exit; - end; + Result := true; end; //Equalizer -function TAudioPlayback_Bass.GetFFTData: TFFTData; -var - Data: TFFTData; +procedure TAudioPlayback_Bass.GetFFTData(var data: TFFTData); begin //Get Channel Data Mono and 256 Values - BASS_ChannelGetData(MusicStream, @Result, BASS_DATA_FFT512); + BASS_ChannelGetData(MusicStream.Handle, @data, BASS_DATA_FFT512); end; {* @@ -447,23 +380,21 @@ var nBytes: DWORD; begin //Get Channel Data Mono and 256 Values - BASS_ChannelGetInfo(MusicStream, info); - ZeroMemory(@data, sizeof(TPCMData)); + BASS_ChannelGetInfo(MusicStream.Handle, info); + FillChar(data, sizeof(TPCMData), 0); if (info.chans = 1) then begin // mono file -> add stereo channel - { - nBytes := BASS_ChannelGetData(Bass, @data[0], samples*sizeof(Smallint)); + nBytes := 0;//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)); + nBytes := BASS_ChannelGetData(MusicStream.Handle, @data, sizeof(TPCMData)); end; if(nBytes <= 0) then result := 0 @@ -471,36 +402,21 @@ begin result := nBytes div sizeof(TPCMStereoSample); end; -function TAudioPlayback_Bass.LoadCustomSound(const Filename: String): Cardinal; -var - S: hStream; - I: Integer; - F: String; +function TAudioPlayback_Bass.OpenSound(const Filename: string): TAudioPlaybackStream; 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; + result := Load(Filename); +end; - if LoadSoundFromFile(S, SoundPath + Filename) then - Result := High(CustomSounds) - else - Result := 0; +procedure TAudioPlayback_Bass.PlaySound(stream: TAudioPlaybackStream); +begin + if assigned(stream) then + stream.Play(); end; -procedure TAudioPlayback_Bass.PlayCustomSound(const Index: Cardinal ); +procedure TAudioPlayback_Bass.StopSound(stream: TAudioPlaybackStream); begin - if Index <= High(CustomSounds) then - with CustomSounds[Index].Stream as TBassOutputStream do - begin - BASS_ChannelPlay(Handle, True); - end; + if assigned(stream) then + stream.Stop(); end; diff --git a/Game/Code/Classes/UAudioPlayback_Portaudio.pas b/Game/Code/Classes/UAudioPlayback_Portaudio.pas index 5f4a8cde..2743fa86 100644 --- a/Game/Code/Classes/UAudioPlayback_Portaudio.pas +++ b/Game/Code/Classes/UAudioPlayback_Portaudio.pas @@ -9,35 +9,40 @@ interface {$I switches.inc} -uses Classes, - SysUtils, - UMusic; +uses + Classes, + SysUtils, + UMusic; implementation uses - {$IFDEF LAZARUS} - lclintf, - {$ifndef win32} - libc, - {$endif} - {$ENDIF} - sdl, - portaudio, - ULog, - UIni, - UMain; + {$IFNDEF Win32} + libc, + {$ENDIF} + sdl, + portaudio, + ULog, + UIni, + UMain; type TPortaudioPlaybackStream = class(TAudioPlaybackStream) private - status: TStreamStatus; - Loaded: boolean; + Status: TStreamStatus; Loop: boolean; + + _volume: integer; + + procedure Reset(); public - decodeStream: TAudioDecodeStream; + DecodeStream: TAudioDecodeStream; + + constructor Create(); + destructor Destroy(); override; + + function SetDecodeStream(decodeStream: TAudioDecodeStream): boolean; - constructor Create(decodeStream: TAudioDecodeStream); procedure Play(); override; procedure Pause(); override; procedure Stop(); override; @@ -49,6 +54,9 @@ type function IsLoaded(): boolean; + function GetVolume(): integer; override; + procedure SetVolume(volume: integer); override; + // functions delegated to the decode stream function GetPosition: real; procedure SetPosition(Time: real); @@ -60,12 +68,23 @@ type private activeStreams: TList; mixerBuffer: PChar; + internalLock: PSDL_Mutex; + + _volume: integer; + + procedure Lock(); inline; + procedure Unlock(); inline; + + function GetVolume(): integer; + procedure SetVolume(volume: integer); public constructor Create(); destructor Destroy(); override; procedure AddStream(stream: TAudioPlaybackStream); procedure RemoveStream(stream: TAudioPlaybackStream); function ReadData(Buffer: PChar; BufSize: integer): integer; + + property Volume: integer READ GetVolume WRITE SetVolume; end; type @@ -73,36 +92,29 @@ type private MusicStream: TPortaudioPlaybackStream; - StartSoundStream: TPortaudioPlaybackStream; - BackSoundStream: TPortaudioPlaybackStream; - SwooshSoundStream: TPortaudioPlaybackStream; - ChangeSoundStream: TPortaudioPlaybackStream; - OptionSoundStream: TPortaudioPlaybackStream; - ClickSoundStream: TPortaudioPlaybackStream; - DrumSoundStream: TPortaudioPlaybackStream; - HihatSoundStream: TPortaudioPlaybackStream; - ClapSoundStream: TPortaudioPlaybackStream; - ShuffleSoundStream: TPortaudioPlaybackStream; - - //Custom Sounds - CustomSounds: array of TCustomSoundEntry; - - mixerStream: TAudioMixerStream; + MixerStream: TAudioMixerStream; paStream: PPaStream; - public - FrameSize: integer; - function GetName: String; + FrameSize: integer; function InitializePortaudio(): boolean; function StartPortaudioStream(): boolean; - procedure InitializePlayback(); + function InitializeSDLAudio(): boolean; + function StartSDLAudioStream(): boolean; + procedure StopSDLAudioStream(); + public + function GetName: String; + + function InitializePlayback(): boolean; + destructor Destroy; override; + + function Load(const Filename: String): TPortaudioPlaybackStream; + procedure SetVolume(Volume: integer); procedure SetMusicVolume(Volume: integer); procedure SetLoop(Enabled: boolean); function Open(Filename: string): boolean; // true if succeed - function Load(Filename: string): TPortaudioPlaybackStream; procedure Rewind; procedure SetPosition(Time: real); procedure Play; @@ -113,27 +125,17 @@ type 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; - - //Equalizer - function GetFFTData: TFFTData; + + // Equalizer + procedure GetFFTData(var data: TFFTData); // Interface for Visualizer function GetPCMData(var data: TPCMData): Cardinal; - //Custom Sounds - function LoadCustomSound(const Filename: String): Cardinal; - procedure PlayCustomSound(const Index: Cardinal ); + // Sounds + function OpenSound(const Filename: String): TAudioPlaybackStream; + procedure PlaySound(stream: TAudioPlaybackStream); + procedure StopSound(stream: TAudioPlaybackStream); end; @@ -150,25 +152,59 @@ var constructor TAudioMixerStream.Create(); begin activeStreams := TList.Create; + internalLock := SDL_CreateMutex(); + _volume := 100; end; destructor TAudioMixerStream.Destroy(); begin - if (mixerBuffer <> nil) then + if assigned(mixerBuffer) then Freemem(mixerBuffer); activeStreams.Free; + SDL_DestroyMutex(internalLock); +end; + +procedure TAudioMixerStream.Lock(); +begin + SDL_mutexP(internalLock); +end; + +procedure TAudioMixerStream.Unlock(); +begin + SDL_mutexV(internalLock); +end; + +function TAudioMixerStream.GetVolume(): integer; +begin + Lock(); + result := _volume; + Unlock(); +end; + +procedure TAudioMixerStream.SetVolume(volume: integer); +begin + Lock(); + _volume := volume; + Unlock(); end; procedure TAudioMixerStream.AddStream(stream: TAudioPlaybackStream); begin + if not assigned(stream) then + Exit; + + Lock(); // check if stream is already in list to avoid duplicates if (activeStreams.IndexOf(Pointer(stream)) = -1) then activeStreams.Add(Pointer(stream)); + Unlock(); end; procedure TAudioMixerStream.RemoveStream(stream: TAudioPlaybackStream); begin + Lock(); activeStreams.Remove(Pointer(stream)); + Unlock(); end; function TAudioMixerStream.ReadData(Buffer: PChar; BufSize: integer): integer; @@ -176,79 +212,111 @@ var i: integer; size: integer; stream: TPortaudioPlaybackStream; + appVolume: single; begin result := BufSize; // zero target-buffer (silence) FillChar(Buffer^, BufSize, 0); - // resize mixer-buffer + // resize mixer-buffer if necessary ReallocMem(mixerBuffer, BufSize); - if (mixerBuffer = nil) then + if not assigned(mixerBuffer) then Exit; - writeln('Mix: ' + inttostr(activeStreams.Count)); + Lock(); + + //writeln('Mix: ' + inttostr(activeStreams.Count)); + + // use _volume instead of Volume to prevent recursive locking + appVolume := _volume / 100 * SDL_MIX_MAXVOLUME; for i := 0 to activeStreams.Count-1 do begin stream := TPortaudioPlaybackStream(activeStreams[i]); - if (stream.GetStatus() = sPlaying) then + if (stream.GetStatus() = ssPlaying) then begin // fetch data from current stream size := stream.ReadData(mixerBuffer, BufSize); if (size > 0) then begin - SDL_MixAudio(PUInt8(Buffer), PUInt8(mixerBuffer), size, SDL_MIX_MAXVOLUME); + SDL_MixAudio(PUInt8(Buffer), PUInt8(mixerBuffer), size, + Trunc(appVolume * stream.Volume / 100)); end; end; end; + + Unlock(); end; { TPortaudioPlaybackStream } -constructor TPortaudioPlaybackStream.Create(decodeStream: TAudioDecodeStream); +constructor TPortaudioPlaybackStream.Create(); begin inherited Create(); - status := sStopped; - if (decodeStream <> nil) then - begin - Self.decodeStream := decodeStream; - Loaded := true; - end; + Reset(); +end; + +destructor TPortaudioPlaybackStream.Destroy(); +begin + Close(); + inherited Destroy(); +end; + +procedure TPortaudioPlaybackStream.Reset(); +begin + Status := ssStopped; + Loop := false; + DecodeStream := nil; + _volume := 0; +end; + +function TPortaudioPlaybackStream.SetDecodeStream(decodeStream: TAudioDecodeStream): boolean; +begin + result := false; + + Reset(); + + if not assigned(decodeStream) then + Exit; + Self.DecodeStream := decodeStream; + + _volume := 100; + + result := true; +end; + +procedure TPortaudioPlaybackStream.Close(); +begin + Reset(); end; procedure TPortaudioPlaybackStream.Play(); begin - if (status <> sPaused) then + if (status <> ssPaused) then begin // rewind - decodeStream.Position := 0; + if assigned(DecodeStream) then + DecodeStream.Position := 0; end; - status := sPlaying; - //mixerStream.AddStream(Self); + status := ssPlaying; + //MixerStream.AddStream(Self); end; procedure TPortaudioPlaybackStream.Pause(); begin - status := sPaused; + status := ssPaused; end; procedure TPortaudioPlaybackStream.Stop(); begin - status := sStopped; -end; - -procedure TPortaudioPlaybackStream.Close(); -begin - status := sStopped; - Loaded := false; - // TODO: cleanup decode-stream + status := ssStopped; end; function TPortaudioPlaybackStream.IsLoaded(): boolean; begin - result := Loaded; + result := assigned(DecodeStream); end; function TPortaudioPlaybackStream.GetLoop(): boolean; @@ -263,7 +331,10 @@ end; function TPortaudioPlaybackStream.GetLength(): real; begin - result := decodeStream.Length; + if assigned(DecodeStream) then + result := DecodeStream.Length + else + result := -1; end; function TPortaudioPlaybackStream.GetStatus(): TStreamStatus; @@ -273,22 +344,47 @@ end; function TPortaudioPlaybackStream.ReadData(Buffer: PChar; BufSize: integer): integer; begin - result := decodeStream.ReadData(Buffer, BufSize); + if not assigned(DecodeStream) then + begin + result := -1; + Exit; + end; + result := DecodeStream.ReadData(Buffer, BufSize); // end-of-file reached -> stop playback - if (decodeStream.EOF) then + if (DecodeStream.EOF) then begin - status := sStopped; + status := ssStopped; end; end; function TPortaudioPlaybackStream.GetPosition: real; begin - result := decodeStream.Position; + if assigned(DecodeStream) then + result := DecodeStream.Position + else + result := -1; end; procedure TPortaudioPlaybackStream.SetPosition(Time: real); begin - decodeStream.Position := Time; + if assigned(DecodeStream) then + DecodeStream.Position := Time; +end; + +function TPortaudioPlaybackStream.GetVolume(): integer; +begin + result := _volume; +end; + +procedure TPortaudioPlaybackStream.SetVolume(volume: integer); +begin + // clamp volume + if (volume > 100) then + _volume := 100 + else if (volume < 0) then + _volume := 0 + else + _volume := volume; end; @@ -298,18 +394,26 @@ function AudioCallback(input: Pointer; output: Pointer; frameCount: Longword; timeInfo: PPaStreamCallbackTimeInfo; statusFlags: TPaStreamCallbackFlags; userData: Pointer): Integer; cdecl; var - playback : TAudioPlayback_Portaudio; - playbackStream : TPortaudioPlaybackStream; - decodeStream : TAudioDecodeStream; + playback: TAudioPlayback_Portaudio; begin playback := TAudioPlayback_Portaudio(userData); with playback do begin - mixerStream.ReadData(output, frameCount * FrameSize); + MixerStream.ReadData(output, frameCount * FrameSize); end; result := paContinue; end; +procedure SDLAudioCallback(userdata: Pointer; stream: PChar; len: integer); cdecl; +var + playback: TAudioPlayback_Portaudio; +begin + playback := TAudioPlayback_Portaudio(userdata); + with playback do + begin + //MixerStream.ReadData(stream, len); + end; +end; function TAudioPlayback_Portaudio.GetName: String; begin @@ -349,10 +453,11 @@ begin device := paOutDevice; channelCount := 2; sampleFormat := paInt16; - suggestedLatency := paOutDeviceInfo^.defaultLowOutputLatency; + suggestedLatency := paOutDeviceInfo^.defaultHighOutputLatency; hostApiSpecificStreamInfo := nil; end; + // set the size of one audio frame (2channel 16bit uint sample) FrameSize := 2 * sizeof(Smallint); err := Pa_OpenStream(paStream, nil, @paOutParams, 44100, @@ -384,219 +489,208 @@ begin result := true; end; -procedure TAudioPlayback_Portaudio.InitializePlayback; +function TAudioPlayback_Portaudio.InitializeSDLAudio(): boolean; +var + desiredAudioSpec, obtainedAudioSpec: TSDL_AudioSpec; + err: integer; begin - Log.LogStatus('InitializePlayback', 'UAudioPlayback_Portaudio'); + result := false; - InitializePortaudio(); - mixerStream := TAudioMixerStream.Create; + SDL_InitSubSystem(SDL_INIT_AUDIO); - StartSoundStream := Load(SoundPath + 'Common start.mp3'); - BackSoundStream := Load(SoundPath + 'Common back.mp3'); - SwooshSoundStream := Load(SoundPath + 'menu swoosh.mp3'); - ChangeSoundStream := Load(SoundPath + 'select music change music 50.mp3'); - OptionSoundStream := Load(SoundPath + 'option change col.mp3'); - ClickSoundStream := Load(SoundPath + 'rimshot022b.mp3'); + FillChar(desiredAudioSpec, sizeof(desiredAudioSpec), 0); + with desiredAudioSpec do + begin + freq := 44100; + format := AUDIO_S16SYS; + channels := 2; + samples := 1024; // latency: 23 ms + callback := @SDLAudioCallback; + userdata := Self; + end; -// DrumSoundStream := Load(SoundPath + 'bassdrumhard076b.mp3'); -// HihatSoundStream := Load(SoundPath + 'hihatclosed068b.mp3'); -// ClapSoundStream := Load(SoundPath + 'claps050b.mp3'); + // set the size of one audio frame (2channel 16bit uint sample) + FrameSize := 2 * sizeof(Smallint); + + if(SDL_OpenAudio(@desiredAudioSpec, @obtainedAudioSpec) = -1) then + begin + Log.LogStatus('SDL_OpenAudio: ' + SDL_GetError(), 'UAudioPlayback_SDL'); + exit; + end; -// ShuffleSoundStream := Load(SoundPath + 'Shuffle.mp3'); + Log.LogStatus('Opened audio device', 'UAudioPlayback_SDL'); - StartPortaudioStream(); + result := true; end; +function TAudioPlayback_Portaudio.StartSDLAudioStream(): boolean; +begin + SDL_PauseAudio(0); + result := true; +end; -procedure TAudioPlayback_Portaudio.SetVolume(Volume: integer); +procedure TAudioPlayback_Portaudio.StopSDLAudioStream(); 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); -*) + SDL_CloseAudio(); end; -procedure TAudioPlayback_Portaudio.SetMusicVolume(Volume: Integer); +function TAudioPlayback_Portaudio.InitializePlayback: boolean; begin - //Max Volume Prevention - if Volume > 100 then - Volume := 100; + result := false; - if Volume < 0 then - Volume := 0; + //Log.LogStatus('InitializePlayback', 'UAudioPlayback_Portaudio'); - //Set Volume -// BASS_ChannelSetAttributes (Bass, -1, Volume, -101); + //if(not InitializePortaudio()) then + if(not InitializeSDLAudio()) then + Exit; + + MixerStream := TAudioMixerStream.Create; + + //if(not StartPortaudioStream()) then; + if(not StartSDLAudioStream()) then + Exit; + + result := true; end; -procedure TAudioPlayback_Portaudio.SetLoop(Enabled: boolean); +destructor TAudioPlayback_Portaudio.Destroy; begin - if (MusicStream <> nil) then - if (MusicStream.IsLoaded) then - MusicStream.SetLoop(Enabled); + StopSDLAudioStream(); + + MixerStream.Free(); + MusicStream.Free(); + + inherited Destroy(); end; -function TAudioPlayback_Portaudio.Open(Filename: string): boolean; +function TAudioPlayback_Portaudio.Load(const Filename: String): TPortaudioPlaybackStream; var decodeStream: TAudioDecodeStream; + playbackStream: TPortaudioPlaybackStream; begin - decodeStream := AudioDecoder.Open(Filename); - MusicStream := TPortaudioPlaybackStream.Create(decodeStream); - // FIXME: remove this line - mixerStream.AddStream(MusicStream); + Result := nil; - if(MusicStream.IsLoaded()) then + decodeStream := AudioDecoder.Open(Filename); + if not assigned(decodeStream) then begin - //Set Max Volume - SetMusicVolume(100); + Log.LogStatus('LoadSoundFromFile: Sound not found "' + Filename + '"', 'UAudioPlayback_Portaudio'); + Exit; end; - Result := MusicStream.IsLoaded(); -end; - -procedure TAudioPlayback_Portaudio.Rewind; -begin - SetPosition(0); -end; + playbackStream := TPortaudioPlaybackStream.Create(); + if (not playbackStream.SetDecodeStream(decodeStream)) then + Exit; -procedure TAudioPlayback_Portaudio.SetPosition(Time: real); -begin - if (MusicStream.IsLoaded) then - begin - MusicStream.SetPosition(Time); - end; -end; + // FIXME: remove this line + MixerStream.AddStream(playbackStream); -function TAudioPlayback_Portaudio.GetPosition: real; -begin - if (MusicStream.IsLoaded) then - Result := MusicStream.GetPosition(); + result := playbackStream; end; -function TAudioPlayback_Portaudio.Length: real; +procedure TAudioPlayback_Portaudio.SetVolume(Volume: integer); begin - Result := 0; - if assigned( MusicStream ) then - if (MusicStream.IsLoaded) then - begin - Result := MusicStream.GetLength(); - end; + // sets volume only for this application + MixerStream.Volume := Volume; end; -procedure TAudioPlayback_Portaudio.Play; +procedure TAudioPlayback_Portaudio.SetMusicVolume(Volume: Integer); begin - if (MusicStream <> nil) then - if (MusicStream.IsLoaded) then - begin - if (MusicStream.GetLoop()) then - begin - end; - // start from beginning... - // actually bass itself does not loop, nor does this TAudio_FFMpeg Class - MusicStream.Play(); - end; + if assigned(MusicStream) then + MusicStream.Volume := Volume; end; -procedure TAudioPlayback_Portaudio.Pause; +procedure TAudioPlayback_Portaudio.SetLoop(Enabled: boolean); begin - if (MusicStream <> nil) then - MusicStream.Pause(); + if assigned(MusicStream) then + MusicStream.SetLoop(Enabled); end; -procedure TAudioPlayback_Portaudio.Stop; +function TAudioPlayback_Portaudio.Open(Filename: string): boolean; +var + decodeStream: TAudioDecodeStream; begin - if MusicStream <> nil then - MusicStream.Stop(); -end; + Result := false; -procedure TAudioPlayback_Portaudio.Close; -begin - if MusicStream <> nil then - MusicStream.Close(); -end; + // free old MusicStream + MusicStream.Free(); -function TAudioPlayback_Portaudio.Finished: boolean; -begin - if MusicStream <> nil then - Result := (MusicStream.GetStatus() = sStopped); -end; + MusicStream := Load(Filename); + if not assigned(MusicStream) then + Exit; -procedure TAudioPlayback_Portaudio.PlayStart; -begin - if StartSoundStream <> nil then - StartSoundStream.Play(); -end; + //Set Max Volume + SetMusicVolume(100); -procedure TAudioPlayback_Portaudio.PlayBack; -begin - if BackSoundStream <> nil then - BackSoundStream.Play(); + Result := true; end; -procedure TAudioPlayback_Portaudio.PlaySwoosh; +procedure TAudioPlayback_Portaudio.Rewind; begin - if SwooshSoundStream <> nil then - SwooshSoundStream.Play(); + SetPosition(0); end; -procedure TAudioPlayback_Portaudio.PlayChange; +procedure TAudioPlayback_Portaudio.SetPosition(Time: real); begin - if ChangeSoundStream <> nil then - ChangeSoundStream.Play(); + if assigned(MusicStream) then + MusicStream.SetPosition(Time); end; -procedure TAudioPlayback_Portaudio.PlayOption; +function TAudioPlayback_Portaudio.GetPosition: real; begin - if OptionSoundStream <> nil then - OptionSoundStream.Play(); + if assigned(MusicStream) then + Result := MusicStream.GetPosition() + else + Result := -1; end; -procedure TAudioPlayback_Portaudio.PlayClick; +function TAudioPlayback_Portaudio.Length: real; begin - if ClickSoundStream <> nil then - ClickSoundStream.Play(); + if assigned(MusicStream) then + Result := MusicStream.GetLength() + else + Result := -1; end; -procedure TAudioPlayback_Portaudio.PlayDrum; +procedure TAudioPlayback_Portaudio.Play; begin - if DrumSoundStream <> nil then - DrumSoundStream.Play(); + if assigned(MusicStream) then + MusicStream.Play(); end; -procedure TAudioPlayback_Portaudio.PlayHihat; +procedure TAudioPlayback_Portaudio.Pause; begin - if HihatSoundStream <> nil then - HihatSoundStream.Play(); + if assigned(MusicStream) then + MusicStream.Pause(); end; -procedure TAudioPlayback_Portaudio.PlayClap; +procedure TAudioPlayback_Portaudio.Stop; begin - if ClapSoundStream <> nil then - ClapSoundStream.Play(); + if assigned(MusicStream) then + MusicStream.Stop(); end; -procedure TAudioPlayback_Portaudio.PlayShuffle; +procedure TAudioPlayback_Portaudio.Close; begin - if ShuffleSoundStream <> nil then - ShuffleSoundStream.Play(); + if assigned(MusicStream) then + begin + MixerStream.RemoveStream(MusicStream); + MusicStream.Close(); + end; end; -procedure TAudioPlayback_Portaudio.StopShuffle; +function TAudioPlayback_Portaudio.Finished: boolean; begin - if ShuffleSoundStream <> nil then - ShuffleSoundStream.Stop(); + if assigned(MusicStream) then + Result := (MusicStream.GetStatus() = ssStopped) + else + Result := true; end; //Equalizer -function TAudioPlayback_Portaudio.GetFFTData: TFFTData; -var - data: TFFTData; +procedure TAudioPlayback_Portaudio.GetFFTData(var data: TFFTData); begin //Get Channel Data Mono and 256 Values // BASS_ChannelGetData(Bass, @Result, BASS_DATA_FFT512); - result := data; end; // Interface for Visualizer @@ -605,66 +699,24 @@ begin result := 0; end; -function TAudioPlayback_Portaudio.Load(Filename: string): TPortaudioPlaybackStream; -var - decodeStream : TAudioDecodeStream; - playbackStream : TPortaudioPlaybackStream; - csIndex : integer; +function TAudioPlayback_Portaudio.OpenSound(const Filename: String): TAudioPlaybackStream; begin - result := nil; - - decodeStream := AudioDecoder.Open(Filename); - if (decodeStream = nil) then - begin - Log.LogStatus('LoadSoundFromFile: Sound not found "' + Filename + '"', 'UAudioPlayback_Portaudio'); - exit; - end; - - playbackStream := TPortaudioPlaybackStream.Create(decodeStream); - // FIXME: remove this line - mixerStream.AddStream(playbackStream); - - //Add CustomSound - csIndex := High(CustomSounds) + 1; - SetLength(CustomSounds, csIndex + 1); - CustomSounds[csIndex].Filename := Filename; - CustomSounds[csIndex].Stream := playbackStream; - - result := playbackStream; + result := Load(Filename); end; -function TAudioPlayback_Portaudio.LoadCustomSound(const Filename: String): Cardinal; -var - S: TAudioPlaybackStream; - I: Integer; - F: String; +procedure TAudioPlayback_Portaudio.PlaySound(stream: TAudioPlaybackStream); 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 := Load(SoundPath + Filename); - if (S <> nil) then - Result := High(CustomSounds) - else - Result := 0; + if assigned(stream) then + stream.Play(); end; -procedure TAudioPlayback_Portaudio.PlayCustomSound(const Index: Cardinal ); +procedure TAudioPlayback_Portaudio.StopSound(stream: TAudioPlaybackStream); begin - if (Index <= High(CustomSounds)) then - CustomSounds[Index].Stream.Play(); + if assigned(stream) then + stream.Stop(); end; - initialization singleton_AudioPlaybackPortaudio := TAudioPlayback_Portaudio.create(); AudioManager.add( singleton_AudioPlaybackPortaudio ); diff --git a/Game/Code/Classes/UDraw.pas b/Game/Code/Classes/UDraw.pas index 662050dc..a81aa93b 100644 --- a/Game/Code/Classes/UDraw.pas +++ b/Game/Code/Classes/UDraw.pas @@ -161,21 +161,25 @@ end; procedure SingDrawOscilloscope(X, Y, W, H: real; NrSound: integer); var - Pet : integer; + SampleIndex: integer; + Sound: TSound; + MaxX, MaxY: real; begin; -// Log.LogStatus('Oscilloscope', 'SingDraw'); + Sound := AudioInputProcessor.Sound[NrSound]; + + // Log.LogStatus('Oscilloscope', 'SingDraw'); glColor3f(Skin_OscR, Skin_OscG, Skin_OscB); {if (ParamStr(1) = '-black') or (ParamStr(1) = '-fsblack') then glColor3f(1, 1, 1); } - glBegin(GL_LINE_STRIP); - - glVertex2f(X, -AudioInputProcessor.Sound[NrSound].BufferArray[1] / $10000 * H + Y + H/2); + MaxX := W-1; + MaxY := (H-1) / 2; - for Pet := 2 to AudioInputProcessor.Sound[NrSound].n div 1 do + glBegin(GL_LINE_STRIP); + for SampleIndex := 0 to High(Sound.BufferArray) do begin - glVertex2f( X + (Pet-1) * W / (AudioInputProcessor.Sound[NrSound].n - 1), - -AudioInputProcessor.Sound[NrSound].BufferArray[Pet] / $10000 * H + Y + H/2 ); + glVertex2f(X + MaxX * SampleIndex/High(Sound.BufferArray), + Y + MaxY * (1 - Sound.BufferArray[SampleIndex]/-Low(Smallint))); end; glEnd; end; diff --git a/Game/Code/Classes/UIni.pas b/Game/Code/Classes/UIni.pas index 599bb8fa..4ac67cda 100644 --- a/Game/Code/Classes/UIni.pas +++ b/Game/Code/Classes/UIni.pas @@ -1,798 +1,801 @@ -unit UIni; - -interface - -{$IFDEF FPC} - {$MODE Delphi} -{$ENDIF} - -{$I switches.inc} - -uses IniFiles, ULog, SysUtils; - -type - TIni = class - Name: array[0..11] of string; - - // Templates for Names Mod - NameTeam: array[0..2] of string; - NameTemplate: array[0..11] of string; - - //Filename of the opened iniFile - Filename: string; - - // Game - Players: integer; - Difficulty: integer; - Language: integer; - Tabs: integer; - Tabs_at_startup:integer; //Tabs at Startup fix - Sorting: integer; - Debug: integer; - - // Graphics - Screens: integer; - Resolution: integer; - Depth: integer; - FullScreen: integer; - TextureSize: integer; - SingWindow: integer; - Oscilloscope: integer; - Spectrum: integer; - Spectrograph: integer; - MovieSize: integer; - - // Sound - MicBoost: integer; - ClickAssist: integer; - BeatClick: integer; - SavePlayback: integer; - Threshold: integer; - - //Song Preview - PreviewVolume: integer; - PreviewFading: integer; - - // Lyrics - LyricsFont: integer; - LyricsEffect: integer; - Solmization: integer; - - // Themes - Theme: integer; - SkinNo: integer; - Color: integer; - - // Record - Card: integer; // not saved in config.ini - - CardList: array of record - Name: string; - Input: integer; - ChannelL: integer; - ChannelR: integer; - end; - - // Advanced - LoadAnimation: integer; - EffectSing: integer; - ScreenFade: integer; - AskbeforeDel: integer; - OnSongClick: integer; - LineBonus: integer; - PartyPopup: integer; - - // Controller - Joypad: integer; - - // Soundcards - SoundCard: array[0..7, 1..2] of integer; - - // Devices - LPT: integer; - - procedure Load; - procedure Save; - procedure SaveNames; - procedure SaveLevel; - end; - - -var - Ini: TIni; - IResolution: array of string; - ILanguage: array of string; - ITheme: array of string; - ISkin: array of string; - ICard: array of string; - IInput: array of string; - -const - IPlayers: array[0..4] of string = ('1', '2', '3', '4', '6'); - IDifficulty: array[0..2] of string = ('Easy', 'Medium', 'Hard'); - ITabs: array[0..1] of string = ('Off', 'On'); - - ISorting: array[0..7] of string = ('Edition', 'Genre', 'Language', 'Folder', 'Title', 'Artist', 'Title2', 'Artist2'); - sEdition = 0; - sGenre = 1; - sLanguage = 2; - sFolder = 3; - sTitle = 4; - sArtist = 5; - sTitle2 = 6; - sArtist2 = 7; - - IDebug: array[0..1] of string = ('Off', 'On'); - - IScreens: array[0..1] of string = ('1', '2'); - IFullScreen: array[0..1] of string = ('Off', 'On'); - IDepth: array[0..1] of string = ('16 bit', '32 bit'); - ITextureSize: array[0..2] of string = ('128', '256', '512'); - ISingWindow: array[0..1] of string = ('Small', 'Big'); - - //SingBar Mod - IOscilloscope: array[0..2] of string = ('Off', 'Osci', 'Bar'); - //IOscilloscope: array[0..1] of string = ('Off', 'On'); - - ISpectrum: array[0..1] of string = ('Off', 'On'); - ISpectrograph: array[0..1] of string = ('Off', 'On'); - IMovieSize: array[0..2] of string = ('Half', 'Full [Vid]', 'Full [BG+Vid]'); - - IMicBoost: array[0..3] of string = ('Off', '+6dB', '+12dB', '+18dB'); - IClickAssist: array[0..1] of string = ('Off', 'On'); - IBeatClick: array[0..1] of string = ('Off', 'On'); - ISavePlayback: array[0..1] of string = ('Off', 'On'); - IThreshold: array[0..3] of string = ('5%', '10%', '15%', '20%'); - //Song Preview - IPreviewVolume: array[0..10] of string = ('Off', '10%', '20%', '30%', '40%', '50%', '60%', '70%', '80%', '90%', '100%'); - IPreviewFading: array[0..5] of string = ('Off', '1 Sec', '2 Secs', '3 Secs', '4 Secs', '5 Secs'); - - - ILyricsFont: array[0..2] of string = ('Plain', 'OLine1', 'OLine2'); - ILyricsEffect: array[0..3] of string = ('Simple', 'Zoom', 'Slide', 'Ball'); - ISolmization: array[0..3] of string = ('Off', 'Euro', 'Jap', 'American'); - - IColor: array[0..8] of string = ('Blue', 'Green', 'Pink', 'Red', 'Violet', 'Orange', 'Yellow', 'Brown', 'Black'); - - // Advanced - ILoadAnimation: array[0..1] of string = ('Off', 'On'); - IEffectSing: array[0..1] of string = ('Off', 'On'); - IScreenFade: array [0..1] of String =('Off', 'On'); - IAskbeforeDel: array[0..1] of string = ('Off', 'On'); - IOnSongClick: array[0..2] of string = ('Sing', 'Select Players', 'Open Menu'); - ILineBonus: array[0..2] of string = ('Off', 'At Score', 'At Notes'); - IPartyPopup: array[0..1] of string = ('Off', 'On'); - - IJoypad: array[0..1] of string = ('Off', 'On'); - ILPT: array[0..2] of string = ('Off', 'LCD', 'Lights'); - - IChannel: array[0..6] of string = ('Off', '1', '2', '3', '4', '5', '6'); - -implementation - -uses //UFiles, - UMain, - SDL, - ULanguage, - UPlatform, - USkins, - URecord, - UCommandLine; - -procedure TIni.Load; -var - IniFile: TMemIniFile; - ThemeIni: TMemIniFile; - Tekst: string; - Pet: integer; - B: boolean; - I, I2, I3: integer; - S: string; - Modes: PPSDL_Rect; - SR: TSearchRec; //Skin List Patch - - function GetFileName (S: String):String; - begin - //Result := copy (S,0,StrRScan (PChar(S),char('.'))+1); - Result := copy (S,0,Pos ('.ini',S)-1); - end; - -begin - GamePath := Platform.GetGameUserPath; - - if (Params.ConfigFile <> '') then - try - IniFile := TMemIniFile.Create(Params.ConfigFile); - except - IniFile := TMemIniFile.Create(GamePath + 'config.ini'); - end - else - IniFile := TMemIniFile.Create(GamePath + 'config.ini'); - - - // Name - for I := 0 to 11 do - Ini.Name[I] := IniFile.ReadString('Name', 'P'+IntToStr(I+1), 'Player'+IntToStr(I+1)); - - - // Templates for Names Mod - for I := 0 to 2 do - Ini.NameTeam[I] := IniFile.ReadString('NameTeam', 'T'+IntToStr(I+1), 'Team'+IntToStr(I+1)); - for I := 0 to 11 do - Ini.NameTemplate[I] := IniFile.ReadString('NameTemplate', 'Name'+IntToStr(I+1), 'Template'+IntToStr(I+1)); - - // Players - Tekst := IniFile.ReadString('Game', 'Players', IPlayers[0]); - for Pet := 0 to High(IPlayers) do - if Tekst = IPlayers[Pet] then Ini.Players := Pet; - - // Difficulty - Tekst := IniFile.ReadString('Game', 'Difficulty', 'Easy'); - for Pet := 0 to High(IDifficulty) do - if Tekst = IDifficulty[Pet] then Ini.Difficulty := Pet; - - // Language - Tekst := IniFile.ReadString('Game', 'Language', 'English'); - for Pet := 0 to High(ILanguage) do - if Tekst = ILanguage[Pet] then Ini.Language := Pet; - -// Language.ChangeLanguage(ILanguage[Ini.Language]); - - // Tabs - Tekst := IniFile.ReadString('Game', 'Tabs', ITabs[0]); - for Pet := 0 to High(ITabs) do - if Tekst = ITabs[Pet] then Ini.Tabs := Pet; - - //Tabs at Startup fix - Ini.Tabs_at_startup := Ini.Tabs; - - // Sorting - Tekst := IniFile.ReadString('Game', 'Sorting', ISorting[0]); - for Pet := 0 to High(ISorting) do - if Tekst = ISorting[Pet] then Ini.Sorting := Pet; - - // Debug - Tekst := IniFile.ReadString('Game', 'Debug', IDebug[0]); - for Pet := 0 to High(IDebug) do - if Tekst = IDebug[Pet] then Ini.Debug := Pet; - - //if Ini.Debug = 1 then SongPath := 'E:\UltraStar 03\Songs\'; - - // Screens - Tekst := IniFile.ReadString('Graphics', 'Screens', IScreens[0]); - for Pet := 0 to High(IScreens) do - if Tekst = IScreens[Pet] then Ini.Screens := Pet; - - // FullScreen - Tekst := IniFile.ReadString('Graphics', 'FullScreen', 'On'); - for Pet := 0 to High(IFullScreen) do - if Tekst = IFullScreen[Pet] then Ini.FullScreen := Pet; - - - // Resolution - SetLength(IResolution, 0); - - Modes := SDL_ListModes(nil, SDL_OPENGL or SDL_FULLSCREEN); // Check if there are any modes available - while assigned( Modes^ ) do //this should solve the biggest wine problem | THANKS Linnex (11.11.07) - begin - SetLength(IResolution, Length(IResolution) + 1); - IResolution[High(IResolution)] := IntToStr(Modes^.w) + 'x' + IntToStr(Modes^.h); - Inc(Modes); - end; - - // if no modes were set, then failback to 800x600 - // as per http://sourceforge.net/forum/message.php?msg_id=4544965 - // THANKS : linnex at users.sourceforge.net - if Length(IResolution) < 1 then - begin - SetLength(IResolution, Length(IResolution) + 1); - IResolution[High(IResolution)] := IntToStr(800) + 'x' + IntToStr(600); - Log.LogStatus('SDL_ListModes Defaulted Res To : ' + IResolution[High(IResolution)] , 'Graphics - Resolutions'); - - // Default to fullscreen OFF, in this case ! - Ini.FullScreen := 0; - end; - - // reverse order - for I := 0 to (Length(IResolution) div 2) - 1 do begin - S := IResolution[I]; - IResolution[I] := IResolution[High(IResolution)-I]; - IResolution[High(IResolution)-I] := S; - end; - - Tekst := IniFile.ReadString('Graphics', 'Resolution', '800x600'); - for Pet := 0 to High(IResolution) do - if Tekst = IResolution[Pet] then Ini.Resolution := Pet; - - - // Resolution - Tekst := IniFile.ReadString('Graphics', 'Depth', '32 bit'); - for Pet := 0 to High(IDepth) do - if Tekst = IDepth[Pet] then Ini.Depth := Pet; - - // Texture Size - Tekst := IniFile.ReadString('Graphics', 'TextureSize', ITextureSize[1]); - for Pet := 0 to High(ITextureSize) do - if Tekst = ITextureSize[Pet] then Ini.TextureSize := Pet; - - // SingWindow - Tekst := IniFile.ReadString('Graphics', 'SingWindow', 'Big'); - for Pet := 0 to High(ISingWindow) do - if Tekst = ISingWindow[Pet] then Ini.SingWindow := Pet; - - // Oscilloscope - Tekst := IniFile.ReadString('Graphics', 'Oscilloscope', 'Bar'); - for Pet := 0 to High(IOscilloscope) do - if Tekst = IOscilloscope[Pet] then Ini.Oscilloscope := Pet; - - // Spectrum - Tekst := IniFile.ReadString('Graphics', 'Spectrum', 'Off'); - for Pet := 0 to High(ISpectrum) do - if Tekst = ISpectrum[Pet] then Ini.Spectrum := Pet; - - // Spectrograph - Tekst := IniFile.ReadString('Graphics', 'Spectrograph', 'Off'); - for Pet := 0 to High(ISpectrograph) do - if Tekst = ISpectrograph[Pet] then Ini.Spectrograph := Pet; - - // MovieSize - Tekst := IniFile.ReadString('Graphics', 'MovieSize', IMovieSize[2]); - for Pet := 0 to High(IMovieSize) do - if Tekst = IMovieSize[Pet] then Ini.MovieSize := Pet; - - // MicBoost - Tekst := IniFile.ReadString('Sound', 'MicBoost', 'Off'); - for Pet := 0 to High(IMicBoost) do - if Tekst = IMicBoost[Pet] then Ini.MicBoost := Pet; - - // ClickAssist - Tekst := IniFile.ReadString('Sound', 'ClickAssist', 'Off'); - for Pet := 0 to High(IClickAssist) do - if Tekst = IClickAssist[Pet] then Ini.ClickAssist := Pet; - - // BeatClick - Tekst := IniFile.ReadString('Sound', 'BeatClick', IBeatClick[0]); - for Pet := 0 to High(IBeatClick) do - if Tekst = IBeatClick[Pet] then Ini.BeatClick := Pet; - - // SavePlayback - Tekst := IniFile.ReadString('Sound', 'SavePlayback', ISavePlayback[0]); - for Pet := 0 to High(ISavePlayback) do - if Tekst = ISavePlayback[Pet] then Ini.SavePlayback := Pet; - - // Threshold - Tekst := IniFile.ReadString('Sound', 'Threshold', IThreshold[2]); - for Pet := 0 to High(IThreshold) do - if Tekst = IThreshold[Pet] then Ini.Threshold := Pet; - - //Song Preview - Tekst := IniFile.ReadString('Sound', 'PreviewVolume', IPreviewVolume[7]); - for Pet := 0 to High(IPreviewVolume) do - if Tekst = IPreviewVolume[Pet] then Ini.PreviewVolume := Pet; - - Tekst := IniFile.ReadString('Sound', 'PreviewFading', IPreviewFading[1]); - for Pet := 0 to High(IPreviewFading) do - if Tekst = IPreviewFading[Pet] then Ini.PreviewFading := Pet; - - // Lyrics Font - Tekst := IniFile.ReadString('Lyrics', 'LyricsFont', ILyricsFont[1]); - for Pet := 0 to High(ILyricsFont) do - if Tekst = ILyricsFont[Pet] then Ini.LyricsFont := Pet; - - // Lyrics Effect - Tekst := IniFile.ReadString('Lyrics', 'LyricsEffect', ILyricsEffect[1]); - for Pet := 0 to High(ILyricsEffect) do - if Tekst = ILyricsEffect[Pet] then Ini.LyricsEffect := Pet; - - // Solmization - Tekst := IniFile.ReadString('Lyrics', 'Solmization', ISolmization[0]); - for Pet := 0 to High(ISolmization) do - if Tekst = ISolmization[Pet] then Ini.Solmization := Pet; - - // Theme - - //Theme List Patch - - //I2 Saves the no of the Deluxe (Standard-) Theme - I2 := 0; - //I counts is the cur. Theme no - I := 0; - - SetLength(ITheme, 0); - writeln( 'Searching for Theme : '+ ThemePath + '*.ini' ); - FindFirst(ThemePath + '*.ini',faAnyFile,SR); - Repeat - writeln( SR.Name ); - - //Read Themename from Theme - ThemeIni := TMemIniFile.Create(SR.Name); - Tekst := UpperCase(ThemeIni.ReadString('Theme','Name',GetFileName(SR.Name))); - ThemeIni.Free; - - //if Deluxe Theme then save Themeno to I2 - if (Tekst = 'DELUXE') then - I2 := I; - - //Search for Skins for this Theme - for Pet := low(Skin.Skin) to high(Skin.Skin) do - begin - if UpperCase(Skin.Skin[Pet].Theme) = Tekst then - begin - SetLength(ITheme, Length(ITheme)+1); - ITheme[High(ITheme)] := GetFileName(SR.Name); - break; - end; - end; - - Inc(I); - Until FindNext(SR) <> 0; - FindClose(SR); - //Theme List Patch End } - - //No Theme Found - if (Length(ITheme)=0) then - begin - Log.CriticalError('Could not find any valid Themes.'); - end; - - - Tekst := IniFile.ReadString('Themes', 'Theme', ITheme[I2]); - Ini.Theme := 0; - for Pet := 0 to High(ITheme) do - if Uppercase(Tekst) = Uppercase(ITheme[Pet]) then Ini.Theme := Pet; - - // Skin - Skin.onThemeChange; - Ini.SkinNo := 0; - - Tekst := IniFile.ReadString('Themes', 'Skin', ISkin[0]); - for Pet := 0 to High(ISkin) do - if Tekst = ISkin[Pet] then Ini.SkinNo := Pet; - - // Color - Tekst := IniFile.ReadString('Themes', 'Color', IColor[0]); - for Pet := 0 to High(IColor) do - if Tekst = IColor[Pet] then Ini.Color := Pet; - - // Record - load ini list - SetLength(CardList, 0); - I := 1; - while (IniFile.ValueExists('Record', 'DeviceName' + IntToStr(I)) = true) do begin - //Automatically Delete not Existing Sound Cards - S := IniFile.ReadString('Record', 'DeviceName' + IntToStr(I), ''); - //{ - B := False; - //Look for Soundcard - for I2 := 0 to High(AudioInputProcessor.SoundCard) do - begin - if (S = Trim(AudioInputProcessor.SoundCard[I2].Description)) then - begin - B := True; - Break; - end; - end; - - if B then - begin //} - I3 := Length(CardList); - SetLength(CardList, I3+1); - Ini.CardList[I3].Name := S; - Ini.CardList[I3].Input := IniFile.ReadInteger('Record', 'Input' + IntToStr(I), 0); - Ini.CardList[I3].ChannelL := IniFile.ReadInteger('Record', 'ChannelL' + IntToStr(I), 0); - Ini.CardList[I3].ChannelR := IniFile.ReadInteger('Record', 'ChannelR' + IntToStr(I), 0); - end; - Inc(I); - end; - - // Record - append detected soundcards - for I := 0 to High(AudioInputProcessor.SoundCard) do - begin - B := False; - For I2 := 0 to High(CardList) do - begin //Search for Card in List - if (CardList[I2].Name = Trim(AudioInputProcessor.SoundCard[I].Description)) then - begin - B := True; - Break; - end; - end; - - //If not in List -> Add - If not B then - begin - I3 := Length(CardList); - SetLength(CardList, I3+1); - CardList[I3].Name := Trim(AudioInputProcessor.SoundCard[I].Description); - CardList[I3].Input := 0; - CardList[I3].ChannelL := 0; - CardList[I3].ChannelR := 0; - // default for new users - if (Length(CardList) = 1) then - CardList[I].ChannelL := 1; - end; - end; - - //Advanced Settings - - // LoadAnimation - Tekst := IniFile.ReadString('Advanced', 'LoadAnimation', 'On'); - for Pet := 0 to High(ILoadAnimation) do - if Tekst = ILoadAnimation[Pet] then Ini.LoadAnimation := Pet; - - // ScreenFade - Tekst := IniFile.ReadString('Advanced', 'ScreenFade', 'On'); - for Pet := 0 to High(IScreenFade) do - if Tekst = IScreenFade[Pet] then Ini.ScreenFade := Pet; - - // EffectSing - Tekst := IniFile.ReadString('Advanced', 'EffectSing', 'On'); - for Pet := 0 to High(IEffectSing) do - if Tekst = IEffectSing[Pet] then Ini.EffectSing := Pet; - - // AskbeforeDel - Tekst := IniFile.ReadString('Advanced', 'AskbeforeDel', 'On'); - for Pet := 0 to High(IAskbeforeDel) do - if Tekst = IAskbeforeDel[Pet] then Ini.AskbeforeDel := Pet; - - // OnSongClick - Tekst := IniFile.ReadString('Advanced', 'OnSongClick', 'Sing'); - for Pet := 0 to High(IOnSongClick) do - if Tekst = IOnSongClick[Pet] then Ini.OnSongClick := Pet; - - // Linebonus - Tekst := IniFile.ReadString('Advanced', 'LineBonus', 'At Score'); - for Pet := 0 to High(ILineBonus) do - if Tekst = ILineBonus[Pet] then Ini.LineBonus := Pet; - - // PartyPopup - Tekst := IniFile.ReadString('Advanced', 'PartyPopup', 'On'); - for Pet := 0 to High(IPartyPopup) do - if Tekst = IPartyPopup[Pet] then Ini.PartyPopup := Pet; - - - // Joypad - Tekst := IniFile.ReadString('Controller', 'Joypad', IJoypad[0]); - for Pet := 0 to High(IJoypad) do - if Tekst = IJoypad[Pet] then Ini.Joypad := Pet; - - // LCD - Tekst := IniFile.ReadString('Devices', 'LPT', ILPT[0]); - for Pet := 0 to High(ILPT) do - if Tekst = ILPT[Pet] then Ini.LPT := Pet; - - - // SongPath - if (Params.SongPath <> '') then - SongPath := IncludeTrailingPathDelimiter(Params.SongPath) - else - SongPath := IncludeTrailingPathDelimiter(IniFile.ReadString('Path', 'Songs', SongPath)); - - Filename := IniFile.FileName; - IniFile.Free; -end; - -procedure TIni.Save; -var - IniFile: TIniFile; - Tekst: string; - I: Integer; - S: String; -begin - //if not (FileExists(GamePath + 'config.ini') and FileIsReadOnly(GamePath + 'config.ini')) then begin - if not (FileExists(Filename) and FileIsReadOnly(Filename)) then begin - - IniFile := TIniFile.Create(Filename); - - // Players - Tekst := IPlayers[Ini.Players]; - IniFile.WriteString('Game', 'Players', Tekst); - - // Difficulty - Tekst := IDifficulty[Ini.Difficulty]; - IniFile.WriteString('Game', 'Difficulty', Tekst); - - // Language - Tekst := ILanguage[Ini.Language]; - IniFile.WriteString('Game', 'Language', Tekst); - - // Tabs - Tekst := ITabs[Ini.Tabs]; - IniFile.WriteString('Game', 'Tabs', Tekst); - - // Sorting - Tekst := ISorting[Ini.Sorting]; - IniFile.WriteString('Game', 'Sorting', Tekst); - - // Debug - Tekst := IDebug[Ini.Debug]; - IniFile.WriteString('Game', 'Debug', Tekst); - - // Screens - Tekst := IScreens[Ini.Screens]; - IniFile.WriteString('Graphics', 'Screens', Tekst); - - // FullScreen - Tekst := IFullScreen[Ini.FullScreen]; - IniFile.WriteString('Graphics', 'FullScreen', Tekst); - - // Resolution - Tekst := IResolution[Ini.Resolution]; - IniFile.WriteString('Graphics', 'Resolution', Tekst); - - // Depth - Tekst := IDepth[Ini.Depth]; - IniFile.WriteString('Graphics', 'Depth', Tekst); - - // Resolution - Tekst := ITextureSize[Ini.TextureSize]; - IniFile.WriteString('Graphics', 'TextureSize', Tekst); - - // Sing Window - Tekst := ISingWindow[Ini.SingWindow]; - IniFile.WriteString('Graphics', 'SingWindow', Tekst); - - // Oscilloscope - Tekst := IOscilloscope[Ini.Oscilloscope]; - IniFile.WriteString('Graphics', 'Oscilloscope', Tekst); - - // Spectrum - Tekst := ISpectrum[Ini.Spectrum]; - IniFile.WriteString('Graphics', 'Spectrum', Tekst); - - // Spectrograph - Tekst := ISpectrograph[Ini.Spectrograph]; - IniFile.WriteString('Graphics', 'Spectrograph', Tekst); - - // Movie Size - Tekst := IMovieSize[Ini.MovieSize]; - IniFile.WriteString('Graphics', 'MovieSize', Tekst); - - // MicBoost - Tekst := IMicBoost[Ini.MicBoost]; - IniFile.WriteString('Sound', 'MicBoost', Tekst); - - // ClickAssist - Tekst := IClickAssist[Ini.ClickAssist]; - IniFile.WriteString('Sound', 'ClickAssist', Tekst); - - // BeatClick - Tekst := IBeatClick[Ini.BeatClick]; - IniFile.WriteString('Sound', 'BeatClick', Tekst); - - // Threshold - Tekst := IThreshold[Ini.Threshold]; - IniFile.WriteString('Sound', 'Threshold', Tekst); - - // Song Preview - Tekst := IPreviewVolume[Ini.PreviewVolume]; - IniFile.WriteString('Sound', 'PreviewVolume', Tekst); - - Tekst := IPreviewFading[Ini.PreviewFading]; - IniFile.WriteString('Sound', 'PreviewFading', Tekst); - - // SavePlayback - Tekst := ISavePlayback[Ini.SavePlayback]; - IniFile.WriteString('Sound', 'SavePlayback', Tekst); - - // Lyrics Font - Tekst := ILyricsFont[Ini.LyricsFont]; - IniFile.WriteString('Lyrics', 'LyricsFont', Tekst); - - // Lyrics Effect - Tekst := ILyricsEffect[Ini.LyricsEffect]; - IniFile.WriteString('Lyrics', 'LyricsEffect', Tekst); - - // Solmization - Tekst := ISolmization[Ini.Solmization]; - IniFile.WriteString('Lyrics', 'Solmization', Tekst); - - // Theme - Tekst := ITheme[Ini.Theme]; - IniFile.WriteString('Themes', 'Theme', Tekst); - - // Skin - Tekst := ISkin[Ini.SkinNo]; - IniFile.WriteString('Themes', 'Skin', Tekst); - - // Color - Tekst := IColor[Ini.Color]; - IniFile.WriteString('Themes', 'Color', Tekst); - - // Record - for I := 0 to High(CardList) do begin - S := IntToStr(I+1); - - Tekst := CardList[I].Name; - IniFile.WriteString('Record', 'DeviceName' + S, Tekst); - - Tekst := IntToStr(CardList[I].Input); - IniFile.WriteString('Record', 'Input' + S, Tekst); - - Tekst := IntToStr(CardList[I].ChannelL); - IniFile.WriteString('Record', 'ChannelL' + S, Tekst); - - Tekst := IntToStr(CardList[I].ChannelR); - IniFile.WriteString('Record', 'ChannelR' + S, Tekst); - end; - - //Log.LogError(InttoStr(Length(CardList)) + ' Cards Saved'); - - //Advanced Settings - - //LoadAnimation - Tekst := ILoadAnimation[Ini.LoadAnimation]; - IniFile.WriteString('Advanced', 'LoadAnimation', Tekst); - - //EffectSing - Tekst := IEffectSing[Ini.EffectSing]; - IniFile.WriteString('Advanced', 'EffectSing', Tekst); - - //ScreenFade - Tekst := IScreenFade[Ini.ScreenFade]; - IniFile.WriteString('Advanced', 'ScreenFade', Tekst); - - //AskbeforeDel - Tekst := IAskbeforeDel[Ini.AskbeforeDel]; - IniFile.WriteString('Advanced', 'AskbeforeDel', Tekst); - - //OnSongClick - Tekst := IOnSongClick[Ini.OnSongClick]; - IniFile.WriteString('Advanced', 'OnSongClick', Tekst); - - //Line Bonus - Tekst := ILineBonus[Ini.LineBonus]; - IniFile.WriteString('Advanced', 'LineBonus', Tekst); - - //Party Popup - Tekst := IPartyPopup[Ini.PartyPopup]; - IniFile.WriteString('Advanced', 'PartyPopup', Tekst); - - // Joypad - Tekst := IJoypad[Ini.Joypad]; - IniFile.WriteString('Controller', 'Joypad', Tekst); - - IniFile.Free; - end; -end; - -procedure TIni.SaveNames; -var - IniFile: TIniFile; - I: integer; -begin - //if not FileIsReadOnly(GamePath + 'config.ini') then begin - //IniFile := TIniFile.Create(GamePath + 'config.ini'); - if not FileIsReadOnly(Filename) then begin - IniFile := TIniFile.Create(Filename); - - //Name - // Templates for Names Mod - for I := 1 to 12 do - IniFile.WriteString('Name', 'P' + IntToStr(I), Ini.Name[I-1]); - for I := 1 to 3 do - IniFile.WriteString('NameTeam', 'T' + IntToStr(I), Ini.NameTeam[I-1]); - for I := 1 to 12 do - IniFile.WriteString('NameTemplate', 'Name' + IntToStr(I), Ini.NameTemplate[I-1]); - - IniFile.Free; - end; -end; - -procedure TIni.SaveLevel; -var - IniFile: TIniFile; - I: integer; -begin - //if not FileIsReadOnly(GamePath + 'config.ini') then begin - //IniFile := TIniFile.Create(GamePath + 'config.ini'); - if not FileIsReadOnly(Filename) then begin - IniFile := TIniFile.Create(Filename); - - // Difficulty - IniFile.WriteString('Game', 'Difficulty', IDifficulty[Ini.Difficulty]); - - IniFile.Free; - end; -end; - -end. +unit UIni;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses IniFiles, ULog, SysUtils;
+
+type
+ PInputDeviceConfig = ^TInputDeviceConfig;
+ TInputDeviceConfig = record
+ Name: string;
+ Input: integer;
+ ChannelToPlayerMap: array[0..1] of integer;
+ end;
+
+type
+ TIni = class
+ Name: array[0..11] of string;
+
+ // Templates for Names Mod
+ NameTeam: array[0..2] of string;
+ NameTemplate: array[0..11] of string;
+
+ //Filename of the opened iniFile
+ Filename: string;
+
+ // Game
+ Players: integer;
+ Difficulty: integer;
+ Language: integer;
+ Tabs: integer;
+ Tabs_at_startup:integer; //Tabs at Startup fix
+ Sorting: integer;
+ Debug: integer;
+
+ // Graphics
+ Screens: integer;
+ Resolution: integer;
+ Depth: integer;
+ FullScreen: integer;
+ TextureSize: integer;
+ SingWindow: integer;
+ Oscilloscope: integer;
+ Spectrum: integer;
+ Spectrograph: integer;
+ MovieSize: integer;
+
+ // Sound
+ MicBoost: integer;
+ ClickAssist: integer;
+ BeatClick: integer;
+ SavePlayback: integer;
+ Threshold: integer;
+
+ //Song Preview
+ PreviewVolume: integer;
+ PreviewFading: integer;
+
+ // Lyrics
+ LyricsFont: integer;
+ LyricsEffect: integer;
+ Solmization: integer;
+
+ // Themes
+ Theme: integer;
+ SkinNo: integer;
+ Color: integer;
+
+ // Record
+ InputDeviceConfig: array of TInputDeviceConfig;
+
+ // Advanced
+ LoadAnimation: integer;
+ EffectSing: integer;
+ ScreenFade: integer;
+ AskbeforeDel: integer;
+ OnSongClick: integer;
+ LineBonus: integer;
+ PartyPopup: integer;
+
+ // Controller
+ Joypad: integer;
+
+ // Soundcards
+ SoundCard: array[0..7, 1..2] of integer;
+
+ // Devices
+ LPT: integer;
+
+ procedure Load;
+ procedure Save;
+ procedure SaveNames;
+ procedure SaveLevel;
+ end;
+
+
+var
+ Ini: TIni;
+ IResolution: array of string;
+ ILanguage: array of string;
+ ITheme: array of string;
+ ISkin: array of string;
+ ICard: array of string;
+ IInput: array of string;
+
+const
+ IPlayers: array[0..4] of string = ('1', '2', '3', '4', '6');
+ IDifficulty: array[0..2] of string = ('Easy', 'Medium', 'Hard');
+ ITabs: array[0..1] of string = ('Off', 'On');
+
+ ISorting: array[0..7] of string = ('Edition', 'Genre', 'Language', 'Folder', 'Title', 'Artist', 'Title2', 'Artist2');
+ sEdition = 0;
+ sGenre = 1;
+ sLanguage = 2;
+ sFolder = 3;
+ sTitle = 4;
+ sArtist = 5;
+ sTitle2 = 6;
+ sArtist2 = 7;
+
+ IDebug: array[0..1] of string = ('Off', 'On');
+
+ IScreens: array[0..1] of string = ('1', '2');
+ IFullScreen: array[0..1] of string = ('Off', 'On');
+ IDepth: array[0..1] of string = ('16 bit', '32 bit');
+ ITextureSize: array[0..2] of string = ('128', '256', '512');
+ ISingWindow: array[0..1] of string = ('Small', 'Big');
+
+ //SingBar Mod
+ IOscilloscope: array[0..2] of string = ('Off', 'Osci', 'Bar');
+ //IOscilloscope: array[0..1] of string = ('Off', 'On');
+
+ ISpectrum: array[0..1] of string = ('Off', 'On');
+ ISpectrograph: array[0..1] of string = ('Off', 'On');
+ IMovieSize: array[0..2] of string = ('Half', 'Full [Vid]', 'Full [BG+Vid]');
+
+ IMicBoost: array[0..3] of string = ('Off', '+6dB', '+12dB', '+18dB');
+ IClickAssist: array[0..1] of string = ('Off', 'On');
+ IBeatClick: array[0..1] of string = ('Off', 'On');
+ ISavePlayback: array[0..1] of string = ('Off', 'On');
+ IThreshold: array[0..3] of string = ('5%', '10%', '15%', '20%');
+ //Song Preview
+ IPreviewVolume: array[0..10] of string = ('Off', '10%', '20%', '30%', '40%', '50%', '60%', '70%', '80%', '90%', '100%');
+ IPreviewFading: array[0..5] of string = ('Off', '1 Sec', '2 Secs', '3 Secs', '4 Secs', '5 Secs');
+
+
+ ILyricsFont: array[0..2] of string = ('Plain', 'OLine1', 'OLine2');
+ ILyricsEffect: array[0..3] of string = ('Simple', 'Zoom', 'Slide', 'Ball');
+ ISolmization: array[0..3] of string = ('Off', 'Euro', 'Jap', 'American');
+
+ IColor: array[0..8] of string = ('Blue', 'Green', 'Pink', 'Red', 'Violet', 'Orange', 'Yellow', 'Brown', 'Black');
+
+ // Advanced
+ ILoadAnimation: array[0..1] of string = ('Off', 'On');
+ IEffectSing: array[0..1] of string = ('Off', 'On');
+ IScreenFade: array [0..1] of String =('Off', 'On');
+ IAskbeforeDel: array[0..1] of string = ('Off', 'On');
+ IOnSongClick: array[0..2] of string = ('Sing', 'Select Players', 'Open Menu');
+ ILineBonus: array[0..2] of string = ('Off', 'At Score', 'At Notes');
+ IPartyPopup: array[0..1] of string = ('Off', 'On');
+
+ IJoypad: array[0..1] of string = ('Off', 'On');
+ ILPT: array[0..2] of string = ('Off', 'LCD', 'Lights');
+
+ IChannel: array[0..6] of string = ('Off', '1', '2', '3', '4', '5', '6');
+
+implementation
+
+uses //UFiles,
+ UMain,
+ SDL,
+ ULanguage,
+ UPlatform,
+ USkins,
+ URecord,
+ UCommandLine;
+
+procedure TIni.Load;
+var
+ IniFile: TMemIniFile;
+ ThemeIni: TMemIniFile;
+ Tekst: string;
+ Pet: integer;
+ B: boolean;
+ I, I2, I3: integer;
+ S: string;
+ Modes: PPSDL_Rect;
+ SR: TSearchRec; //Skin List Patch
+
+ function GetFileName (S: String):String;
+ begin
+ //Result := copy (S,0,StrRScan (PChar(S),char('.'))+1);
+ Result := copy (S,0,Pos ('.ini',S)-1);
+ end;
+
+begin
+ GamePath := Platform.GetGameUserPath;
+
+ if (Params.ConfigFile <> '') then
+ try
+ IniFile := TMemIniFile.Create(Params.ConfigFile);
+ except
+ IniFile := TMemIniFile.Create(GamePath + 'config.ini');
+ end
+ else
+ IniFile := TMemIniFile.Create(GamePath + 'config.ini');
+
+
+ // Name
+ for I := 0 to 11 do
+ Ini.Name[I] := IniFile.ReadString('Name', 'P'+IntToStr(I+1), 'Player'+IntToStr(I+1));
+
+
+ // Templates for Names Mod
+ for I := 0 to 2 do
+ Ini.NameTeam[I] := IniFile.ReadString('NameTeam', 'T'+IntToStr(I+1), 'Team'+IntToStr(I+1));
+ for I := 0 to 11 do
+ Ini.NameTemplate[I] := IniFile.ReadString('NameTemplate', 'Name'+IntToStr(I+1), 'Template'+IntToStr(I+1));
+
+ // Players
+ Tekst := IniFile.ReadString('Game', 'Players', IPlayers[0]);
+ for Pet := 0 to High(IPlayers) do
+ if Tekst = IPlayers[Pet] then Ini.Players := Pet;
+
+ // Difficulty
+ Tekst := IniFile.ReadString('Game', 'Difficulty', 'Easy');
+ for Pet := 0 to High(IDifficulty) do
+ if Tekst = IDifficulty[Pet] then Ini.Difficulty := Pet;
+
+ // Language
+ Tekst := IniFile.ReadString('Game', 'Language', 'English');
+ for Pet := 0 to High(ILanguage) do
+ if Tekst = ILanguage[Pet] then Ini.Language := Pet;
+
+// Language.ChangeLanguage(ILanguage[Ini.Language]);
+
+ // Tabs
+ Tekst := IniFile.ReadString('Game', 'Tabs', ITabs[0]);
+ for Pet := 0 to High(ITabs) do
+ if Tekst = ITabs[Pet] then Ini.Tabs := Pet;
+
+ //Tabs at Startup fix
+ Ini.Tabs_at_startup := Ini.Tabs;
+
+ // Sorting
+ Tekst := IniFile.ReadString('Game', 'Sorting', ISorting[0]);
+ for Pet := 0 to High(ISorting) do
+ if Tekst = ISorting[Pet] then Ini.Sorting := Pet;
+
+ // Debug
+ Tekst := IniFile.ReadString('Game', 'Debug', IDebug[0]);
+ for Pet := 0 to High(IDebug) do
+ if Tekst = IDebug[Pet] then Ini.Debug := Pet;
+
+ //if Ini.Debug = 1 then SongPath := 'E:\UltraStar 03\Songs\';
+
+ // Screens
+ Tekst := IniFile.ReadString('Graphics', 'Screens', IScreens[0]);
+ for Pet := 0 to High(IScreens) do
+ if Tekst = IScreens[Pet] then Ini.Screens := Pet;
+
+ // FullScreen
+ Tekst := IniFile.ReadString('Graphics', 'FullScreen', 'On');
+ for Pet := 0 to High(IFullScreen) do
+ if Tekst = IFullScreen[Pet] then Ini.FullScreen := Pet;
+
+
+ // Resolution
+ SetLength(IResolution, 0);
+
+ Modes := SDL_ListModes(nil, SDL_OPENGL or SDL_FULLSCREEN); // Check if there are any modes available
+ while assigned( Modes^ ) do //this should solve the biggest wine problem | THANKS Linnex (11.11.07)
+ begin
+ SetLength(IResolution, Length(IResolution) + 1);
+ IResolution[High(IResolution)] := IntToStr(Modes^.w) + 'x' + IntToStr(Modes^.h);
+ Inc(Modes);
+ end;
+
+ // if no modes were set, then failback to 800x600
+ // as per http://sourceforge.net/forum/message.php?msg_id=4544965
+ // THANKS : linnex at users.sourceforge.net
+ if Length(IResolution) < 1 then
+ begin
+ SetLength(IResolution, Length(IResolution) + 1);
+ IResolution[High(IResolution)] := IntToStr(800) + 'x' + IntToStr(600);
+ Log.LogStatus('SDL_ListModes Defaulted Res To : ' + IResolution[High(IResolution)] , 'Graphics - Resolutions');
+
+ // Default to fullscreen OFF, in this case !
+ Ini.FullScreen := 0;
+ end;
+
+ // reverse order
+ for I := 0 to (Length(IResolution) div 2) - 1 do begin
+ S := IResolution[I];
+ IResolution[I] := IResolution[High(IResolution)-I];
+ IResolution[High(IResolution)-I] := S;
+ end;
+
+ Tekst := IniFile.ReadString('Graphics', 'Resolution', '800x600');
+ for Pet := 0 to High(IResolution) do
+ if Tekst = IResolution[Pet] then Ini.Resolution := Pet;
+
+
+ // Resolution
+ Tekst := IniFile.ReadString('Graphics', 'Depth', '32 bit');
+ for Pet := 0 to High(IDepth) do
+ if Tekst = IDepth[Pet] then Ini.Depth := Pet;
+
+ // Texture Size
+ Tekst := IniFile.ReadString('Graphics', 'TextureSize', ITextureSize[1]);
+ for Pet := 0 to High(ITextureSize) do
+ if Tekst = ITextureSize[Pet] then Ini.TextureSize := Pet;
+
+ // SingWindow
+ Tekst := IniFile.ReadString('Graphics', 'SingWindow', 'Big');
+ for Pet := 0 to High(ISingWindow) do
+ if Tekst = ISingWindow[Pet] then Ini.SingWindow := Pet;
+
+ // Oscilloscope
+ Tekst := IniFile.ReadString('Graphics', 'Oscilloscope', 'Bar');
+ for Pet := 0 to High(IOscilloscope) do
+ if Tekst = IOscilloscope[Pet] then Ini.Oscilloscope := Pet;
+
+ // Spectrum
+ Tekst := IniFile.ReadString('Graphics', 'Spectrum', 'Off');
+ for Pet := 0 to High(ISpectrum) do
+ if Tekst = ISpectrum[Pet] then Ini.Spectrum := Pet;
+
+ // Spectrograph
+ Tekst := IniFile.ReadString('Graphics', 'Spectrograph', 'Off');
+ for Pet := 0 to High(ISpectrograph) do
+ if Tekst = ISpectrograph[Pet] then Ini.Spectrograph := Pet;
+
+ // MovieSize
+ Tekst := IniFile.ReadString('Graphics', 'MovieSize', IMovieSize[2]);
+ for Pet := 0 to High(IMovieSize) do
+ if Tekst = IMovieSize[Pet] then Ini.MovieSize := Pet;
+
+ // MicBoost
+ Tekst := IniFile.ReadString('Sound', 'MicBoost', 'Off');
+ for Pet := 0 to High(IMicBoost) do
+ if Tekst = IMicBoost[Pet] then Ini.MicBoost := Pet;
+
+ // ClickAssist
+ Tekst := IniFile.ReadString('Sound', 'ClickAssist', 'Off');
+ for Pet := 0 to High(IClickAssist) do
+ if Tekst = IClickAssist[Pet] then Ini.ClickAssist := Pet;
+
+ // BeatClick
+ Tekst := IniFile.ReadString('Sound', 'BeatClick', IBeatClick[0]);
+ for Pet := 0 to High(IBeatClick) do
+ if Tekst = IBeatClick[Pet] then Ini.BeatClick := Pet;
+
+ // SavePlayback
+ Tekst := IniFile.ReadString('Sound', 'SavePlayback', ISavePlayback[0]);
+ for Pet := 0 to High(ISavePlayback) do
+ if Tekst = ISavePlayback[Pet] then Ini.SavePlayback := Pet;
+
+ // Threshold
+ Tekst := IniFile.ReadString('Sound', 'Threshold', IThreshold[2]);
+ for Pet := 0 to High(IThreshold) do
+ if Tekst = IThreshold[Pet] then Ini.Threshold := Pet;
+
+ //Song Preview
+ Tekst := IniFile.ReadString('Sound', 'PreviewVolume', IPreviewVolume[7]);
+ for Pet := 0 to High(IPreviewVolume) do
+ if Tekst = IPreviewVolume[Pet] then Ini.PreviewVolume := Pet;
+
+ Tekst := IniFile.ReadString('Sound', 'PreviewFading', IPreviewFading[1]);
+ for Pet := 0 to High(IPreviewFading) do
+ if Tekst = IPreviewFading[Pet] then Ini.PreviewFading := Pet;
+
+ // Lyrics Font
+ Tekst := IniFile.ReadString('Lyrics', 'LyricsFont', ILyricsFont[1]);
+ for Pet := 0 to High(ILyricsFont) do
+ if Tekst = ILyricsFont[Pet] then Ini.LyricsFont := Pet;
+
+ // Lyrics Effect
+ Tekst := IniFile.ReadString('Lyrics', 'LyricsEffect', ILyricsEffect[1]);
+ for Pet := 0 to High(ILyricsEffect) do
+ if Tekst = ILyricsEffect[Pet] then Ini.LyricsEffect := Pet;
+
+ // Solmization
+ Tekst := IniFile.ReadString('Lyrics', 'Solmization', ISolmization[0]);
+ for Pet := 0 to High(ISolmization) do
+ if Tekst = ISolmization[Pet] then Ini.Solmization := Pet;
+
+ // Theme
+
+ //Theme List Patch
+
+ //I2 Saves the no of the Deluxe (Standard-) Theme
+ I2 := 0;
+ //I counts is the cur. Theme no
+ I := 0;
+
+ SetLength(ITheme, 0);
+ writeln( 'Searching for Theme : '+ ThemePath + '*.ini' );
+ FindFirst(ThemePath + '*.ini',faAnyFile,SR);
+ Repeat
+ writeln( SR.Name );
+
+ //Read Themename from Theme
+ ThemeIni := TMemIniFile.Create(SR.Name);
+ Tekst := UpperCase(ThemeIni.ReadString('Theme','Name',GetFileName(SR.Name)));
+ ThemeIni.Free;
+
+ //if Deluxe Theme then save Themeno to I2
+ if (Tekst = 'DELUXE') then
+ I2 := I;
+
+ //Search for Skins for this Theme
+ for Pet := low(Skin.Skin) to high(Skin.Skin) do
+ begin
+ if UpperCase(Skin.Skin[Pet].Theme) = Tekst then
+ begin
+ SetLength(ITheme, Length(ITheme)+1);
+ ITheme[High(ITheme)] := GetFileName(SR.Name);
+ break;
+ end;
+ end;
+
+ Inc(I);
+ Until FindNext(SR) <> 0;
+ FindClose(SR);
+ //Theme List Patch End }
+
+ //No Theme Found
+ if (Length(ITheme)=0) then
+ begin
+ Log.CriticalError('Could not find any valid Themes.');
+ end;
+
+
+ Tekst := IniFile.ReadString('Themes', 'Theme', ITheme[I2]);
+ Ini.Theme := 0;
+ for Pet := 0 to High(ITheme) do
+ if Uppercase(Tekst) = Uppercase(ITheme[Pet]) then Ini.Theme := Pet;
+
+ // Skin
+ Skin.onThemeChange;
+ Ini.SkinNo := 0;
+
+ Tekst := IniFile.ReadString('Themes', 'Skin', ISkin[0]);
+ for Pet := 0 to High(ISkin) do
+ if Tekst = ISkin[Pet] then Ini.SkinNo := Pet;
+
+ // Color
+ Tekst := IniFile.ReadString('Themes', 'Color', IColor[0]);
+ for Pet := 0 to High(IColor) do
+ if Tekst = IColor[Pet] then Ini.Color := Pet;
+
+ // Input devices - load ini list
+ SetLength(InputDeviceConfig, 0);
+ I := 1;
+ while (IniFile.ValueExists('Record', 'DeviceName'+IntToStr(I))) do begin
+ // resize list
+ SetLength(InputDeviceConfig, Length(InputDeviceConfig)+1);
+ I2 := High(InputDeviceConfig);
+
+ // read an input device's config.
+ // Note: All devices are appended to the list whether they exist or not.
+ // Otherwise an external device's config will be lost if it is not
+ // connected (e.g. singstar mics or USB-Audio devices).
+ InputDeviceConfig[I2].Name :=
+ IniFile.ReadString('Record', 'DeviceName'+IntToStr(I), '');
+ InputDeviceConfig[I2].Input :=
+ IniFile.ReadInteger('Record', 'Input'+IntToStr(I), 0);
+ InputDeviceConfig[I2].ChannelToPlayerMap[0] :=
+ IniFile.ReadInteger('Record', 'ChannelL'+IntToStr(I), 0);
+ InputDeviceConfig[I2].ChannelToPlayerMap[1] :=
+ IniFile.ReadInteger('Record', 'ChannelR'+IntToStr(I), 0);
+
+ Inc(I);
+ end;
+
+ // Input devices - append detected soundcards
+ for I := 0 to High(AudioInputProcessor.Device) do
+ begin
+ B := False;
+ For I2 := 0 to High(InputDeviceConfig) do
+ begin //Search for Card in List
+ if (InputDeviceConfig[I2].Name = Trim(AudioInputProcessor.Device[I].Description)) then
+ begin
+ B := True;
+ // associate ini-index with device
+ AudioInputProcessor.Device[I].CfgIndex := I2;
+ Break;
+ end;
+ end;
+
+ //If not in List -> Add
+ If not B then
+ begin
+ // resize list
+ SetLength(InputDeviceConfig, Length(InputDeviceConfig)+1);
+ I2 := High(InputDeviceConfig);
+
+ InputDeviceConfig[I2].Name := Trim(AudioInputProcessor.Device[I].Description);
+ InputDeviceConfig[I2].Input := 0;
+ InputDeviceConfig[I2].ChannelToPlayerMap[0] := 0;
+ InputDeviceConfig[I2].ChannelToPlayerMap[1] := 0;
+
+ // associate ini-index with device
+ AudioInputProcessor.Device[I].CfgIndex := I2;
+
+ // set default at first start of USDX (1st device, 1st channel -> player1)
+ if (I2 = 0) then
+ InputDeviceConfig[I2].ChannelToPlayerMap[0] := 1;
+ end;
+ end;
+
+ //Advanced Settings
+
+ // LoadAnimation
+ Tekst := IniFile.ReadString('Advanced', 'LoadAnimation', 'On');
+ for Pet := 0 to High(ILoadAnimation) do
+ if Tekst = ILoadAnimation[Pet] then Ini.LoadAnimation := Pet;
+
+ // ScreenFade
+ Tekst := IniFile.ReadString('Advanced', 'ScreenFade', 'On');
+ for Pet := 0 to High(IScreenFade) do
+ if Tekst = IScreenFade[Pet] then Ini.ScreenFade := Pet;
+
+ // EffectSing
+ Tekst := IniFile.ReadString('Advanced', 'EffectSing', 'On');
+ for Pet := 0 to High(IEffectSing) do
+ if Tekst = IEffectSing[Pet] then Ini.EffectSing := Pet;
+
+ // AskbeforeDel
+ Tekst := IniFile.ReadString('Advanced', 'AskbeforeDel', 'On');
+ for Pet := 0 to High(IAskbeforeDel) do
+ if Tekst = IAskbeforeDel[Pet] then Ini.AskbeforeDel := Pet;
+
+ // OnSongClick
+ Tekst := IniFile.ReadString('Advanced', 'OnSongClick', 'Sing');
+ for Pet := 0 to High(IOnSongClick) do
+ if Tekst = IOnSongClick[Pet] then Ini.OnSongClick := Pet;
+
+ // Linebonus
+ Tekst := IniFile.ReadString('Advanced', 'LineBonus', 'At Score');
+ for Pet := 0 to High(ILineBonus) do
+ if Tekst = ILineBonus[Pet] then Ini.LineBonus := Pet;
+
+ // PartyPopup
+ Tekst := IniFile.ReadString('Advanced', 'PartyPopup', 'On');
+ for Pet := 0 to High(IPartyPopup) do
+ if Tekst = IPartyPopup[Pet] then Ini.PartyPopup := Pet;
+
+
+ // Joypad
+ Tekst := IniFile.ReadString('Controller', 'Joypad', IJoypad[0]);
+ for Pet := 0 to High(IJoypad) do
+ if Tekst = IJoypad[Pet] then Ini.Joypad := Pet;
+
+ // LCD
+ Tekst := IniFile.ReadString('Devices', 'LPT', ILPT[0]);
+ for Pet := 0 to High(ILPT) do
+ if Tekst = ILPT[Pet] then Ini.LPT := Pet;
+
+
+ // SongPath
+ if (Params.SongPath <> '') then
+ SongPath := IncludeTrailingPathDelimiter(Params.SongPath)
+ else
+ SongPath := IncludeTrailingPathDelimiter(IniFile.ReadString('Path', 'Songs', SongPath));
+
+ Filename := IniFile.FileName;
+ IniFile.Free;
+end;
+
+procedure TIni.Save;
+var
+ IniFile: TIniFile;
+ Tekst: string;
+ I: Integer;
+ S: String;
+begin
+ //if not (FileExists(GamePath + 'config.ini') and FileIsReadOnly(GamePath + 'config.ini')) then begin
+ if not (FileExists(Filename) and FileIsReadOnly(Filename)) then begin
+
+ IniFile := TIniFile.Create(Filename);
+
+ // Players
+ Tekst := IPlayers[Ini.Players];
+ IniFile.WriteString('Game', 'Players', Tekst);
+
+ // Difficulty
+ Tekst := IDifficulty[Ini.Difficulty];
+ IniFile.WriteString('Game', 'Difficulty', Tekst);
+
+ // Language
+ Tekst := ILanguage[Ini.Language];
+ IniFile.WriteString('Game', 'Language', Tekst);
+
+ // Tabs
+ Tekst := ITabs[Ini.Tabs];
+ IniFile.WriteString('Game', 'Tabs', Tekst);
+
+ // Sorting
+ Tekst := ISorting[Ini.Sorting];
+ IniFile.WriteString('Game', 'Sorting', Tekst);
+
+ // Debug
+ Tekst := IDebug[Ini.Debug];
+ IniFile.WriteString('Game', 'Debug', Tekst);
+
+ // Screens
+ Tekst := IScreens[Ini.Screens];
+ IniFile.WriteString('Graphics', 'Screens', Tekst);
+
+ // FullScreen
+ Tekst := IFullScreen[Ini.FullScreen];
+ IniFile.WriteString('Graphics', 'FullScreen', Tekst);
+
+ // Resolution
+ Tekst := IResolution[Ini.Resolution];
+ IniFile.WriteString('Graphics', 'Resolution', Tekst);
+
+ // Depth
+ Tekst := IDepth[Ini.Depth];
+ IniFile.WriteString('Graphics', 'Depth', Tekst);
+
+ // Resolution
+ Tekst := ITextureSize[Ini.TextureSize];
+ IniFile.WriteString('Graphics', 'TextureSize', Tekst);
+
+ // Sing Window
+ Tekst := ISingWindow[Ini.SingWindow];
+ IniFile.WriteString('Graphics', 'SingWindow', Tekst);
+
+ // Oscilloscope
+ Tekst := IOscilloscope[Ini.Oscilloscope];
+ IniFile.WriteString('Graphics', 'Oscilloscope', Tekst);
+
+ // Spectrum
+ Tekst := ISpectrum[Ini.Spectrum];
+ IniFile.WriteString('Graphics', 'Spectrum', Tekst);
+
+ // Spectrograph
+ Tekst := ISpectrograph[Ini.Spectrograph];
+ IniFile.WriteString('Graphics', 'Spectrograph', Tekst);
+
+ // Movie Size
+ Tekst := IMovieSize[Ini.MovieSize];
+ IniFile.WriteString('Graphics', 'MovieSize', Tekst);
+
+ // MicBoost
+ Tekst := IMicBoost[Ini.MicBoost];
+ IniFile.WriteString('Sound', 'MicBoost', Tekst);
+
+ // ClickAssist
+ Tekst := IClickAssist[Ini.ClickAssist];
+ IniFile.WriteString('Sound', 'ClickAssist', Tekst);
+
+ // BeatClick
+ Tekst := IBeatClick[Ini.BeatClick];
+ IniFile.WriteString('Sound', 'BeatClick', Tekst);
+
+ // Threshold
+ Tekst := IThreshold[Ini.Threshold];
+ IniFile.WriteString('Sound', 'Threshold', Tekst);
+
+ // Song Preview
+ Tekst := IPreviewVolume[Ini.PreviewVolume];
+ IniFile.WriteString('Sound', 'PreviewVolume', Tekst);
+
+ Tekst := IPreviewFading[Ini.PreviewFading];
+ IniFile.WriteString('Sound', 'PreviewFading', Tekst);
+
+ // SavePlayback
+ Tekst := ISavePlayback[Ini.SavePlayback];
+ IniFile.WriteString('Sound', 'SavePlayback', Tekst);
+
+ // Lyrics Font
+ Tekst := ILyricsFont[Ini.LyricsFont];
+ IniFile.WriteString('Lyrics', 'LyricsFont', Tekst);
+
+ // Lyrics Effect
+ Tekst := ILyricsEffect[Ini.LyricsEffect];
+ IniFile.WriteString('Lyrics', 'LyricsEffect', Tekst);
+
+ // Solmization
+ Tekst := ISolmization[Ini.Solmization];
+ IniFile.WriteString('Lyrics', 'Solmization', Tekst);
+
+ // Theme
+ Tekst := ITheme[Ini.Theme];
+ IniFile.WriteString('Themes', 'Theme', Tekst);
+
+ // Skin
+ Tekst := ISkin[Ini.SkinNo];
+ IniFile.WriteString('Themes', 'Skin', Tekst);
+
+ // Color
+ Tekst := IColor[Ini.Color];
+ IniFile.WriteString('Themes', 'Color', Tekst);
+
+ // Record
+ for I := 0 to High(InputDeviceConfig) do begin
+ S := IntToStr(I+1);
+
+ Tekst := InputDeviceConfig[I].Name;
+ IniFile.WriteString('Record', 'DeviceName' + S, Tekst);
+
+ Tekst := IntToStr(InputDeviceConfig[I].Input);
+ IniFile.WriteString('Record', 'Input' + S, Tekst);
+
+ Tekst := IntToStr(InputDeviceConfig[I].ChannelToPlayerMap[0]);
+ IniFile.WriteString('Record', 'ChannelL' + S, Tekst);
+
+ Tekst := IntToStr(InputDeviceConfig[I].ChannelToPlayerMap[1]);
+ IniFile.WriteString('Record', 'ChannelR' + S, Tekst);
+ end;
+
+ //Log.LogError(InttoStr(Length(CardList)) + ' Cards Saved');
+
+ //Advanced Settings
+
+ //LoadAnimation
+ Tekst := ILoadAnimation[Ini.LoadAnimation];
+ IniFile.WriteString('Advanced', 'LoadAnimation', Tekst);
+
+ //EffectSing
+ Tekst := IEffectSing[Ini.EffectSing];
+ IniFile.WriteString('Advanced', 'EffectSing', Tekst);
+
+ //ScreenFade
+ Tekst := IScreenFade[Ini.ScreenFade];
+ IniFile.WriteString('Advanced', 'ScreenFade', Tekst);
+
+ //AskbeforeDel
+ Tekst := IAskbeforeDel[Ini.AskbeforeDel];
+ IniFile.WriteString('Advanced', 'AskbeforeDel', Tekst);
+
+ //OnSongClick
+ Tekst := IOnSongClick[Ini.OnSongClick];
+ IniFile.WriteString('Advanced', 'OnSongClick', Tekst);
+
+ //Line Bonus
+ Tekst := ILineBonus[Ini.LineBonus];
+ IniFile.WriteString('Advanced', 'LineBonus', Tekst);
+
+ //Party Popup
+ Tekst := IPartyPopup[Ini.PartyPopup];
+ IniFile.WriteString('Advanced', 'PartyPopup', Tekst);
+
+ // Joypad
+ Tekst := IJoypad[Ini.Joypad];
+ IniFile.WriteString('Controller', 'Joypad', Tekst);
+
+ IniFile.Free;
+ end;
+end;
+
+procedure TIni.SaveNames;
+var
+ IniFile: TIniFile;
+ I: integer;
+begin
+ //if not FileIsReadOnly(GamePath + 'config.ini') then begin
+ //IniFile := TIniFile.Create(GamePath + 'config.ini');
+ if not FileIsReadOnly(Filename) then begin
+ IniFile := TIniFile.Create(Filename);
+
+ //Name
+ // Templates for Names Mod
+ for I := 1 to 12 do
+ IniFile.WriteString('Name', 'P' + IntToStr(I), Ini.Name[I-1]);
+ for I := 1 to 3 do
+ IniFile.WriteString('NameTeam', 'T' + IntToStr(I), Ini.NameTeam[I-1]);
+ for I := 1 to 12 do
+ IniFile.WriteString('NameTemplate', 'Name' + IntToStr(I), Ini.NameTemplate[I-1]);
+
+ IniFile.Free;
+ end;
+end;
+
+procedure TIni.SaveLevel;
+var
+ IniFile: TIniFile;
+ I: integer;
+begin
+ //if not FileIsReadOnly(GamePath + 'config.ini') then begin
+ //IniFile := TIniFile.Create(GamePath + 'config.ini');
+ if not FileIsReadOnly(Filename) then begin
+ IniFile := TIniFile.Create(Filename);
+
+ // Difficulty
+ IniFile.WriteString('Game', 'Difficulty', IDifficulty[Ini.Difficulty]);
+
+ IniFile.Free;
+ end;
+end;
+
+end.
diff --git a/Game/Code/Classes/UMain.pas b/Game/Code/Classes/UMain.pas index 901d7370..801a66db 100644 --- a/Game/Code/Classes/UMain.pas +++ b/Game/Code/Classes/UMain.pas @@ -195,23 +195,14 @@ begin Log.BenchmarkEnd(1); Log.LogBenchmark('Loading Skin List', 1); -(* - // Sound Card List - Log.BenchmarkStart(1); - Log.LogStatus('Loading Soundcard list', 'Initialization'); - Recording := TRecord.Create; - Log.BenchmarkEnd(1); - Log.LogBenchmark('Loading Soundcard list', 1); -*) - - // Sound (+ fills Sound Card List) + // Sound Log.BenchmarkStart(1); Log.LogStatus('Initialize Sound', 'Initialization'); InitializeSound(); Log.BenchmarkEnd(1); Log.LogBenchmark('Initializing Sound', 1); - // Ini + Paths + // Ini + Paths (depends on Sound) Log.BenchmarkStart(1); Log.LogStatus('Load Ini', 'Initialization'); Ini := TIni.Create; @@ -758,7 +749,7 @@ begin // beat click if (Ini.BeatClick = 1) and ((Czas.AktBeatC + Czesci[0].Resolution + Czesci[0].NotesGAP) mod Czesci[0].Resolution = 0) then - AudioPlayback.PlayClick; + AudioPlayback.PlaySound(SoundLib.Click); // debug system on LPT if ((Czas.AktBeatC + Czesci[0].Resolution + Czesci[0].NotesGAP) mod Czesci[0].Resolution = 0) then begin @@ -780,7 +771,7 @@ begin if (Czesci[0].Czesc[Czesci[0].Akt].Nuta[Pet].Start = Czas.AktBeatC) then begin // click assist if Ini.ClickAssist = 1 then - AudioPlayback.PlayClick; + AudioPlayback.PlaySound(SoundLib.Click); //LPT_2 := 0; if ParamStr(1) <> '-doublelights' then @@ -871,7 +862,7 @@ begin // Czas.Ton := 27; // gdy moze, to dodaje nute - if (AudioInputProcessor.Sound[CP].SzczytJest) and (Mozna) then begin + if (AudioInputProcessor.Sound[CP].ToneValid) and (Mozna) then begin // operowanie na ostatniej nucie for Pet := 0 to Czesci[0].Czesc[S].HighNut do if (Czesci[0].Czesc[S].Nuta[Pet].Start <= Czas.OldBeatD+1) @@ -880,11 +871,11 @@ begin // to robi, tylko dla pary nut (oryginalnej i gracza) // przesuwanie tonu w odpowiednia game - while (AudioInputProcessor.Sound[CP].Ton - Czesci[0].Czesc[S].Nuta[Pet].Ton > 6) do - AudioInputProcessor.Sound[CP].Ton := AudioInputProcessor.Sound[CP].Ton - 12; + while (AudioInputProcessor.Sound[CP].Tone - Czesci[0].Czesc[S].Nuta[Pet].Ton > 6) do + AudioInputProcessor.Sound[CP].Tone := AudioInputProcessor.Sound[CP].Tone - 12; - while (AudioInputProcessor.Sound[CP].Ton - Czesci[0].Czesc[S].Nuta[Pet].Ton < -6) do - AudioInputProcessor.Sound[CP].Ton := AudioInputProcessor.Sound[CP].Ton + 12; + while (AudioInputProcessor.Sound[CP].Tone - Czesci[0].Czesc[S].Nuta[Pet].Ton < -6) do + AudioInputProcessor.Sound[CP].Tone := AudioInputProcessor.Sound[CP].Tone + 12; // Half size Notes Patch NoteHit := false; @@ -894,8 +885,8 @@ begin //if Ini.Difficulty = 2 then Range := 0; Range := 2 - Ini.Difficulty; - if abs(Czesci[0].Czesc[S].Nuta[Pet].Ton - AudioInputProcessor.Sound[CP].Ton) <= Range then begin - AudioInputProcessor.Sound[CP].Ton := Czesci[0].Czesc[S].Nuta[Pet].Ton; + if abs(Czesci[0].Czesc[S].Nuta[Pet].Ton - AudioInputProcessor.Sound[CP].Tone) <= Range then begin + AudioInputProcessor.Sound[CP].Tone := Czesci[0].Czesc[S].Nuta[Pet].Ton; // Half size Notes Patch @@ -936,7 +927,7 @@ begin Nowa := true; // jezeli ostatnia ma ten sam ton if (Player[CP].IlNut > 0 ) - and (Player[CP].Nuta[Player[CP].HighNut].Ton = AudioInputProcessor.Sound[CP].Ton) + and (Player[CP].Nuta[Player[CP].HighNut].Ton = AudioInputProcessor.Sound[CP].Tone) and (Player[CP].Nuta[Player[CP].HighNut].Start + Player[CP].Nuta[Player[CP].HighNut].Dlugosc = Czas.AktBeatD) then Nowa := false; // jezeli jest jakas nowa nuta na sprawdzanym beacie @@ -952,7 +943,7 @@ begin SetLength(Player[CP].Nuta, Player[CP].IlNut); Player[CP].Nuta[Player[CP].HighNut].Start := Czas.AktBeatD; Player[CP].Nuta[Player[CP].HighNut].Dlugosc := 1; - Player[CP].Nuta[Player[CP].HighNut].Ton := AudioInputProcessor.Sound[CP].Ton; // Ton || TonDokl + Player[CP].Nuta[Player[CP].HighNut].Ton := AudioInputProcessor.Sound[CP].Tone; // Ton || TonDokl Player[CP].Nuta[Player[CP].HighNut].Detekt := Czas.MidBeat; diff --git a/Game/Code/Classes/UMedia_dummy.pas b/Game/Code/Classes/UMedia_dummy.pas index c973512d..cd62dc51 100644 --- a/Game/Code/Classes/UMedia_dummy.pas +++ b/Game/Code/Classes/UMedia_dummy.pas @@ -1,268 +1,206 @@ -unit UMedia_dummy; -{< ############################################################################# -# FFmpeg support for UltraStar deluxe # -# # -# Created by b1indy # -# based on 'An ffmpeg and SDL Tutorial' (http://www.dranger.com/ffmpeg/) # -# # -# http://www.mail-archive.com/fpc-pascal@lists.freepascal.org/msg09949.html # -# http://www.nabble.com/file/p11795857/mpegpas01.zip # -# # -############################################################################## } - -interface - -{$IFDEF FPC} - {$MODE Delphi} -{$ENDIF} - -{$I switches.inc} - -implementation - -uses - SysUtils, - math, - UMusic; - - -var - singleton_dummy : IVideoPlayback; - -type - Tmedia_dummy = class( TInterfacedObject, IVideoPlayback, IVideoVisualization, IAudioPlayback, IAudioInput ) - private - public - constructor create(); - function GetName: String; - - procedure init(); - - function Open( aFileName : string): boolean; // true if succeed - procedure Close; - - procedure Play; - procedure Pause; - procedure Stop; - - procedure SetPosition(Time: real); - function GetPosition: real; - - procedure GetFrame(Time: Extended); - procedure DrawGL(Screen: integer); - - // IAudioInput - procedure InitializeRecord; - procedure CaptureStart; - procedure CaptureStop; - procedure CaptureCard(RecordI, PlayerLeft, PlayerRight: byte); - procedure StopCard(Card: byte); - function GetFFTData: TFFTData; - function GetPCMData(var data: TPCMData): Cardinal; - - // IAudioPlayback - procedure InitializePlayback; - procedure SetVolume(Volume: integer); - procedure SetMusicVolume(Volume: integer); - procedure SetLoop(Enabled: boolean); - procedure Rewind; - - function Finished: boolean; - function Length: real; - - procedure PlayStart; - procedure PlayBack; - procedure PlaySwoosh; - procedure PlayChange; - procedure PlayOption; - procedure PlayClick; - procedure PlayDrum; - procedure PlayHihat; - procedure PlayClap; - procedure PlayShuffle; - procedure StopShuffle; - - function LoadCustomSound(const Filename: String): Cardinal; - procedure PlayCustomSound(const Index: Cardinal ); - - end; - - - -function Tmedia_dummy.GetName: String; -begin - result := 'dummy'; -end; - - -procedure Tmedia_dummy.GetFrame(Time: Extended); -begin -end; - -procedure Tmedia_dummy.DrawGL(Screen: integer); -begin -end; - -constructor Tmedia_dummy.create(); -begin -end; - -procedure Tmedia_dummy.init(); -begin -end; - - -function Tmedia_dummy.Open( aFileName : string): boolean; // true if succeed -begin - result := false; -end; - -procedure Tmedia_dummy.Close; -begin -end; - -procedure Tmedia_dummy.Play; -begin -end; - -procedure Tmedia_dummy.Pause; -begin -end; - -procedure Tmedia_dummy.Stop; -begin -end; - -procedure Tmedia_dummy.SetPosition(Time: real); -begin -end; - -function Tmedia_dummy.getPosition: real; -begin - result := 0; -end; - -// IAudioInput -procedure Tmedia_dummy.InitializeRecord; -begin -end; - -procedure Tmedia_dummy.CaptureStart; -begin -end; - -procedure Tmedia_dummy.CaptureStop; -begin -end; - -procedure Tmedia_dummy.CaptureCard(RecordI, PlayerLeft, PlayerRight: byte); -begin -end; - -procedure Tmedia_dummy.StopCard(Card: byte); -begin -end; - -function Tmedia_dummy.GetFFTData: TFFTData; -var data: TFFTData; -begin - result := data; -end; - -function Tmedia_dummy.GetPCMData(var data: TPCMData): Cardinal; -begin - result := 0; -end; - -// IAudioPlayback -procedure Tmedia_dummy.InitializePlayback; -begin -end; - -procedure Tmedia_dummy.SetVolume(Volume: integer); -begin -end; - -procedure Tmedia_dummy.SetMusicVolume(Volume: integer); -begin -end; - -procedure Tmedia_dummy.SetLoop(Enabled: boolean); -begin -end; - -procedure Tmedia_dummy.Rewind; -begin -end; - -function Tmedia_dummy.Finished: boolean; -begin - result := false; -end; - -function Tmedia_dummy.Length: real; -begin - Result := 60; -end; - -procedure Tmedia_dummy.PlayStart; -begin -end; - -procedure Tmedia_dummy.PlayBack; -begin -end; - -procedure Tmedia_dummy.PlaySwoosh; -begin -end; - -procedure Tmedia_dummy.PlayChange; -begin -end; - -procedure Tmedia_dummy.PlayOption; -begin -end; - -procedure Tmedia_dummy.PlayClick; -begin -end; - -procedure Tmedia_dummy.PlayDrum; -begin -end; - -procedure Tmedia_dummy.PlayHihat; -begin -end; - -procedure Tmedia_dummy.PlayClap; -begin -end; - -procedure Tmedia_dummy.PlayShuffle; -begin -end; - -procedure Tmedia_dummy.StopShuffle; -begin -end; - -function Tmedia_dummy.LoadCustomSound(const Filename: String): Cardinal; -begin - result := 0; -end; - -procedure Tmedia_dummy.PlayCustomSound(const Index: Cardinal ); -begin -end; - -initialization - singleton_dummy := Tmedia_dummy.create(); - AudioManager.add( singleton_dummy ); - -finalization - AudioManager.Remove( singleton_dummy ); - -end. +unit UMedia_dummy;
+{< #############################################################################
+# FFmpeg support for UltraStar deluxe #
+# #
+# Created by b1indy #
+# based on 'An ffmpeg and SDL Tutorial' (http://www.dranger.com/ffmpeg/) #
+# #
+# http://www.mail-archive.com/fpc-pascal@lists.freepascal.org/msg09949.html #
+# http://www.nabble.com/file/p11795857/mpegpas01.zip #
+# #
+############################################################################## }
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+implementation
+
+uses
+ SysUtils,
+ math,
+ UMusic;
+
+
+var
+ singleton_dummy : IVideoPlayback;
+
+type
+ Tmedia_dummy = class( TInterfacedObject, IVideoPlayback, IVideoVisualization, IAudioPlayback, IAudioInput )
+ private
+ public
+ constructor create();
+ function GetName: String;
+
+ procedure init();
+
+ function Open( aFileName : string): boolean; // true if succeed
+ procedure Close;
+
+ procedure Play;
+ procedure Pause;
+ procedure Stop;
+
+ procedure SetPosition(Time: real);
+ function GetPosition: real;
+
+ procedure GetFrame(Time: Extended);
+ procedure DrawGL(Screen: integer);
+
+ // IAudioInput
+ function InitializeRecord: boolean;
+ procedure CaptureStart;
+ procedure CaptureStop;
+ procedure GetFFTData(var data: TFFTData);
+ function GetPCMData(var data: TPCMData): Cardinal;
+
+ // IAudioPlayback
+ function InitializePlayback: boolean;
+ procedure SetVolume(Volume: integer);
+ procedure SetMusicVolume(Volume: integer);
+ procedure SetLoop(Enabled: boolean);
+ procedure Rewind;
+
+ function Finished: boolean;
+ function Length: real;
+
+ function OpenSound(const Filename: String): TAudioPlaybackStream;
+ procedure PlaySound(stream: TAudioPlaybackStream);
+ procedure StopSound(stream: TAudioPlaybackStream);
+ end;
+
+
+
+function Tmedia_dummy.GetName: String;
+begin
+ result := 'dummy';
+end;
+
+
+procedure Tmedia_dummy.GetFrame(Time: Extended);
+begin
+end;
+
+procedure Tmedia_dummy.DrawGL(Screen: integer);
+begin
+end;
+
+constructor Tmedia_dummy.create();
+begin
+end;
+
+procedure Tmedia_dummy.init();
+begin
+end;
+
+
+function Tmedia_dummy.Open( aFileName : string): boolean; // true if succeed
+begin
+ result := false;
+end;
+
+procedure Tmedia_dummy.Close;
+begin
+end;
+
+procedure Tmedia_dummy.Play;
+begin
+end;
+
+procedure Tmedia_dummy.Pause;
+begin
+end;
+
+procedure Tmedia_dummy.Stop;
+begin
+end;
+
+procedure Tmedia_dummy.SetPosition(Time: real);
+begin
+end;
+
+function Tmedia_dummy.getPosition: real;
+begin
+ result := 0;
+end;
+
+// IAudioInput
+function Tmedia_dummy.InitializeRecord: boolean;
+begin
+ result := true;
+end;
+
+procedure Tmedia_dummy.CaptureStart;
+begin
+end;
+
+procedure Tmedia_dummy.CaptureStop;
+begin
+end;
+
+procedure Tmedia_dummy.GetFFTData(var data: TFFTData);
+begin
+end;
+
+function Tmedia_dummy.GetPCMData(var data: TPCMData): Cardinal;
+begin
+ result := 0;
+end;
+
+// IAudioPlayback
+function Tmedia_dummy.InitializePlayback: boolean;
+begin
+ result := true;
+end;
+
+procedure Tmedia_dummy.SetVolume(Volume: integer);
+begin
+end;
+
+procedure Tmedia_dummy.SetMusicVolume(Volume: integer);
+begin
+end;
+
+procedure Tmedia_dummy.SetLoop(Enabled: boolean);
+begin
+end;
+
+procedure Tmedia_dummy.Rewind;
+begin
+end;
+
+function Tmedia_dummy.Finished: boolean;
+begin
+ result := false;
+end;
+
+function Tmedia_dummy.Length: real;
+begin
+ Result := 60;
+end;
+
+function Tmedia_dummy.OpenSound(const Filename: String): TAudioPlaybackStream;
+begin
+ result := nil;
+end;
+
+procedure Tmedia_dummy.PlaySound(stream: TAudioPlaybackStream);
+begin
+end;
+
+procedure Tmedia_dummy.StopSound(stream: TAudioPlaybackStream);
+begin
+end;
+
+initialization
+ singleton_dummy := Tmedia_dummy.create();
+ AudioManager.add( singleton_dummy );
+
+finalization
+ AudioManager.Remove( singleton_dummy );
+
+end.
diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas index a7f1918f..27ab86e1 100644 --- a/Game/Code/Classes/UMusic.pas +++ b/Game/Code/Classes/UMusic.pas @@ -1,423 +1,492 @@ -unit UMusic; - -interface - -{$IFDEF FPC} - {$MODE Delphi} -{$ENDIF} - -{$I switches.inc} - -uses Classes ; - -type - TMuzyka = record - Path: string; - Start: integer; // start of song in ms - IlNut: integer; - DlugoscNut: integer; - end; - - PLine = ^TLine; - TLine = record - Start: integer; - StartNote: integer; - Lyric: string; - LyricWidth: real; - Koniec: integer; - BaseNote: integer; - HighNut: integer; - IlNut: integer; - TotalNotes: integer; - Nuta: array of record - Color: integer; - Start: integer; - Dlugosc: integer; - Ton: integer; - TonGamy: integer; - Tekst: string; - FreeStyle: boolean; - Wartosc: integer; // zwykla nuta x1, zlota nuta x2 - end; - end; - ALine = array of TLine; - - TCzesci = record - Akt: integer; // aktualna czesc utworu do rysowania - High: integer; - Ilosc: integer; - Resolution: integer; - NotesGAP: integer; - Wartosc: integer; - Czesc: ALine; - end; - - TCzas = record // wszystko, co dotyczy aktualnej klatki - OldBeat: integer; // poprzednio wykryty beat w utworze - AktBeat: integer; // aktualny beat w utworze - MidBeat: real; // dokladny AktBeat - - // now we use this for super synchronization! - // only used when analyzing voice - OldBeatD: integer; // poprzednio wykryty beat w utworze - AktBeatD: integer; // aktualny beat w utworze - MidBeatD: real; // dokladny AktBeatD - FracBeatD: real; // fractional part of MidBeatD - - // we use this for audiable clicks - OldBeatC: integer; // poprzednio wykryty beat w utworze - AktBeatC: integer; // aktualny beat w utworze - MidBeatC: real; // dokladny AktBeatC - FracBeatC: real; // fractional part of MidBeatC - - - OldCzesc: integer; // poprzednio wyswietlana czesc - // akt jest w czesci.akt - - Teraz: real; // aktualny czas w utworze - Razem: real; // caly czas utworu - end; - - TSoundCard = record - Name: string; - Source: array of string; - end; - -type - TFFTData = array[0..256] of Single; - - TPCMStereoSample = array[0..1] of Smallint; - TPCMData = array[0..511] of TPCMStereoSample; - -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 : TAudioPlaybackStream; - end; - -type - IGenericPlayback = Interface - ['{63A5EBC3-3F4D-4F23-8DFB-B5165FCE33DD}'] - function GetName: String; - - function Open(Filename: string): boolean; // true if succeed - procedure Close; - - procedure Play; - procedure Pause; - procedure Stop; - - 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 - - end; - - IVideoVisualization = Interface( IVideoPlayback ) - ['{5AC17D60-B34D-478D-B632-EB00D4078017}'] - end; - - IAudioPlayback = Interface( IGenericPlayback ) - ['{E4AE0B40-3C21-4DC5-847C-20A87E0DFB96}'] - procedure InitializePlayback; - procedure SetVolume(Volume: integer); - procedure SetMusicVolume(Volume: integer); - procedure SetLoop(Enabled: boolean); - - procedure Rewind; - function Finished: boolean; - function Length: real; - - procedure PlayStart; - procedure PlayBack; - procedure PlaySwoosh; - procedure PlayChange; - procedure PlayOption; - procedure PlayClick; - procedure PlayDrum; - procedure PlayHihat; - procedure PlayClap; - procedure PlayShuffle; - procedure StopShuffle; - - //Custom Sounds - function LoadCustomSound(const Filename: String): Cardinal; - procedure PlayCustomSound(const Index: Cardinal ); - - //Equalizer - function GetFFTData: TFFTData; - - // Interface for Visualizer - 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; - procedure InitializeRecord; - - procedure CaptureStart; - procedure CaptureStop; - end; - - -var // TODO : JB --- THESE SHOULD NOT BE GLOBAL - // muzyka - Muzyka: TMuzyka; - - // czesci z nutami; - Czesci: array of TCzesci; - - // czas - Czas: TCzas; - - -procedure InitializeSound; - -function Visualization(): IVideoPlayback; -function VideoPlayback(): IVideoPlayback; -function AudioPlayback(): IAudioPlayback; -function AudioInput(): IAudioInput; -function AudioDecoder(): IAudioDecoder; - -function AudioManager: TInterfaceList; - - -implementation - -uses - sysutils, - UCommandLine; -// uLog; - -var - singleton_VideoPlayback : IVideoPlayback = nil; - singleton_Visualization : IVideoPlayback = nil; - singleton_AudioPlayback : IAudioPlayback = nil; - singleton_AudioInput : IAudioInput = nil; - singleton_AudioDecoder : IAudioDecoder = nil; - - singleton_AudioManager : TInterfaceList = nil; - - -function AudioManager: TInterfaceList; -begin - if singleton_AudioManager = nil then - singleton_AudioManager := TInterfaceList.Create(); - - Result := singleton_AudioManager; -end; //CompressionPluginManager - - -function VideoPlayback(): IVideoPlayback; -begin - result := singleton_VideoPlayback; -end; - -function Visualization(): IVideoPlayback; -begin - result := singleton_Visualization; -end; - -function AudioPlayback(): IAudioPlayback; -begin - result := singleton_AudioPlayback; -end; - -function AudioInput(): IAudioInput; -begin - result := singleton_AudioInput; -end; - -function AudioDecoder(): IAudioDecoder; -begin - result := singleton_AudioDecoder; -end; - -procedure InitializeSound; -var - lTmpInterface : IInterface; - iCount : Integer; -begin - lTmpInterface := nil; - - singleton_AudioPlayback := nil; - singleton_AudioInput := nil; - singleton_AudioDecoder := nil; - singleton_VideoPlayback := nil; - singleton_Visualization := nil; - - for iCount := 0 to AudioManager.Count - 1 do - begin - if assigned( AudioManager[iCount] ) then - begin - // if this interface is a Playback, then set it as the default used - - if ( AudioManager[iCount].QueryInterface( IAudioPlayback, lTmpInterface ) = 0 ) AND - ( true ) then - begin - singleton_AudioPlayback := IAudioPlayback( lTmpInterface ); - end; - - // if this interface is a Input, then set it as the default used - if ( AudioManager[iCount].QueryInterface( IAudioInput, lTmpInterface ) = 0 ) AND - ( true ) then - 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 - begin - singleton_VideoPlayback := IVideoPlayback( lTmpInterface ); - end; - - if ( AudioManager[iCount].QueryInterface( IVideoVisualization, lTmpInterface ) = 0 ) AND - ( true ) then - begin - singleton_Visualization := IVideoPlayback( lTmpInterface ); - end; - - end; - end; - - - - if VideoPlayback <> nil then - begin - end; - - if AudioDecoder <> nil then - begin - AudioDecoder.InitializeDecoder; - end; - - if AudioPlayback <> nil then - begin - AudioPlayback.InitializePlayback; - end; - - if AudioInput <> nil then - begin - AudioInput.InitializeRecord; - end; - - 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 - singleton_AudioManager := TInterfaceList.Create(); - -end; - -finalization - singleton_AudioManager.clear; - FreeAndNil( singleton_AudioManager ); - -end. +unit UMusic;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+ Classes;
+
+type
+ TNoteType = (ntFreestyle, ntNormal, ntGolden);
+
+ //http://paste.ubuntu-nl.org/51892/
+
+ TMuzyka = record // (TODO: rename to TMusic/TMelody?)
+ Path: string;
+ Start: integer; // start of song in ms
+ IlNut: integer; // (TODO: Il = tone, Nut(a) = Note)
+ DlugoscNut: integer; // (TODO: Dlugosc = length, Nut(a) = Note)
+ end;
+
+ PLine = ^TLine;
+ TLine = record // (TODO: rename to TSentence?)
+ Start: integer;
+ StartNote: integer;
+ Lyric: string;
+ LyricWidth: real;
+ Koniec: integer; // (TODO: rename to End_/Ending?)
+ BaseNote: integer;
+ HighNut: integer; // (TODO: rename to HighNote)
+ IlNut: integer; // (TODO: Il = tone, Nut(a) = Note)
+ TotalNotes: integer;
+ Nuta: array of record // (TODO: rename to Note)
+ Color: integer;
+ Start: integer;
+ Dlugosc: integer; // (TODO: rename to Length)
+ Ton: integer; // full range tone (TODO: rename to Tone)
+ TonGamy: integer; // tone unified to one octave (TODO: rename to something meaningful, ToneGamus)
+ Tekst: string; // (TODO: rename to Text)
+ FreeStyle: boolean;
+ Wartosc: integer; // normal-note: 1, golden-note: 2 (TODO: wartosc=value, rename to Type_ or Kind?)
+ end;
+ end;
+ ALine = array of TLine; // (TODO: rename to TLineArray)
+
+ // (TCzesci = TSentences)
+ TCzesci = record
+ Akt: integer; // for drawing of current line (Akt = Current)
+ High: integer;
+ Ilosc: integer; // (TODO: Ilosc = Number/Count)
+ Resolution: integer;
+ NotesGAP: integer;
+ Wartosc: integer; // TODO: rename (wartosc=value)
+ Czesc: ALine; // TODO: rename to Sentence or Line
+ end;
+
+ // (TODO: rename TCzas to something like T(Line/Sentence)Time/TLinePosition/TLineState)
+ // (Czas = time)
+ TCzas = record // all that concerns the current frames
+ OldBeat: integer; // previous discovered beat
+ AktBeat: integer; // current beat (TODO: rename)
+ MidBeat: real; // like AktBeat
+
+ // now we use this for super synchronization!
+ // only used when analyzing voice
+ OldBeatD: integer; // previous discovered beat
+ AktBeatD: integer; // current beat (TODO: rename)
+ MidBeatD: real; // like AktBeatD
+ FracBeatD: real; // fractional part of MidBeatD
+
+ // we use this for audible clicks
+ OldBeatC: integer; // previous discovered beat
+ AktBeatC: integer; // current beat (TODO: rename)
+ MidBeatC: real; // like AktBeatC
+ FracBeatC: real; // fractional part of MidBeatC
+
+
+ OldCzesc: integer; // previous displayed sentence (Czesc = part (here: sentence/line))
+
+ Teraz: real; // (TODO: Teraz = current time)
+ Razem: real; // (TODO: Razem = total time)
+ end;
+
+
+type
+ TFFTData = array[0..255] of Single;
+
+ TPCMStereoSample = array[0..1] of Smallint;
+ TPCMData = array[0..511] of TPCMStereoSample;
+
+type
+ TStreamStatus = (ssStopped, ssPlaying, ssPaused, ssBlocked, ssUnknown);
+const
+ StreamStatusStr: array[TStreamStatus] of string =
+ ('Stopped', 'Playing', 'Paused', 'Blocked', 'Unknown');
+
+type
+ TAudioSampleFormat = (
+ asfU8, asfS8, // unsigned/signed 8 bits
+ asfU16LSB, asfS16LSB, // unsigned/signed 16 bits (endianness: LSB)
+ asfU16MSB, asfS16MSB, // unsigned/signed 16 bits (endianness: MSB)
+ asfU16, asfS16, // unsigned/signed 16 bits (endianness: System)
+ asfS24, // signed 24 bits (endianness: System)
+ asfS32, // signed 32 bits (endianness: System)
+ asfFloat // float
+ );
+
+ TAudioFormatInfo = record
+ Channels: byte;
+ SampleRate: integer;
+ Format: TAudioSampleFormat;
+ end;
+
+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;
+ function GetVolume(): integer; virtual; abstract;
+ procedure SetVolume(volume: integer); 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;
+ property Volume: integer READ GetVolume WRITE SetVolume;
+ 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 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;
+ function GetAudioFormatInfo(): TAudioFormatInfo; virtual; abstract;
+
+ property Length: real READ GetLength;
+ property Position: real READ GetPosition WRITE SetPosition;
+ property EOF: boolean READ IsEOF;
+ end;
+
+type
+ IGenericPlayback = Interface
+ ['{63A5EBC3-3F4D-4F23-8DFB-B5165FCE33DD}']
+ function GetName: String;
+
+ function Open(Filename: string): boolean; // true if succeed
+ procedure Close;
+
+ procedure Play;
+ procedure Pause;
+ procedure Stop;
+
+ 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
+
+ end;
+
+ IVideoVisualization = Interface( IVideoPlayback )
+ ['{5AC17D60-B34D-478D-B632-EB00D4078017}']
+ end;
+
+ IAudioPlayback = Interface( IGenericPlayback )
+ ['{E4AE0B40-3C21-4DC5-847C-20A87E0DFB96}']
+ function InitializePlayback: boolean;
+ procedure SetVolume(Volume: integer);
+ procedure SetMusicVolume(Volume: integer);
+ procedure SetLoop(Enabled: boolean);
+
+ procedure Rewind;
+ function Finished: boolean;
+ function Length: real;
+
+ // Sounds
+ function OpenSound(const Filename: String): TAudioPlaybackStream;
+ procedure PlaySound(stream: TAudioPlaybackStream);
+ procedure StopSound(stream: TAudioPlaybackStream);
+
+ // Equalizer
+ procedure GetFFTData(var data: TFFTData);
+
+ // Interface for Visualizer
+ 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;
+ function InitializeRecord: boolean;
+
+ procedure CaptureStart;
+ procedure CaptureStop;
+ end;
+
+type
+ TSoundLibrary = class
+ public
+ Start: TAudioPlaybackStream;
+ Back: TAudioPlaybackStream;
+ Swoosh: TAudioPlaybackStream;
+ Change: TAudioPlaybackStream;
+ Option: TAudioPlaybackStream;
+ Click: TAudioPlaybackStream;
+ Drum: TAudioPlaybackStream;
+ Hihat: TAudioPlaybackStream;
+ Clap: TAudioPlaybackStream;
+ Shuffle: TAudioPlaybackStream;
+
+ constructor Create();
+ destructor Destroy(); override;
+ end;
+
+var // TODO : JB --- THESE SHOULD NOT BE GLOBAL
+ // music
+ Muzyka: TMuzyka; // TODO: rename
+
+ // czesci z nutami;
+ Czesci: array of TCzesci; // TODO: rename to Sentences/Lines
+
+ // czas
+ Czas: TCzas; // TODO: rename
+
+ SoundLib: TSoundLibrary;
+
+
+procedure InitializeSound;
+
+function Visualization(): IVideoPlayback;
+function VideoPlayback(): IVideoPlayback;
+function AudioPlayback(): IAudioPlayback;
+function AudioInput(): IAudioInput;
+function AudioDecoder(): IAudioDecoder;
+
+function AudioManager: TInterfaceList;
+
+
+implementation
+
+uses
+ sysutils,
+ UMain,
+ UCommandLine;
+// uLog;
+
+var
+ singleton_VideoPlayback : IVideoPlayback = nil;
+ singleton_Visualization : IVideoPlayback = nil;
+ singleton_AudioPlayback : IAudioPlayback = nil;
+ singleton_AudioInput : IAudioInput = nil;
+ singleton_AudioDecoder : IAudioDecoder = nil;
+
+ singleton_AudioManager : TInterfaceList = nil;
+
+
+function AudioManager: TInterfaceList;
+begin
+ if singleton_AudioManager = nil then
+ singleton_AudioManager := TInterfaceList.Create();
+
+ Result := singleton_AudioManager;
+end; //CompressionPluginManager
+
+
+function VideoPlayback(): IVideoPlayback;
+begin
+ result := singleton_VideoPlayback;
+end;
+
+function Visualization(): IVideoPlayback;
+begin
+ result := singleton_Visualization;
+end;
+
+function AudioPlayback(): IAudioPlayback;
+begin
+ result := singleton_AudioPlayback;
+end;
+
+function AudioInput(): IAudioInput;
+begin
+ result := singleton_AudioInput;
+end;
+
+function AudioDecoder(): IAudioDecoder;
+begin
+ result := singleton_AudioDecoder;
+end;
+
+procedure InitializeSound;
+var
+ lTmpInterface : IInterface;
+ iCount : Integer;
+begin
+ lTmpInterface := nil;
+
+ singleton_AudioPlayback := nil;
+ singleton_AudioInput := nil;
+ singleton_AudioDecoder := nil;
+ singleton_VideoPlayback := nil;
+ singleton_Visualization := nil;
+
+ for iCount := 0 to AudioManager.Count - 1 do
+ begin
+ if assigned( AudioManager[iCount] ) then
+ begin
+ // if this interface is a Playback, then set it as the default used
+
+ if ( AudioManager[iCount].QueryInterface( IAudioPlayback, lTmpInterface ) = 0 ) AND
+ ( true ) then
+ begin
+ singleton_AudioPlayback := IAudioPlayback( lTmpInterface );
+ end;
+
+ // if this interface is a Input, then set it as the default used
+ if ( AudioManager[iCount].QueryInterface( IAudioInput, lTmpInterface ) = 0 ) AND
+ ( true ) then
+ 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
+ begin
+ singleton_VideoPlayback := IVideoPlayback( lTmpInterface );
+ end;
+
+ if ( AudioManager[iCount].QueryInterface( IVideoVisualization, lTmpInterface ) = 0 ) AND
+ ( true ) then
+ begin
+ singleton_Visualization := IVideoPlayback( lTmpInterface );
+ end;
+
+ end;
+ end;
+
+
+
+ if VideoPlayback <> nil then
+ begin
+ end;
+
+ if AudioDecoder <> nil then
+ begin
+ AudioDecoder.InitializeDecoder;
+ end;
+
+ if AudioPlayback <> nil then
+ begin
+ AudioPlayback.InitializePlayback;
+ end;
+
+ if AudioInput <> nil then
+ begin
+ AudioInput.InitializeRecord;
+ end;
+
+ // Load in-game sounds
+ SoundLib := TSoundLibrary.Create;
+
+ 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;
+
+constructor TSoundLibrary.Create();
+begin
+ //Log.LogStatus('Loading Sounds', 'Music Initialize');
+
+ //Log.BenchmarkStart(4);
+
+ Start := AudioPlayback.OpenSound(SoundPath + 'Common start.mp3');
+ (*
+ Back := AudioPlayback.OpenSound(SoundPath + 'Common back.mp3');
+ Swoosh := AudioPlayback.OpenSound(SoundPath + 'menu swoosh.mp3');
+ Change := AudioPlayback.OpenSound(SoundPath + 'select music change music 50.mp3');
+ Option := AudioPlayback.OpenSound(SoundPath + 'option change col.mp3');
+ Click := AudioPlayback.OpenSound(SoundPath + 'rimshot022b.mp3');
+ *)
+
+ //Drum := AudioPlayback.OpenSound(SoundPath + 'bassdrumhard076b.mp3');
+ //Hihat := AudioPlayback.OpenSound(SoundPath + 'hihatclosed068b.mp3');
+ //Clap := AudioPlayback.OpenSound(SoundPath + 'claps050b.mp3');
+
+ //Shuffle := AudioPlayback.OpenSound(SoundPath + 'Shuffle.mp3');
+
+ //Log.BenchmarkEnd(4);
+ //Log.LogBenchmark('--> Loading Sounds', 4);
+end;
+
+destructor TSoundLibrary.Destroy();
+begin
+ Start.Free;
+ Back.Free;
+ Swoosh.Free;
+ Change.Free;
+ Option.Free;
+ Click.Free;
+
+ //Drum.Free;
+ //Hihat.Free;
+ //Clap.Free;
+
+ //Shuffle.Free;
+end;
+
+
+initialization
+begin
+ singleton_AudioManager := TInterfaceList.Create();
+
+end;
+
+finalization
+ singleton_AudioManager.clear;
+ FreeAndNil( singleton_AudioManager );
+
+end.
diff --git a/Game/Code/Classes/URecord.pas b/Game/Code/Classes/URecord.pas index ab351f6e..8ae0978a 100644 --- a/Game/Code/Classes/URecord.pas +++ b/Game/Code/Classes/URecord.pas @@ -1,325 +1,535 @@ -unit URecord; - -interface - -{$IFDEF FPC} - {$MODE Delphi} -{$ENDIF} - -{$I switches.inc} - -uses Classes, - Math, - SysUtils, - UCommon, - UMusic, - UIni; - -// http://www.poltran.com - -type - TSound = class - BufferNew: TMemoryStream; // buffer for newest sample - BufferArray: array[1..4096] of smallint; // (Signal) newest 4096 samples - BufferLong: array of TMemoryStream; // full buffer - - Num: integer; - n: integer; // length of Signal to analyze - - // pitch detection - SzczytJest: boolean; // czy jest szczyt - pivot : integer; // Position of summit (top) on horizontal pivot - TonDokl: real; // ton aktualnego szczytu - Ton: integer; // ton bez ulamka - TonGamy: integer; // ton w gamie. wartosci: 0-11 - Skala: real; // skala FFT - - // procedures - procedure ProcessNewBuffer; - procedure AnalyzeBuffer; // use to analyze sound from buffers to get new pitch - procedure AnalyzeByAutocorrelation; // we call it to analyze sound by checking Autocorrelation - function AnalyzeAutocorrelationFreq(Freq: real): real; // use this to check one frequency by Autocorrelation - end; - - TSoundCardInput = record - Name: string; - end; - - TGenericSoundCard = class - // here can be the soundcard information - whole database from which user will select recording source - Description: string; // soundcard name/description - Input: array of TSoundCardInput; // soundcard input(-source)s - InputSelected: integer; // unused. What is this good for? - MicInput: integer; // unused. What is this good for? - //SampleRate: integer; // TODO: for sample-rate conversion (for devices that do not support 44.1kHz) - CaptureSoundLeft: TSound; // sound(-buffer) used for left channel capture data - CaptureSoundRight: TSound; // sound(-buffer) used for right channel capture data - end; - - TAudioInputProcessor = class - Sound: array of TSound; - SoundCard: array of TGenericSoundCard; - - constructor Create; - - // handle microphone input - procedure HandleMicrophoneData(Buffer: Pointer; Length: Cardinal; - InputDevice: TGenericSoundCard); - - function volume( aChannel : byte ): byte; - end; - - smallintarray = array [0..maxInt shr 1-1] of smallInt; - psmallintarray = ^smallintarray; - - function AudioInputProcessor(): TAudioInputProcessor; - -implementation - -uses UMain; - -var - singleton_AudioInputProcessor : TAudioInputProcessor = nil; - - -// FIXME: Race-Conditions between Callback-thread and main-thread -// on BufferArray (maybe BufferNew also). -// Use SDL-mutexes to solve this problem. - - -function AudioInputProcessor(): TAudioInputProcessor; -begin +unit URecord;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses Classes,
+ Math,
+ SysUtils,
+ UCommon,
+ UMusic,
+ UIni;
+
+type
+ TSound = class
+ private
+ BufferNew: TMemoryStream; // buffer for newest samples
+ public
+ BufferArray: array[0..4095] of smallint; // newest 4096 samples
+ BufferLong: array of TMemoryStream; // full buffer
+
+ Index: integer; // index in TAudioInputProcessor.Sound[] (TODO: Remove if not used)
+
+ AnalysisBufferSize: integer; // number of samples to analyze
+
+ // pitch detection
+ ToneValid: boolean; // true if Tone contains a valid value (otherwise it contains noise)
+ //Peak: integer; // position of peak on horizontal pivot (TODO: Remove if not used)
+ //ToneAccuracy: real; // tone accuracy (TODO: Remove if not used)
+ Tone: integer; // TODO: should be a non-unified full range tone (e.g. C2<>C3). Range: 0..NumHalftones-1
+ // Note: at the moment it is the same as ToneUnified
+ ToneUnified: integer; // tone unified to one octave (e.g. C2=C3=C4). Range: 0-11
+ //Scale: real; // FFT scale (TODO: Remove if not used)
+
+ // procedures
+ procedure ProcessNewBuffer;
+ procedure AnalyzeBuffer; // use to analyze sound from buffers to get new pitch
+ procedure AnalyzeByAutocorrelation; // we call it to analyze sound by checking Autocorrelation
+ function AnalyzeAutocorrelationFreq(Freq: real): real; // use this to check one frequency by Autocorrelation
+ end;
+
+ TAudioInputDeviceSource = record
+ Name: string;
+ end;
+
+ // soundcard input-devices information
+ TAudioInputDevice = class
+ public
+ CfgIndex: integer; // index of this device in Ini.InputDeviceConfig
+ Description: string; // soundcard name/description
+ Source: array of TAudioInputDeviceSource; // soundcard input(-source)s
+ SourceSelected: integer; // unused. What is this good for?
+ MicInput: integer; // unused. What is this good for?
+ SampleRate: integer; // capture sample-rate (e.g. 44.1kHz -> 44100)
+ CaptureChannel: array[0..1] of TSound; // sound(-buffers) used for left/right channel's capture data
+
+ procedure Start(); virtual; abstract;
+ procedure Stop(); virtual; abstract;
+
+ destructor Destroy; override;
+ end;
+
+ TAudioInputProcessor = class
+ Sound: array of TSound;
+ Device: array of TAudioInputDevice;
+
+ constructor Create;
+
+ // handle microphone input
+ procedure HandleMicrophoneData(Buffer: Pointer; Size: Cardinal;
+ InputDevice: TAudioInputDevice);
+
+ function Volume( aChannel : byte ): byte;
+ end;
+
+ TAudioInputBase = class( TInterfacedObject, IAudioInput )
+ private
+ Started: boolean;
+ protected
+ function UnifyDeviceName(const name: string; deviceIndex: integer): string;
+ function UnifyDeviceSourceName(const name: string; const deviceName: string): string;
+ public
+ function GetName: String; virtual; abstract;
+ function InitializeRecord: boolean; virtual; abstract;
+
+ procedure CaptureStart;
+ procedure CaptureStop;
+ end;
+
+
+ SmallIntArray = array [0..maxInt shr 1-1] of smallInt;
+ PSmallIntArray = ^SmallIntArray;
+
+ function AudioInputProcessor(): TAudioInputProcessor;
+
+implementation
+
+uses
+ ULog,
+ UMain;
+
+const
+ CaptureFreq = 44100;
+ BaseToneFreq = 65.4064; // lowest (half-)tone to analyze (C2 = 65.4064 Hz)
+ NumHalftones = 36; // C2-B4 (for Whitney and my high voice)
+
+var
+ singleton_AudioInputProcessor : TAudioInputProcessor = nil;
+
+
+// FIXME: Race-Conditions between Callback-thread and main-thread
+// on BufferArray (maybe BufferNew also).
+// Use SDL-mutexes to solve this problem.
+
+
+{ Global }
+
+function AudioInputProcessor(): TAudioInputProcessor;
+begin
if singleton_AudioInputProcessor = nil then
singleton_AudioInputProcessor := TAudioInputProcessor.create();
result := singleton_AudioInputProcessor;
-
end;
- -procedure TSound.ProcessNewBuffer; -var - S: integer; - L: integer; - A: integer; -begin - // process BufferArray - S := 0; - L := BufferNew.Size div 2; - if L > n then begin - S := L - n; - L := n; - end; - - // copy to array - for A := L+1 to n do - BufferArray[A-L] := BufferArray[A]; - - BufferNew.Seek(2*S, soBeginning); - BufferNew.ReadBuffer(BufferArray[1+n-L], 2*L); - - // process BufferLong - if Ini.SavePlayback = 1 then - begin - BufferNew.Seek(0, soBeginning); - BufferLong[0].CopyFrom(BufferNew, BufferNew.Size); - end; -end; - -procedure TSound.AnalyzeBuffer; -begin - AnalyzeByAutocorrelation; -end; - -procedure TSound.AnalyzeByAutocorrelation; -var - T: integer; // tone - F: real; // freq - Wages: array[0..35] of real; // wages - MaxT: integer; // max tone - MaxW: real; // max wage - V: real; // volume - MaxV: real; // max volume - S: integer; // Signal - Threshold: real; // threshold -begin - SzczytJest := false; - - // find maximum volume of first 1024 words of signal - MaxV := 0; - for S := 1 to 1024 do // 0.5.2: fix. was from 0 to 1023 - begin - V := Abs(BufferArray[S]) / $10000; - - if V > MaxV then - MaxV := V; - end; - - // prepare to analyze - MaxW := 0; - - // analyze all 12 halftones - for T := 0 to 35 do // to 11, then 23, now 35 (for Whitney and my high voice) - begin - F := 130.81 * Power(1.05946309436, T)/2; // let's analyze below 130.81 - Wages[T] := AnalyzeAutocorrelationFreq(F); - - if Wages[T] > MaxW then - begin // this frequency has better wage - MaxW := Wages[T]; - MaxT := T; - end; - end; // for T - - Threshold := 0.1; - case Ini.Threshold of - 0: Threshold := 0.05; - 1: Threshold := 0.1; - 2: Threshold := 0.15; - 3: Threshold := 0.2; - end; - - if MaxV >= Threshold then - begin // found acceptable volume // 0.1 - SzczytJest := true; - TonGamy := MaxT mod 12; - Ton := MaxT mod 12; - end; - -end; - -function TSound.AnalyzeAutocorrelationFreq(Freq: real): real; // result medium difference -var - Count: real; - Src: integer; - Dst: integer; - Move: integer; - Il: integer; // how many counts were done -begin - // we use Signal as source - Count := 0; - Il := 0; - Src := 1; - Move := Round(44100/Freq); - Dst := Src + Move; - - // ver 2 - compare in vertical - while (Dst < n) do - begin // process up to n (4KB) of Signal - Count := Count + Abs(BufferArray[Src] - BufferArray[Dst]) / $10000; - Inc(Src); - Inc(Dst); - Inc(Il); - end; - - Result := 1 - Count / Il; -end; - -{* - * Handle captured microphone input data. - * Params: - * Buffer - buffer of signed 16bit interleaved stereo PCM-samples. - * Interleaved means that a right-channel sample follows a left- - * channel sample and vice versa (0:left[0],1:right[0],2:left[1],...). - * Length - number of bytes in Buffer - * Input - Soundcard-Input used for capture - *} -procedure TAudioInputProcessor.HandleMicrophoneData(Buffer: Pointer; Length: Cardinal; InputDevice: TGenericSoundCard); -var - L: integer; - S: integer; - PB: pbytearray; - PSI: psmallintarray; - I: integer; - Skip: integer; - Boost: byte; -begin - // set boost - case Ini.MicBoost of - 0: Boost := 1; - 1: Boost := 2; - 2: Boost := 4; - 3: Boost := 8; - end; - - // boost buffer - L := Length div 2; // number of samples - PSI := Buffer; - for S := 0 to L-1 do - begin - I := PSI^[S] * Boost; - - // TODO : JB - This will clip the audio... cant we reduce the "Boot" if the data clips ?? - if I > 32767 then - I := 32767; // 0.5.0: limit - - if I < -32768 then - I := -32768; // 0.5.0: limit - - PSI^[S] := I; - end; - - // 2 players USB mic, left channel - if InputDevice.CaptureSoundLeft <> nil then - begin - L := Length div 4; // number of samples - PB := Buffer; - - InputDevice.CaptureSoundLeft.BufferNew.Clear; // 0.5.2: problem on exiting - for S := 0 to L-1 do - begin - InputDevice.CaptureSoundLeft.BufferNew.Write(PB[S*4], 2); - end; - InputDevice.CaptureSoundLeft.ProcessNewBuffer; - end; - - // 2 players USB mic, right channel - Skip := 2; - - if InputDevice.CaptureSoundRight <> nil then - begin - L := Length div 4; // number of samples - PB := Buffer; - InputDevice.CaptureSoundRight.BufferNew.Clear; - for S := 0 to L-1 do - begin - InputDevice.CaptureSoundRight.BufferNew.Write(PB[Skip + S*4], 2); - end; - InputDevice.CaptureSoundRight.ProcessNewBuffer; - end; -end; - -constructor TAudioInputProcessor.Create; -var - S: integer; -begin - SetLength(Sound, 6 {max players});//Ini.Players+1); - for S := 0 to High(Sound) do - begin //Ini.Players do begin - Sound[S] := TSound.Create; - Sound[S].Num := S; - Sound[S].BufferNew := TMemoryStream.Create; - SetLength(Sound[S].BufferLong, 1); - Sound[S].BufferLong[0] := TMemoryStream.Create; - Sound[S].n := 4*1024; - end; -end; - -function TAudioInputProcessor.volume( aChannel : byte ): byte; -var - lCount : Integer; - lMaxVol : double; -begin; - lMaxVol := AudioInputProcessor.Sound[aChannel].BufferArray[1]; - for lCount := 2 to AudioInputProcessor.Sound[aChannel].n div 1 do - begin - if AudioInputProcessor.Sound[aChannel].BufferArray[lCount] > lMaxVol then - lMaxVol := AudioInputProcessor.Sound[aChannel].BufferArray[lCount]; - end; - - result := trunc( ( 255 / 32767 ) * trunc( lMaxVol ) ); -end; - -end. - - - +
+
+{ TAudioInputDevice }
+
+destructor TAudioInputDevice.Destroy;
+var
+ i: integer;
+begin
+ Stop();
+ Source := nil;
+ for i := 0 to High(CaptureChannel) do
+ CaptureChannel[i] := nil;
+ inherited Destroy;
+end;
+
+
+{ TSound }
+
+procedure TSound.ProcessNewBuffer;
+var
+ SkipCount: integer;
+ NumSamples: integer;
+ SampleIndex: integer;
+begin
+ // process BufferArray
+ SkipCount := 0;
+ NumSamples := BufferNew.Size div 2;
+
+ // check if we have more new samples than we can store
+ if NumSamples > Length(BufferArray) then
+ begin
+ // discard the oldest of the new samples
+ SkipCount := NumSamples - Length(BufferArray);
+ NumSamples := Length(BufferArray);
+ end;
+
+ // move old samples to the beginning of the array (if necessary)
+ for SampleIndex := NumSamples to High(BufferArray) do
+ BufferArray[SampleIndex-NumSamples] := BufferArray[SampleIndex];
+
+ // skip samples if necessary
+ BufferNew.Seek(2*SkipCount, soBeginning);
+ // copy samples
+ BufferNew.ReadBuffer(BufferArray[Length(BufferArray)-NumSamples], 2*NumSamples);
+
+ // save capture-data to BufferLong if neccessary
+ if Ini.SavePlayback = 1 then
+ begin
+ BufferNew.Seek(0, soBeginning);
+ BufferLong[0].CopyFrom(BufferNew, BufferNew.Size);
+ end;
+end;
+
+procedure TSound.AnalyzeBuffer;
+begin
+ AnalyzeByAutocorrelation;
+end;
+
+procedure TSound.AnalyzeByAutocorrelation;
+var
+ ToneIndex: integer;
+ Freq: real;
+ Wages: array[0..NumHalftones-1] of real;
+ MaxTone: integer;
+ MaxWage: real;
+ Volume: real;
+ MaxVolume: real;
+ SampleIndex: integer;
+ Threshold: real;
+const
+ HalftoneBase = 1.05946309436; // 2^(1/12) -> HalftoneBase^12 = 2 (one octave)
+begin
+ ToneValid := false;
+
+ // find maximum volume of first 1024 samples
+ MaxVolume := 0;
+ for SampleIndex := 0 to 1023 do
+ begin
+ Volume := Abs(BufferArray[SampleIndex]) /
+ -Low(Smallint); // was $10000 (65536) before but must be 32768
+
+ if Volume > MaxVolume then
+ MaxVolume := Volume;
+ end;
+
+ // prepare to analyze
+ MaxWage := 0;
+
+ // analyze halftones
+ for ToneIndex := 0 to NumHalftones-1 do
+ begin
+ Freq := BaseToneFreq * Power(HalftoneBase, ToneIndex);
+ Wages[ToneIndex] := AnalyzeAutocorrelationFreq(Freq);
+
+ if Wages[ToneIndex] > MaxWage then
+ begin
+ // this frequency has better wage
+ MaxWage := Wages[ToneIndex];
+ MaxTone := ToneIndex;
+ end;
+ end;
+
+ Threshold := 0.2;
+ case Ini.Threshold of
+ 0: Threshold := 0.1;
+ 1: Threshold := 0.2;
+ 2: Threshold := 0.3;
+ 3: Threshold := 0.4;
+ end;
+
+ // check if signal has an acceptable volume (ignore background-noise)
+ if MaxVolume >= Threshold then
+ begin
+ ToneValid := true;
+ ToneUnified := MaxTone mod 12;
+ Tone := MaxTone mod 12;
+ end;
+
+end;
+
+function TSound.AnalyzeAutocorrelationFreq(Freq: real): real; // result medium difference
+var
+ Dist: real; // distance (0=equal .. 1=totally different) between correlated samples
+ AccumDist: real; // accumulated distances
+ SampleIndex: integer; // index of sample to analyze
+ CorrelatingSampleIndex: integer; // index of sample one period ahead
+ SamplesPerPeriod: integer; // samples in one period
+begin
+ SampleIndex := 0;
+ SamplesPerPeriod := Round(CaptureFreq/Freq);
+ CorrelatingSampleIndex := SampleIndex + SamplesPerPeriod;
+
+ AccumDist := 0;
+
+ // compare correlating samples
+ while (CorrelatingSampleIndex < AnalysisBufferSize) do
+ begin
+ // calc distance (correlation: 1-dist) to corresponding sample in next period
+ Dist := Abs(BufferArray[SampleIndex] - BufferArray[CorrelatingSampleIndex]) /
+ High(Word); // was $10000 (65536) before but must be 65535
+ AccumDist := AccumDist + Dist;
+ Inc(SampleIndex);
+ Inc(CorrelatingSampleIndex);
+ end;
+
+ // return "inverse" average distance (=correlation)
+ Result := 1 - AccumDist / AnalysisBufferSize;
+end;
+
+
+{ TAudioInputProcessor }
+
+{*
+ * Handle captured microphone input data.
+ * Params:
+ * Buffer - buffer of signed 16bit interleaved stereo PCM-samples.
+ * Interleaved means that a right-channel sample follows a left-
+ * channel sample and vice versa (0:left[0],1:right[0],2:left[1],...).
+ * Length - number of bytes in Buffer
+ * Input - Soundcard-Input used for capture
+ *}
+procedure TAudioInputProcessor.HandleMicrophoneData(Buffer: Pointer; Size: Cardinal; InputDevice: TAudioInputDevice);
+var
+ NumSamples: integer; // number of samples
+ SampleIndex: integer;
+ Value: integer;
+ ByteBuffer: PByteArray; // buffer handled as array of bytes
+ SampleBuffer: PSmallIntArray; // buffer handled as array of samples
+ Offset: integer;
+ Boost: byte;
+ ChannelCount: integer;
+ ChannelIndex: integer;
+ CaptureChannel: TSound;
+ SampleSize: integer;
+begin
+ // set boost
+ case Ini.MicBoost of
+ 0: Boost := 1;
+ 1: Boost := 2;
+ 2: Boost := 4;
+ 3: Boost := 8;
+ end;
+
+ // boost buffer
+ NumSamples := Size div 2;
+ SampleBuffer := Buffer;
+ for SampleIndex := 0 to NumSamples-1 do
+ begin
+ Value := SampleBuffer^[SampleIndex] * Boost;
+
+ // TODO : JB - This will clip the audio... cant we reduce the "Boost" if the data clips ??
+ if Value > High(Smallint) then
+ Value := High(Smallint);
+
+ if Value < Low(Smallint) then
+ Value := Low(Smallint);
+
+ SampleBuffer^[SampleIndex] := Value;
+ end;
+
+ // number of channels
+ ChannelCount := Length(InputDevice.CaptureChannel);
+ // size of one sample
+ SampleSize := ChannelCount * SizeOf(SmallInt);
+ // samples per channel
+ NumSamples := Size div SampleSize;
+
+ // interpret buffer as buffer of bytes
+ ByteBuffer := Buffer;
+
+ // process channels
+ for ChannelIndex := 0 to High(InputDevice.CaptureChannel) do
+ begin
+ CaptureChannel := InputDevice.CaptureChannel[ChannelIndex];
+ if (CaptureChannel <> nil) then
+ begin
+ Offset := ChannelIndex * SizeOf(SmallInt);
+
+ // TODO: remove BufferNew and write to BufferArray directly
+
+ CaptureChannel.BufferNew.Clear;
+ for SampleIndex := 0 to NumSamples-1 do
+ begin
+ CaptureChannel.BufferNew.Write(ByteBuffer^[Offset + SampleIndex*SampleSize],
+ SizeOf(SmallInt));
+ end;
+ CaptureChannel.ProcessNewBuffer();
+ end;
+ end;
+end;
+
+constructor TAudioInputProcessor.Create;
+var
+ i: integer;
+begin
+ SetLength(Sound, 6 {max players});//Ini.Players+1);
+ for i := 0 to High(Sound) do
+ begin
+ Sound[i] := TSound.Create;
+ Sound[i].Index := i;
+ Sound[i].BufferNew := TMemoryStream.Create;
+ SetLength(Sound[i].BufferLong, 1);
+ Sound[i].BufferLong[0] := TMemoryStream.Create;
+ Sound[i].AnalysisBufferSize := Min(4*1024, Length(Sound[i].BufferArray));
+ end;
+end;
+
+function TAudioInputProcessor.Volume( aChannel : byte ): byte;
+var
+ lSampleIndex: Integer;
+ lMaxVol : Word;
+begin;
+ with AudioInputProcessor.Sound[aChannel] do
+ begin
+ lMaxVol := BufferArray[0];
+ for lSampleIndex := 1 to High(BufferArray) do
+ begin
+ if Abs(BufferArray[lSampleIndex]) > lMaxVol then
+ lMaxVol := Abs(BufferArray[lSampleIndex]);
+ end;
+ end;
+
+ result := trunc( ( 255 / -Low(Smallint) ) * lMaxVol );
+end;
+
+
+{ TAudioInputBase }
+
+{*
+ * Start capturing on all used input-device.
+ *}
+procedure TAudioInputBase.CaptureStart;
+var
+ S: integer;
+ DeviceIndex: integer;
+ ChannelIndex: integer;
+ Device: TAudioInputDevice;
+ DeviceCfg: PInputDeviceConfig;
+ DeviceUsed: boolean;
+ Player: integer;
+begin
+ if (Started) then
+ CaptureStop();
+
+ Log.BenchmarkStart(1);
+
+ // reset buffers
+ for S := 0 to High(AudioInputProcessor.Sound) do
+ AudioInputProcessor.Sound[S].BufferLong[0].Clear;
+
+ // start capturing on each used device
+ for DeviceIndex := 0 to High(AudioInputProcessor.Device) do begin
+ Device := AudioInputProcessor.Device[DeviceIndex];
+ if not assigned(Device) then
+ continue;
+ DeviceCfg := @Ini.InputDeviceConfig[Device.CfgIndex];
+
+ DeviceUsed := false;
+
+ // check if device is used
+ for ChannelIndex := 0 to High(DeviceCfg.ChannelToPlayerMap) do
+ begin
+ Player := DeviceCfg.ChannelToPlayerMap[ChannelIndex]-1;
+ if (Player < 0) or (Player >= PlayersPlay) then
+ begin
+ Device.CaptureChannel[ChannelIndex] := nil;
+ end
+ else
+ begin
+ Device.CaptureChannel[ChannelIndex] := AudioInputProcessor.Sound[Player];
+ DeviceUsed := true;
+ end;
+ end;
+
+ // start device if used
+ if (DeviceUsed) then begin
+ Log.BenchmarkStart(2);
+ Device.Start();
+ Log.BenchmarkEnd(2);
+ Log.LogBenchmark('Device.Start', 2) ; + end;
+ end;
+
+ Log.BenchmarkEnd(1);
+ Log.LogBenchmark('CaptureStart', 1) ; +
+ Started := true;
+end;
+
+{*
+ * Stop input-capturing on all soundcards.
+ *}
+procedure TAudioInputBase.CaptureStop;
+var
+ DeviceIndex: integer;
+ Player: integer;
+ Device: TAudioInputDevice;
+ DeviceCfg: PInputDeviceConfig;
+begin
+ for DeviceIndex := 0 to High(AudioInputProcessor.Device) do begin
+ Device := AudioInputProcessor.Device[DeviceIndex];
+ if not assigned(Device) then
+ continue;
+ Device.Stop();
+ end;
+
+ Started := false;
+end;
+
+function TAudioInputBase.UnifyDeviceName(const name: string; deviceIndex: integer): string;
+var
+ count: integer; // count of devices with this name
+
+ function IsDuplicate(const name: string): boolean;
+ var
+ i: integer;
+ begin
+ Result := False;
+ // search devices with same description
+ For i := 0 to deviceIndex-1 do
+ begin
+ if (AudioInputProcessor.Device[i].Description = name) then
+ begin
+ Result := True;
+ Break;
+ end;
+ end;
+ end;
+begin
+ count := 1;
+ result := name;
+
+ // if there is another device with the same ID, search for an available name
+ while (IsDuplicate(result)) do
+ begin
+ Inc(count);
+ // set description
+ result := name + ' ('+IntToStr(count)+')';
+ end;
+end;
+
+{*
+ * Unifies an input-device's source name.
+ * Note: the description member of the device must already be set when
+ * calling this function.
+ *}
+function TAudioInputBase.UnifyDeviceSourceName(const name: string; const deviceName: string): string;
+var
+ Descr: string;
+begin
+ result := name;
+
+ {$IFDEF DARWIN}
+ // Under MacOSX the SingStar Mics have an empty
+ // InputName. So, we have to add a hard coded
+ // Workaround for this problem
+ if (name = '') and (Pos( 'USBMIC Serial#', deviceName) > 0) then
+ begin
+ result := 'Microphone';
+ end;
+ {$ENDIF}
+end;
+
+end.
+
+
+
diff --git a/Game/Code/Screens/UScreenCredits.pas b/Game/Code/Screens/UScreenCredits.pas index d5c9bebc..925d62cc 100644 --- a/Game/Code/Screens/UScreenCredits.pas +++ b/Game/Code/Screens/UScreenCredits.pas @@ -1,1402 +1,1402 @@ -unit UScreenCredits; - -interface - -{$IFDEF FPC} - {$MODE Delphi} -{$ENDIF} - -{$I switches.inc} - - -uses - UMenu, - SDL, - SDL_Image, - UDisplay, - UTexture, - OpenGL12, - UMusic, - UFiles, - SysUtils, - UThemes, - ULCD, - ULight, - UGraphicClasses; - -type - TCreditsStages=(InitialDelay,Intro,MainPart,Outro); - - TScreenCredits = class(TMenu) - public - - Credits_X: Real; - Credits_Time: Cardinal; - Credits_Alpha: Cardinal; - CTime: Cardinal; - CTime_hold: Cardinal; - ESC_Alpha: Integer; - - credits_entry_tex: TTexture; - credits_entry_dx_tex: TTexture; - credits_bg_tex: TTexture; - credits_bg_ovl: TTexture; -// credits_bg_logo: TTexture; - credits_bg_scrollbox_left: TTexture; - credits_blindguard: TTexture; - credits_blindy: TTexture; - credits_canni: TTexture; - credits_commandio: TTexture; - credits_lazyjoker: TTexture; - credits_mog: TTexture; - credits_mota: TTexture; - credits_skillmaster: TTexture; - credits_whiteshark: TTexture; - intro_layer01: TTexture; - intro_layer02: TTexture; - intro_layer03: TTexture; - intro_layer04: TTexture; - intro_layer05: TTexture; - intro_layer06: TTexture; - intro_layer07: TTexture; - intro_layer08: TTexture; - intro_layer09: TTexture; - outro_bg: TTexture; - outro_esc: TTexture; - outro_exd: TTexture; - - deluxe_slidein: cardinal; - - CurrentScrollText: String; - NextScrollUpdate: Real; - EndofLastScrollingPart: Cardinal; - CurrentScrollStart, CurrentScrollEnd: Integer; - - CRDTS_Stage: TCreditsStages; - - myTex: glUint; - mysdlimage,myconvertedsdlimage: PSDL_Surface; - - Fadeout: boolean; - constructor Create; override; - function ParseInput(PressedKey: Cardinal; ScanCode: byte; PressedDown: Boolean): Boolean; override; - function Draw: boolean; override; - procedure onShow; override; - procedure onHide; override; - procedure DrawCredits; - procedure Draw_FunkyText; - end; - -const - Funky_Text: AnsiString = - 'Grandma Deluxe has arrived! Thanks to Corvus5 for the massive work on UltraStar, Wome for the nice tune you´re hearing, '+ - 'all the people who put massive effort and work in new songs (don´t forget UltraStar w/o songs would be nothing), ppl from '+ - 'irc helping us - eBandit and Gabari, scene ppl who really helped instead of compiling and running away. Greetings to DennisTheMenace for betatesting, '+ - 'Demoscene.tv, pouet.net, KakiArts, Sourceforge,..'; - - - Timings: array[0..21] of Cardinal=( - 20, // 0 Delay vor Start - - 149, // 1 Ende erster Intro Zoom - 155, // 2 Start 2. Action im Intro - 170, // 3 Ende Separation im Intro - 271, // 4 Anfang Zoomout im Intro - 0, // 5 unused - 261, // 6 Start fade-to-white im Intro - - 271, // 7 Start Main Part - 280, // 8 Start On-Beat-Sternchen Main Part - - 396, // 9 Start BlindGuard - 666, // 10 Start blindy - 936, // 11 Start Canni - 1206, // 12 Start Commandio - 1476, // 13 Start LazyJoker - 1746, // 14 Start Mog - 2016, // 15 Start Mota - 2286, // 16 Start SkillMaster - 2556, // 17 Start WhiteShark - 2826, // 18 Ende Whiteshark - 3096, // 19 Start FadeOut Mainscreen - 3366, // 20 Ende Credits Tune - 60); // 21 start flare im intro - - - sdl32bpprgba: TSDL_Pixelformat=(palette: nil; - BitsPerPixel: 32; - BytesPerPixel: 4; - Rloss: 0; - Gloss: 0; - Bloss: 0; - Aloss: 0; - Rshift: 0; - Gshift: 8; - Bshift: 16; - Ashift: 24; - Rmask: $000000ff; - Gmask: $0000ff00; - Bmask: $00ff0000; - Amask: $ff000000; - colorkey: 0; - alpha: 255 ); - - -implementation - -uses {$IFDEF win32} - windows, - {$ELSE} - lclintf, - {$ENDIF} - ULog, - UGraphic, - UMain, - UIni, - USongs, - Textgl, - ULanguage, - UCommon, - Math, - dialogs; - - -function TScreenCredits.ParseInput(PressedKey: Cardinal; ScanCode: byte; PressedDown: Boolean): Boolean; -begin - Result := true; - If (PressedDown) Then - begin // Key Down - case PressedKey of - - SDLK_ESCAPE, - SDLK_BACKSPACE : - begin - FadeTo(@ScreenMain); - AudioPlayback.PlayBack; - end; -{ SDLK_SPACE: - begin - setlength(CTime_hold,length(CTime_hold)+1); - CTime_hold[high(CTime_hold)]:=CTime; - end; -} - end;//esac - end; //fi -end; - -constructor TScreenCredits.Create; -begin - inherited Create; - - credits_bg_tex := Texture.LoadTexture(true, 'CRDTS_BG', 'PNG', 'Plain', 0); - credits_bg_ovl := Texture.LoadTexture(true, 'CRDTS_OVL', 'PNG', 'Transparent', 0); - - credits_blindguard := Texture.LoadTexture(true, 'CRDTS_blindguard', 'PNG', 'Font Black', 0); - credits_blindy := Texture.LoadTexture(true, 'CRDTS_blindy', 'PNG', 'Font Black', 0); - credits_canni := Texture.LoadTexture(true, 'CRDTS_canni', 'PNG', 'Font Black', 0); - credits_commandio := Texture.LoadTexture(true, 'CRDTS_commandio', 'PNG', 'Font Black', 0); - credits_lazyjoker := Texture.LoadTexture(true, 'CRDTS_lazyjoker', 'PNG', 'Font Black', 0); - credits_mog := Texture.LoadTexture(true, 'CRDTS_mog', 'PNG', 'Font Black', 0); - credits_mota := Texture.LoadTexture(true, 'CRDTS_mota', 'PNG', 'Font Black', 0); - credits_skillmaster := Texture.LoadTexture(true, 'CRDTS_skillmaster', 'PNG', 'Font Black', 0); - credits_whiteshark := Texture.LoadTexture(true, 'CRDTS_whiteshark', 'PNG', 'Font Black', 0); - - intro_layer01 := Texture.LoadTexture(true, 'INTRO_L01', 'PNG', 'Transparent', 0); - intro_layer02 := Texture.LoadTexture(true, 'INTRO_L02', 'PNG', 'Transparent', 0); - intro_layer03 := Texture.LoadTexture(true, 'INTRO_L03', 'PNG', 'Transparent', 0); - intro_layer04 := Texture.LoadTexture(true, 'INTRO_L04', 'PNG', 'Transparent', 0); - intro_layer05 := Texture.LoadTexture(true, 'INTRO_L05', 'PNG', 'Transparent', 0); - intro_layer06 := Texture.LoadTexture(true, 'INTRO_L06', 'PNG', 'Transparent', 0); - intro_layer07 := Texture.LoadTexture(true, 'INTRO_L07', 'PNG', 'Transparent', 0); - intro_layer08 := Texture.LoadTexture(true, 'INTRO_L08', 'PNG', 'Transparent', 0); - intro_layer09 := Texture.LoadTexture(true, 'INTRO_L09', 'PNG', 'Transparent', 0); - - outro_bg := Texture.LoadTexture(true, 'OUTRO_BG', 'PNG', 'Plain', 0); - outro_esc := Texture.LoadTexture(true, 'OUTRO_ESC', 'PNG', 'Transparent', 0); - outro_exd := Texture.LoadTexture(true, 'OUTRO_EXD', 'PNG', 'Transparent', 0); - - CRDTS_Stage:=InitialDelay; -end; - -function TScreenCredits.Draw: boolean; -begin - DrawCredits; - Draw:=true; -end; - -function pixfmt_eq(fmt1,fmt2: TSDL_Pixelformat): boolean; -begin - if (fmt1.BitsPerPixel = fmt2.BitsPerPixel) and - (fmt1.BytesPerPixel = fmt2.BytesPerPixel) and - (fmt1.Rloss = fmt2.Rloss) and - (fmt1.Gloss = fmt2.Gloss) and - (fmt1.Bloss = fmt2.Bloss) and - (fmt1.Rmask = fmt2.Rmask) and - (fmt1.Gmask = fmt2.Gmask) and - (fmt1.Bmask = fmt2.Bmask) and - (fmt1.Rshift = fmt2.Rshift) and - (fmt1.Gshift = fmt2.Gshift) and - (fmt1.Bshift = fmt2.Bshift) - then - pixfmt_eq:=True - else - pixfmt_eq:=False; -end; - -function inttohexstr(i: cardinal):pchar; -var helper, i2, c:cardinal; - tmpstr: string; -begin - helper:=0; - i2:=i; - tmpstr:=''; - for c:=1 to 8 do - begin - helper:=(helper shl 4) or (i2 and $f); - i2:=i2 shr 4; - end; - for c:=1 to 8 do - begin - i2:=helper and $f; - helper := helper shr 4; - case i2 of - 0: tmpstr:=tmpstr+'0'; - 1: tmpstr:=tmpstr+'1'; - 2: tmpstr:=tmpstr+'2'; - 3: tmpstr:=tmpstr+'3'; - 4: tmpstr:=tmpstr+'4'; - 5: tmpstr:=tmpstr+'5'; - 6: tmpstr:=tmpstr+'6'; - 7: tmpstr:=tmpstr+'7'; - 8: tmpstr:=tmpstr+'8'; - 9: tmpstr:=tmpstr+'9'; - 10: tmpstr:=tmpstr+'a'; - 11: tmpstr:=tmpstr+'b'; - 12: tmpstr:=tmpstr+'c'; - 13: tmpstr:=tmpstr+'d'; - 14: tmpstr:=tmpstr+'e'; - 15: tmpstr:=tmpstr+'f'; - end; - end; - inttohexstr:=pchar(tmpstr); -end; - -procedure TScreenCredits.onShow; -begin - CRDTS_Stage:=InitialDelay; - Credits_X := 580; - deluxe_slidein := 0; - Credits_Alpha := 0; - //Music.SetLoop(true); Loop looped ned, so ne scheisse - AudioPlayback.Open(soundpath + 'wome-credits-tune.mp3'); //danke kleinster liebster weeeetüüüüü!! -// Music.Play; - CTime:=0; -// setlength(CTime_hold,0); - - mysdlimage:=IMG_Load('test.png'); - if assigned(mysdlimage) then - begin - {$IFNDEF FPC} - showmessage('opened image via SDL_Image'+#13#10+ - 'Width: '+inttostr(mysdlimage^.w)+#13#10+ - 'Height: '+inttostr(mysdlimage^.h)+#13#10+ - 'BitsPP: '+inttostr(mysdlimage^.format.BitsPerPixel)+#13#10+ - 'BytesPP: '+inttostr(mysdlimage^.format.BytesPerPixel)+#13#10+ - 'Rloss: '+inttostr(mysdlimage^.format.Rloss)+#13#10+ - 'Gloss: '+inttostr(mysdlimage^.format.Gloss)+#13#10+ - 'Bloss: '+inttostr(mysdlimage^.format.Bloss)+#13#10+ - 'Aloss: '+inttostr(mysdlimage^.format.Aloss)+#13#10+ - 'Rshift: '+inttostr(mysdlimage^.format.Rshift)+#13#10+ - 'Gshift: '+inttostr(mysdlimage^.format.Gshift)+#13#10+ - 'Bshift: '+inttostr(mysdlimage^.format.Bshift)+#13#10+ - 'Ashift: '+inttostr(mysdlimage^.format.Ashift)+#13#10+ - 'Rmask: '+inttohexstr(mysdlimage^.format.Rmask)+#13#10+ - 'Gmask: '+inttohexstr(mysdlimage^.format.Gmask)+#13#10+ - 'Bmask: '+inttohexstr(mysdlimage^.format.Bmask)+#13#10+ - 'Amask: '+inttohexstr(mysdlimage^.format.Amask)+#13#10+ - 'ColKey: '+inttostr(mysdlimage^.format.Colorkey)+#13#10+ - 'Alpha: '+inttostr(mysdlimage^.format.Alpha)); - - if pixfmt_eq(mysdlimage^.format^,sdl32bpprgba) then - showmessage('equal pixelformats') - else - showmessage('different pixelformats'); - {$ENDIF} - - myconvertedsdlimage:=SDL_ConvertSurface(mysdlimage,@sdl32bpprgba,SDL_SWSURFACE); - glGenTextures(1,@myTex); - glBindTexture(GL_TEXTURE_2D, myTex); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); - glTexImage2D( GL_TEXTURE_2D, 0, 4, myconvertedsdlimage^.w, myconvertedsdlimage^.h, 0, - GL_RGBA, GL_UNSIGNED_BYTE, myconvertedsdlimage^.pixels ); - SDL_FreeSurface(mysdlimage); - SDL_FreeSurface(myconvertedsdlimage); - end - else - {$IFDEF FPC} - writeln( 'could not open file - test.png'); - {$ELSE} - showmessage('could not open file - test.png'); - {$ENDIF} - -end; - -procedure TScreenCredits.onHide; -begin - AudioPlayback.Stop; -end; - -Procedure TScreenCredits.Draw_FunkyText; -var - S: Integer; - X,Y,A: Real; - visibleText: PChar; -begin - SetFontSize(10); - //Init ScrollingText - if (CTime = Timings[7]) then - begin - //Set Position of Text - Credits_X := 600; - CurrentScrollStart:=1; - CurrentScrollEnd:=1; - end; - - if (CTime > Timings[7]) and (CurrentScrollStart < length(Funky_Text)) then - begin - X:=0; - visibleText:=pchar(Copy(Funky_Text, CurrentScrollStart, CurrentScrollEnd)); - for S := 0 to length(visibleText)-1 do begin - Y:=abs(sin((Credits_X+X)*0.93{*(((Credits_X+X))/1200)}/100*pi)); - SetFontPos(Credits_X+X,538-Y*(Credits_X+X)*(Credits_X+X)*(Credits_X+X)/1000000); - A:=0; - if (Credits_X+X < 15) then A:=0; - if (Credits_X+X >=15) then A:=Credits_X+X-15; - if Credits_X+X > 32 then A:=17; - glColor4f( 230/255-40/255+Y*(Credits_X+X)/900, 200/255-30/255+Y*(Credits_X+X)/1000, 155/255-20/255+Y*(Credits_X+X)/1100, A/17); - glPrintLetter(visibleText[S]); - X := X + Fonts[ActFont].Width[Ord(visibleText[S])] * Fonts[ActFont].Tex.H / 30 * Fonts[ActFont].AspectW; - end; - if (Credits_X<0) and (CurrentScrollStart < length(Funky_Text)) then begin - Credits_X:=Credits_X + Fonts[ActFont].Width[Ord(Funky_Text[CurrentScrollStart])] * Fonts[ActFont].Tex.H / 30 * Fonts[ActFont].AspectW; - inc(CurrentScrollStart); - end; - visibleText:=pchar(Copy(Funky_Text, CurrentScrollStart, CurrentScrollEnd)); - if (Credits_X+glTextWidth(visibleText) < 600) and (CurrentScrollEnd < length(Funky_Text)) then begin - inc(CurrentScrollEnd); - end; - end; -{ // timing hack - X:=5; - SetFontStyle (2); - SetFontItalic(False); - SetFontSize(9); - glColor4f(1, 1, 1, 1); - for S:=0 to high(CTime_hold) do begin - visibleText:=pchar(inttostr(CTime_hold[S])); - SetFontPos (500, X); - glPrint (Addr(visibleText[0])); - X:=X+20; - end;} -end; - -procedure Start3D; -begin - glMatrixMode(GL_PROJECTION); - glPushMatrix; - glLoadIdentity; - glFrustum(-0.3*4/3,0.3*4/3,-0.3,0.3,1,1000); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity; -end; -procedure End3D; -begin - glMatrixMode(GL_PROJECTION); - glPopMatrix; - glMatrixMode(GL_MODELVIEW); -end; - -procedure TScreenCredits.DrawCredits; -var - T,I: Cardinal; - X: Real; - Ver: PChar; - RuntimeStr: AnsiString; - Data: TFFTData; - j,k,l:cardinal; - f,g,h: Real; - STime:cardinal; - Delay:cardinal; - - myPixel: longword; - myColor: Cardinal; - myScale: Real; - myAngle: Real; - - -const myLogoCoords: Array[0..27,0..1] of Cardinal = ((39,32),(84,32),(100,16),(125,24), - (154,31),(156,58),(168,32),(203,36), - (258,34),(251,50),(274,93),(294,84), - (232,54),(278,62),(319,34),(336,92), - (347,23),(374,32),(377,58),(361,83), - (385,91),(405,91),(429,35),(423,51), - (450,32),(485,34),(444,91),(486,93)); - -begin - //dis does teh muiwk y0r - Data := AudioPlayback.GetFFTData; - - Log.LogStatus('',' JB-1'); - - T := GetTickCount div 33; - if T <> Credits_Time then - begin - Credits_Time := T; - inc(CTime); - inc(CTime_hold); - Credits_X := Credits_X-2; - - Log.LogStatus('',' JB-2'); - if (CRDTS_Stage=InitialDelay) and (CTime=Timings[0]) then - begin -// CTime:=Timings[20]; -// CRDTS_Stage:=Outro; - - CRDTS_Stage:=Intro; - CTime:=0; - AudioPlayback.Play; - - end; - if (CRDTS_Stage=Intro) and (CTime=Timings[7]) then - begin - CRDTS_Stage:=MainPart; - end; - if (CRDTS_Stage=MainPart) and (CTime=Timings[20]) then - begin - CRDTS_Stage:=Outro; - end; - end; - - Log.LogStatus('',' JB-3'); - - //draw background - if CRDTS_Stage=InitialDelay then - begin - glClearColor(0,0,0,0); - glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); - end - else - if CRDTS_Stage=Intro then - begin - Start3D; - glPushMatrix; - - glClearColor(0,0,0,0); - glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); - - glEnable(GL_TEXTURE_2D); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); - - if CTime < Timings[1] then begin - myScale:= 0.5+0.5*(Timings[1]-CTime)/(Timings[1]); // slowly move layers together - myAngle:=cos((CTime)*pi/((Timings[1])*2)); // and make logo face towards camera - end else begin // this is the part when the logo stands still - myScale:=0.5; - myAngle:=0; - end; - if CTime > Timings[2] then begin - myScale:= 0.5+0.5*(CTime-Timings[2])/(Timings[3]-Timings[2]); // get some space between layers - myAngle:=0; - end; -// if CTime > Timings[3] then myScale:=1; // keep the space between layers - glTranslatef(0,0,-5+0.5*myScale); - if CTime > Timings[3] then myScale:=1; // keep the space between layers - if CTime > Timings[3] then begin // make logo rotate left and grow -// myScale:=(CTime-Timings[4])/(Timings[7]-Timings[4]); - glRotatef(20*sqr(CTime-Timings[3])/sqr((Timings[7]-Timings[3])/2),0,0,1); - glScalef(1+sqr(CTime-Timings[3])/(32*(Timings[7]-Timings[3])),1+sqr(CTime-Timings[3])/(32*(Timings[7]-Timings[3])),1); - end; - if CTime < Timings[2] then - glRotatef(30*myAngle,0.5*myScale+myScale,1+myScale,0); -// glScalef(0.5,0.5,0.5); - glScalef(4/3,-1,1); - glColor4f(1, 1, 1, 1); - - glBindTexture(GL_TEXTURE_2D, intro_layer01.TexNum); - glbegin(gl_quads); - glTexCoord2f(0,0);glVertex3f(-1, -1, -0.4 * myScale); - glTexCoord2f(0,1);glVertex3f(-1, 1, -0.4 * myScale); - glTexCoord2f(1,1); glVertex3f(1, 1, -0.4 * myScale); - glTexCoord2f(1,0);glVertex3f(1, -1, -0.4 * myScale); - glEnd; - glBindTexture(GL_TEXTURE_2D, intro_layer02.TexNum); - glbegin(gl_quads); - glTexCoord2f(0,0);glVertex3f(-1, -1, -0.3 * myScale); - glTexCoord2f(0,1);glVertex3f(-1, 1, -0.3 * myScale); - glTexCoord2f(1,1); glVertex3f(1, 1, -0.3 * myScale); - glTexCoord2f(1,0);glVertex3f(1, -1, -0.3 * myScale); - glEnd; - glBindTexture(GL_TEXTURE_2D, intro_layer03.TexNum); - glbegin(gl_quads); - glTexCoord2f(0,0);glVertex3f(-1, -1, -0.2 * myScale); - glTexCoord2f(0,1);glVertex3f(-1, 1, -0.2 * myScale); - glTexCoord2f(1,1); glVertex3f(1, 1, -0.2 * myScale); - glTexCoord2f(1,0);glVertex3f(1, -1, -0.2 * myScale); - glEnd; - glBindTexture(GL_TEXTURE_2D, intro_layer04.TexNum); - glbegin(gl_quads); - glTexCoord2f(0,0);glVertex3f(-1, -1, -0.1 * myScale); - glTexCoord2f(0,1);glVertex3f(-1, 1, -0.1 * myScale); - glTexCoord2f(1,1); glVertex3f(1, 1, -0.1 * myScale); - glTexCoord2f(1,0);glVertex3f(1, -1, -0.1 * myScale); - glEnd; - glBindTexture(GL_TEXTURE_2D, intro_layer05.TexNum); - glbegin(gl_quads); - glTexCoord2f(0,0);glVertex3f(-1, -1, 0 * myScale); - glTexCoord2f(0,1);glVertex3f(-1, 1, 0 * myScale); - glTexCoord2f(1,1); glVertex3f(1, 1, 0 * myScale); - glTexCoord2f(1,0);glVertex3f(1, -1, 0 * myScale); - glEnd; - glBindTexture(GL_TEXTURE_2D, intro_layer06.TexNum); - glbegin(gl_quads); - glTexCoord2f(0,0);glVertex3f(-1, -1, 0.1 * myScale); - glTexCoord2f(0,1);glVertex3f(-1, 1, 0.1 * myScale); - glTexCoord2f(1,1); glVertex3f(1, 1, 0.1 * myScale); - glTexCoord2f(1,0);glVertex3f(1, -1, 0.1 * myScale); - glEnd; - glBindTexture(GL_TEXTURE_2D, intro_layer07.TexNum); - glbegin(gl_quads); - glTexCoord2f(0,0);glVertex3f(-1, -1, 0.2 * myScale); - glTexCoord2f(0,1);glVertex3f(-1, 1, 0.2 * myScale); - glTexCoord2f(1,1); glVertex3f(1, 1, 0.2 * myScale); - glTexCoord2f(1,0);glVertex3f(1, -1, 0.2 * myScale); - glEnd; - glBindTexture(GL_TEXTURE_2D, intro_layer08.TexNum); - glbegin(gl_quads); - glTexCoord2f(0,0);glVertex3f(-1, -1, 0.3 * myScale); - glTexCoord2f(0,1);glVertex3f(-1, 1, 0.3 * myScale); - glTexCoord2f(1,1); glVertex3f(1, 1, 0.3 * myScale); - glTexCoord2f(1,0);glVertex3f(1, -1, 0.3 * myScale); - glEnd; - glBindTexture(GL_TEXTURE_2D, intro_layer09.TexNum); - glbegin(gl_quads); - glTexCoord2f(0,0);glVertex3f(-1, -1, 0.22 * myScale); - glTexCoord2f(0,1);glVertex3f(-1, 1, 0.22 * myScale); - glTexCoord2f(1,1); glVertex3f(1, 1, 0.22 * myScale); - glTexCoord2f(1,0);glVertex3f(1, -1, 0.22 * myScale); - glEnd; - gldisable(gl_texture_2d); - glDisable(GL_BLEND); - - glPopMatrix; - End3D; - - // do some sparkling effects - if (CTime < Timings[1]) and (CTime > Timings[21]) then - begin - for k:=1 to 3 do begin - l:=410+floor((CTime-Timings[21])/(Timings[1]-Timings[21])*(536-410))+RandomRange(-5,5); - j:=floor((Timings[1]-CTime)/22)+RandomRange(285,301); - GoldenRec.Spawn(l, j, 1, 16, 0, -1, Flare, 0); - end; - end; - - // fade to white at end - if Ctime > Timings[6] then - begin - glColor4f(1,1,1,sqr(Ctime-Timings[6])*(Ctime-Timings[6])/sqr(Timings[7]-Timings[6])); - glEnable(GL_BLEND); - glBegin(GL_QUADS); - glVertex2f(0,0); - glVertex2f(0,600); - glVertex2f(800,600); - glVertex2f(800,0); - glEnd; - glDisable(GL_BLEND); - end; - - end; - if (CRDTS_Stage=MainPart) then - // main credits screen background, scroller, logo and girl - begin - - glEnable(GL_TEXTURE_2D); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); - - glColor4f(1, 1, 1, 1); - glBindTexture(GL_TEXTURE_2D, credits_bg_tex.TexNum); - glbegin(gl_quads); - glTexCoord2f(0,0);glVertex2f(0, 0); - glTexCoord2f(0,600/1024);glVertex2f(0, 600); - glTexCoord2f(800/1024,600/1024); glVertex2f(800, 600); - glTexCoord2f(800/1024,0);glVertex2f(800, 0); - glEnd; - glDisable(GL_TEXTURE_2D); - glDisable(GL_BLEND); - - // draw scroller - Draw_FunkyText; - -//######################################################################### -// draw credits names - - -Log.LogStatus('',' JB-4'); - -// BlindGuard (von links oben reindrehen, nach rechts unten rausdrehen) - STime:=Timings[9]-10; - Delay:=Timings[10]-Timings[9]; - if CTime > STime then - begin - k:=0; - ESC_Alpha:=20; - - try - for j:=0 to 40 do - begin - if ( j < length( Data ) ) AND - ( k < length( Data ) ) then - begin - if Data[j] >= Data[k] then - k:=j; - end; - end; - except - end; - - if Data[k]>0.25 then ESC_Alpha:=5 else inc(ESC_Alpha); - if ESC_Alpha >20 then ESC_Alpha:=20; - if ((CTime-STime)<20) then ESC_Alpha:=20; - if CTime <=STime+10 then j:=CTime-STime else j:=10; - if (CTime >=STime+Delay-10) then if (CTime <=STime+Delay) then j:=(STime+Delay)-CTime else j:=0; - glColor4f(1, 1, 1, ESC_Alpha/20*j/10); - - if (CTime >= STime+10) and (CTime<=STime+12) then begin - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5); - end; - - glPushMatrix; - gltranslatef(0,329,0); - if CTime <= STime+10 then begin glrotatef((CTime-STime)*9+270,0,0,1);end; - gltranslatef(223,0,0); - if CTime >=STime+Delay-10 then if CTime <=STime+Delay then begin - gltranslatef(223,0,0); - glrotatef((integer(CTime)-(integer(STime+Delay)-10))*-9,0,0,1); - gltranslatef(-223,0,0); - end; - glBindTexture(GL_TEXTURE_2D, credits_blindguard.TexNum); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); - glEnable(GL_TEXTURE_2D); - glbegin(gl_quads); - glTexCoord2f(0,0);glVertex2f(-163, -129); - glTexCoord2f(0,1);glVertex2f(-163, 129); - glTexCoord2f(1,1); glVertex2f(163, 129); - glTexCoord2f(1,0);glVertex2f(163, -129); - glEnd; - gldisable(gl_texture_2d); - gldisable(GL_BLEND); - glPopMatrix; - end; - -// Blindy (zoom von 0 auf volle grösse und drehung, zoom auf doppelte grösse und nach rechts oben schieben) - STime:=Timings[10]-10; - Delay:=Timings[11]-Timings[10]+5; - if CTime > STime then - begin - k:=0; - ESC_Alpha:=20; - - try - for j:=0 to 40 do - begin - if ( j < length( Data ) ) AND - ( k < length( Data ) ) then - begin - if Data[j] >= Data[k] then - k:=j; - end; - end; - except - end; - - - if Data[k]>0.25 then ESC_Alpha:=5 else inc(ESC_Alpha); - if ESC_Alpha >20 then ESC_Alpha:=20; - if ((CTime-STime)<20) then ESC_Alpha:=20; - if CTime <=STime+10 then j:=CTime-STime else j:=10; - if (CTime >=STime+Delay-10) then if (CTime <=STime+Delay) then j:=(STime+Delay)-CTime else j:=0; - glColor4f(1, 1, 1, ESC_Alpha/20*j/10); - - if (CTime >= STime+20) and (CTime<=STime+22) then begin - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5); - end; - - glPushMatrix; - gltranslatef(223,329,0); - if CTime <= STime+20 then begin - j:=CTime-Stime; - glscalef(j*j/400,j*j/400,j*j/400); - glrotatef(j*18.0,0,0,1); - end; - if CTime >=STime+Delay-10 then if CTime <=STime+Delay then begin - j:=CTime-(STime+Delay-10); - f:=j*10.0; - gltranslatef(f*3,-f,0); - glscalef(1+j/10,1+j/10,1+j/10); - glrotatef(j*9.0,0,0,1); - end; - glBindTexture(GL_TEXTURE_2D, credits_blindy.TexNum); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); - glEnable(GL_TEXTURE_2D); - glbegin(gl_quads); - glTexCoord2f(0,0);glVertex2f(-163, -129); - glTexCoord2f(0,1);glVertex2f(-163, 129); - glTexCoord2f(1,1); glVertex2f(163, 129); - glTexCoord2f(1,0);glVertex2f(163, -129); - glEnd; - gldisable(gl_texture_2d); - gldisable(GL_BLEND); - glPopMatrix; - end; - -// Canni (von links reinschieben, nach rechts oben rausschieben) - STime:=Timings[11]-10; - Delay:=Timings[12]-Timings[11]+5; - if CTime > STime then - begin - k:=0; - ESC_Alpha:=20; - - try - for j:=0 to 40 do - begin - if ( j < length( Data ) ) AND - ( k < length( Data ) ) then - begin - if Data[j] >= Data[k] then - k:=j; - end; - end; - except - end; - - - if Data[k]>0.25 then ESC_Alpha:=5 else inc(ESC_Alpha); - if ESC_Alpha >20 then ESC_Alpha:=20; - if ((CTime-STime)<20) then ESC_Alpha:=20; - if CTime <=STime+10 then j:=CTime-STime else j:=10; - if (CTime >=STime+Delay-10) then if (CTime <=STime+Delay) then j:=(STime+Delay)-CTime else j:=0; - glColor4f(1, 1, 1, ESC_Alpha/20*j/10); - - if (CTime >= STime+10) and (CTime<=STime+12) then begin - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5); - end; - - glPushMatrix; - gltranslatef(223,329,0); - if CTime <= STime+10 then begin - gltranslatef(((CTime-STime)*21.0)-210,0,0); - end; - if CTime >=STime+Delay-10 then if CTime <=STime+Delay then begin - j:=(CTime-(STime+Delay-10))*21; - gltranslatef(j,-j/2,0); - end; - glBindTexture(GL_TEXTURE_2D, credits_canni.TexNum); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); - glEnable(GL_TEXTURE_2D); - glbegin(gl_quads); - glTexCoord2f(0,0);glVertex2f(-163, -129); - glTexCoord2f(0,1);glVertex2f(-163, 129); - glTexCoord2f(1,1); glVertex2f(163, 129); - glTexCoord2f(1,0);glVertex2f(163, -129); - glEnd; - gldisable(gl_texture_2d); - gldisable(GL_BLEND); - glPopMatrix; - end; - -// Commandio (von unten reinklappen, nach rechts oben rausklappen) - STime:=Timings[12]-10; - Delay:=Timings[13]-Timings[12]; - if CTime > STime then - begin - k:=0; - ESC_Alpha:=20; - - try - for j:=0 to 40 do - begin - if ( j < length( Data ) ) AND - ( k < length( Data ) ) then - begin - if Data[j] >= Data[k] then - k:=j; - end; - end; - except - end; - - - if Data[k]>0.25 then ESC_Alpha:=5 else inc(ESC_Alpha); - if ESC_Alpha >20 then ESC_Alpha:=20; - if ((CTime-STime)<20) then ESC_Alpha:=20; - if CTime <=STime+10 then j:=CTime-STime else j:=10; - if (CTime >=STime+Delay-10) then if (CTime <=STime+Delay) then j:=(STime+Delay)-CTime else j:=0; - glColor4f(1, 1, 1, ESC_Alpha/20*j/10); - - if (CTime >= STime+10) and (CTime<=STime+12) then begin - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5); - end; - - glPushMatrix; - gltranslatef(223,329,0); - if CTime <= STime+10 then - f:=258.0-25.8*(CTime-STime) - else - f:=0; - g:=0; - if CTime >=STime+Delay-10 then if CTime <=STime+Delay then begin - j:=CTime-(STime+Delay-10); - g:=32.6*j; - end; - glBindTexture(GL_TEXTURE_2D, credits_commandio.TexNum); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); - glEnable(GL_TEXTURE_2D); - glbegin(gl_quads); - glTexCoord2f(0,0);glVertex2f(-163+g-f*1.5, -129+f*1.5-g/2); - glTexCoord2f(0,1);glVertex2f(-163+g*1.5, 129-(g*1.5*258/326)); - glTexCoord2f(1,1); glVertex2f(163+g, 129+g/4); - glTexCoord2f(1,0);glVertex2f(163+f*1.5+g/4, -129+f*1.5-g/4); - glEnd; - gldisable(gl_texture_2d); - gldisable(GL_BLEND); - glPopMatrix; - end; - -// lazy joker (just scrolls from left to right, no twinkling stars, no on-beat flashing) - STime:=Timings[13]-35; - Delay:=Timings[14]-Timings[13]+5; - if CTime > STime then - begin - k:=0; - - try - for j:=0 to 40 do - begin - if ( j < length( Data ) ) AND - ( k < length( Data ) ) then - begin - if Data[j] >= Data[k] then - k:=j; - end; - end; - except - end; - - - if Data[k]>0.25 then ESC_Alpha:=5 else inc(ESC_Alpha); - if ESC_Alpha >20 then ESC_Alpha:=20; - if ((CTime-STime)>10) and ((CTime-STime)<20) then ESC_Alpha:=20; - ESC_Alpha:=10; - f:=CTime-STime; - if CTime <=STime+40 then j:=CTime-STime else j:=40; - if (CTime >=STime+Delay-40) then if (CTime <=STime+Delay) then j:=(STime+Delay)-CTime else j:=0; - glColor4f(1, 1, 1, ESC_Alpha/20*j*j/1600); - - glPushMatrix; - gltranslatef(180+(f-70),329,0); - glBindTexture(GL_TEXTURE_2D, credits_lazyjoker.TexNum); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); - glEnable(GL_TEXTURE_2D); - glbegin(gl_quads); - glTexCoord2f(0,0);glVertex2f(-163, -129); - glTexCoord2f(0,1);glVertex2f(-163, 129); - glTexCoord2f(1,1); glVertex2f(163, 129); - glTexCoord2f(1,0);glVertex2f(163, -129); - glEnd; - gldisable(gl_texture_2d); - gldisable(GL_BLEND); - glPopMatrix; - end; - -// Mog (von links reinklappen, nach rechts unten rausklappen) - STime:=Timings[14]-10; - Delay:=Timings[15]-Timings[14]+5; - if CTime > STime then - begin - k:=0; - ESC_Alpha:=20; - - - try - for j:=0 to 40 do - begin - if ( j < length( Data ) ) AND - ( k < length( Data ) ) then - begin - if Data[j] >= Data[k] then - k:=j; - end; - end; - except - end; - - - if Data[k]>0.25 then ESC_Alpha:=5 else inc(ESC_Alpha); - if ESC_Alpha >20 then ESC_Alpha:=20; - if ((CTime-STime)<20) then ESC_Alpha:=20; - if CTime <=STime+10 then j:=CTime-STime else j:=10; - if (CTime >=STime+Delay-10) then if (CTime <=STime+Delay) then j:=(STime+Delay)-CTime else j:=0; - glColor4f(1, 1, 1, ESC_Alpha/20*j/10); - - if (CTime >= STime+10) and (CTime<=STime+12) then begin - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5); - end; - - glPushMatrix; - gltranslatef(223,329,0); - if CTime <= STime+10 then - f:=326.0-32.6*(CTime-STime) - else - f:=0; - - g:=0; - if CTime >=STime+Delay-10 then if CTime <=STime+Delay then begin - j:=CTime-(STime+Delay-10); - g:=32.6*j; - end; - glBindTexture(GL_TEXTURE_2D, credits_mog.TexNum); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); - glEnable(GL_TEXTURE_2D); - glbegin(gl_quads); - glTexCoord2f(0,0);glVertex2f(-163+g*1.5, -129+g*1.5); - glTexCoord2f(0,1);glVertex2f(-163+g*1.2, 129+g); - glTexCoord2f(1,1); glVertex2f(163-f+g/2, 129+f*1.5+g/4); - glTexCoord2f(1,0);glVertex2f(163-f+g*1.5, -129-f*1.5); - glEnd; - gldisable(gl_texture_2d); - gldisable(GL_BLEND); - glPopMatrix; - end; - -// Mota (von rechts oben reindrehen, nach links unten rausschieben und verkleinern und dabei drehen) - STime:=Timings[15]-10; - Delay:=Timings[16]-Timings[15]+5; - if CTime > STime then - begin - k:=0; - ESC_Alpha:=20; - - try - for j:=0 to 40 do - begin - if ( j < length( Data ) ) AND - ( k < length( Data ) ) then - begin - if Data[j] >= Data[k] then - k:=j; - end; - end; - except - end; - - - if Data[k]>0.25 then ESC_Alpha:=5 else inc(ESC_Alpha); - if ESC_Alpha >20 then ESC_Alpha:=20; - if ((CTime-STime)<20) then ESC_Alpha:=20; - if CTime <=STime+10 then j:=CTime-STime else j:=10; - if (CTime >=STime+Delay-10) then if (CTime <=STime+Delay) then j:=(STime+Delay)-CTime else j:=0; - glColor4f(1, 1, 1, ESC_Alpha/20*j/10); - - if (CTime >= STime+10) and (CTime<=STime+12) then begin - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5); - end; - - glPushMatrix; - gltranslatef(223,329,0); - if CTime <= STime+10 then begin - gltranslatef(223,0,0); - glrotatef((10-(CTime-STime))*9,0,0,1); - gltranslatef(-223,0,0); - end; - if CTime >=STime+Delay-10 then if CTime <=STime+Delay then begin - j:=CTime-(STime+Delay-10); - f:=j*10.0; - gltranslatef(-f*2,-f,0); - glscalef(1-j/10,1-j/10,1-j/10); - glrotatef(-j*9.0,0,0,1); - end; - glBindTexture(GL_TEXTURE_2D, credits_mota.TexNum); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); - glEnable(GL_TEXTURE_2D); - glbegin(gl_quads); - glTexCoord2f(0,0);glVertex2f(-163, -129); - glTexCoord2f(0,1);glVertex2f(-163, 129); - glTexCoord2f(1,1); glVertex2f(163, 129); - glTexCoord2f(1,0);glVertex2f(163, -129); - glEnd; - gldisable(gl_texture_2d); - gldisable(GL_BLEND); - glPopMatrix; - end; - -// Skillmaster (von rechts unten reinschieben, nach rechts oben rausdrehen) - STime:=Timings[16]-10; - Delay:=Timings[17]-Timings[16]+5; - if CTime > STime then - begin - k:=0; - ESC_Alpha:=20; - - try - for j:=0 to 40 do - begin - if ( j < length( Data ) ) AND - ( k < length( Data ) ) then - begin - if Data[j] >= Data[k] then - k:=j; - end; - end; - except - end; - - - if Data[k]>0.25 then ESC_Alpha:=5 else inc(ESC_Alpha); - if ESC_Alpha >20 then ESC_Alpha:=20; - if ((CTime-STime)<20) then ESC_Alpha:=20; - if CTime <=STime+10 then j:=CTime-STime else j:=10; - if (CTime >=STime+Delay-10) then if (CTime <=STime+Delay) then j:=(STime+Delay)-CTime else j:=0; - glColor4f(1, 1, 1, ESC_Alpha/20*j/10); - - if (CTime >= STime+10) and (CTime<=STime+12) then begin - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5); - end; - - glPushMatrix; - gltranslatef(223,329,0); - if CTime <= STime+10 then begin - j:=STime+10-CTime; - f:=j*10.0; - gltranslatef(+f*2,+f/2,0); - end; - if CTime >=STime+Delay-10 then if CTime <=STime+Delay then begin - j:=CTime-(STime+Delay-10); - gltranslatef(0,-223,0); - glrotatef(integer(j)*-9,0,0,1); - gltranslatef(0,223,0); - glrotatef(j*9,0,0,1); - end; - glBindTexture(GL_TEXTURE_2D, credits_skillmaster.TexNum); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); - glEnable(GL_TEXTURE_2D); - glbegin(gl_quads); - glTexCoord2f(0,0);glVertex2f(-163, -129); - glTexCoord2f(0,1);glVertex2f(-163, 129); - glTexCoord2f(1,1); glVertex2f(163, 129); - glTexCoord2f(1,0);glVertex2f(163, -129); - glEnd; - gldisable(gl_texture_2d); - gldisable(GL_BLEND); - glPopMatrix; - end; - -// WhiteShark (von links unten reinklappen, nach rechts oben rausklappen) - STime:=Timings[17]-10; - Delay:=Timings[18]-Timings[17]; - if CTime > STime then - begin - k:=0; - ESC_Alpha:=20; - - try - for j:=0 to 40 do - begin - if ( j < length( Data ) ) AND - ( k < length( Data ) ) then - begin - if Data[j] >= Data[k] then - k:=j; - end; - end; - except - end; - - - if Data[k]>0.25 then ESC_Alpha:=5 else inc(ESC_Alpha); - if ESC_Alpha >20 then ESC_Alpha:=20; - if ((CTime-STime)<20) then ESC_Alpha:=20; - if CTime <=STime+10 then j:=CTime-STime else j:=10; - if (CTime >=STime+Delay-10) then if (CTime <=STime+Delay) then j:=(STime+Delay)-CTime else j:=0; - glColor4f(1, 1, 1, ESC_Alpha/20*j/10); - - if (CTime >= STime+10) and (CTime<=STime+12) then begin - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1); - GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5); - end; - - glPushMatrix; - gltranslatef(223,329,0); - if CTime <= STime+10 then - f:=326.0-32.6*(CTime-STime) - else - f:=0; - - if CTime >=STime+Delay-10 then if CTime <=STime+Delay then begin - j:=CTime-(STime+Delay-10); - g:=32.6*j; - end else - g:=0; - glBindTexture(GL_TEXTURE_2D, credits_whiteshark.TexNum); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); - glEnable(GL_TEXTURE_2D); - glbegin(gl_quads); - glTexCoord2f(0,0);glVertex2f(-163-f+g, -129+f/4-g/2); - glTexCoord2f(0,1);glVertex2f(-163-f/4+g, 129+g/2+f/4); - glTexCoord2f(1,1); glVertex2f(163-f*1.2+g/4, 129+f/2-g/4); - glTexCoord2f(1,0);glVertex2f(163-f*1.5+g/4, -129+f*1.5+g/4); - glEnd; - gldisable(gl_texture_2d); - gldisable(GL_BLEND); - glPopMatrix; - end; - - - Log.LogStatus('',' JB-103'); - -// #################################################################### -// do some twinkle stuff (kinda on beat) - if (CTime > Timings[8] ) and - (CTime < Timings[19] ) then - begin - k := 0; - - try - for j:=0 to 40 do - begin - if ( j < length( Data ) ) AND - ( k < length( Data ) ) then - begin - if Data[j] >= Data[k] then - k:=j; - end; - end; - except - end; - - if Data[k]>0.2 then - begin - l := RandomRange(6,16); - j := RandomRange(0,27); - - GoldenRec.Spawn(myLogoCoords[j,0], myLogoCoords[j,1], 16-l, l, 0, -1, PerfectNote, 0); - end; - end; - -//################################################# -// draw the rest of the main screen (girl and logo - glEnable(GL_TEXTURE_2D); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); - glColor4f(1, 1, 1, 1); - glBindTexture(GL_TEXTURE_2D, credits_bg_ovl.TexNum); - glbegin(gl_quads); - glTexCoord2f(0,0);glVertex2f(800-393, 0); - glTexCoord2f(0,600/1024);glVertex2f(800-393, 600); - glTexCoord2f(393/512,600/1024); glVertex2f(800, 600); - glTexCoord2f(393/512,0);glVertex2f(800, 0); - glEnd; -{ glBindTexture(GL_TEXTURE_2D, credits_bg_logo.TexNum); - glbegin(gl_quads); - glTexCoord2f(0,0);glVertex2f(0, 0); - glTexCoord2f(0,112/128);glVertex2f(0, 112); - glTexCoord2f(497/512,112/128); glVertex2f(497, 112); - glTexCoord2f(497/512,0);glVertex2f(497, 0); - glEnd; -} - gldisable(gl_texture_2d); - glDisable(GL_BLEND); - - // fade out at end of main part - if Ctime > Timings[19] then - begin - glColor4f(0,0,0,(Ctime-Timings[19])/(Timings[20]-Timings[19])); - glEnable(GL_BLEND); - glBegin(GL_QUADS); - glVertex2f(0,0); - glVertex2f(0,600); - glVertex2f(800,600); - glVertex2f(800,0); - glEnd; - glDisable(GL_BLEND); - end; - end - else - if (CRDTS_Stage=Outro) then - begin - if CTime=Timings[20] then begin - CTime_hold:=0; - AudioPlayback.Stop; - AudioPlayback.Open(soundpath + 'credits-outro-tune.mp3'); - AudioPlayback.Play; - AudioPlayback.SetVolume(20); - AudioPlayback.SetLoop(True); - end; - if CTime_hold > 231 then begin - AudioPlayback.Play; - Ctime_hold:=0; - end; - glClearColor(0,0,0,0); - glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); - - // do something useful - // outro background - glEnable(GL_TEXTURE_2D); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); - - glColor4f(1, 1, 1, 1); - glBindTexture(GL_TEXTURE_2D, outro_bg.TexNum); - glbegin(gl_quads); - glTexCoord2f(0,0);glVertex2f(0, 0); - glTexCoord2f(0,600/1024);glVertex2f(0, 600); - glTexCoord2f(800/1024,600/1024); glVertex2f(800, 600); - glTexCoord2f(800/1024,0);glVertex2f(800, 0); - glEnd; - - //outro overlays - glColor4f(1, 1, 1, (1+sin(CTime/15))/3+1/3); - glBindTexture(GL_TEXTURE_2D, outro_esc.TexNum); - glbegin(gl_quads); - glTexCoord2f(0,0);glVertex2f(0, 0); - glTexCoord2f(0,223/256);glVertex2f(0, 223); - glTexCoord2f(487/512,223/256); glVertex2f(487, 223); - glTexCoord2f(487/512,0);glVertex2f(487, 0); - glEnd; - - ESC_Alpha:=20; - if (RandomRange(0,20) > 18) and (ESC_Alpha=20) then - ESC_Alpha:=0 - else inc(ESC_Alpha); - if ESC_Alpha > 20 then ESC_Alpha:=20; - glColor4f(1, 1, 1, ESC_Alpha/20); - glBindTexture(GL_TEXTURE_2D, outro_exd.TexNum); - glbegin(gl_quads); - glTexCoord2f(0,0);glVertex2f(800-310, 600-247); - glTexCoord2f(0,247/256);glVertex2f(800-310, 600); - glTexCoord2f(310/512,247/256); glVertex2f(800, 600); - glTexCoord2f(310/512,0);glVertex2f(800, 600-247); - glEnd; - glDisable(GL_TEXTURE_2D); - glDisable(GL_BLEND); - - // outro scrollers? - // ... - end; - -{ // draw credits runtime counter - SetFontStyle (2); - SetFontItalic(False); - SetFontSize(9); - SetFontPos (5, 5); - glColor4f(1, 1, 1, 1); -// RuntimeStr:='CTime: '+inttostr(floor(CTime/30.320663991914489602156136106092))+'.'+inttostr(floor(CTime/3.0320663991914489602156136106092)-floor(CTime/30.320663991914489602156136106092)*10); - RuntimeStr:='CTime: '+inttostr(CTime); - glPrint (Addr(RuntimeStr[1])); -} - - - glEnable(GL_TEXTURE_2D); - glEnable(GL_BLEND); - glColor4f(1, 1, 1, 1); - glBindTexture(GL_TEXTURE_2D, myTex); - glbegin(gl_quads); - glTexCoord2f(0,0);glVertex2f(100, 100); - glTexCoord2f(0,1);glVertex2f(100, 200); - glTexCoord2f(1,1); glVertex2f(200, 200); - glTexCoord2f(1,0);glVertex2f(200, 100); - glEnd; - glDisable(GL_TEXTURE_2D); - glDisable(GL_BLEND); - - - // make the stars shine - GoldenRec.Draw; -end; - -end. +unit UScreenCredits;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+
+uses
+ UMenu,
+ SDL,
+ SDL_Image,
+ UDisplay,
+ UTexture,
+ OpenGL12,
+ UMusic,
+ UFiles,
+ SysUtils,
+ UThemes,
+ ULCD,
+ ULight,
+ UGraphicClasses;
+
+type
+ TCreditsStages=(InitialDelay,Intro,MainPart,Outro);
+
+ TScreenCredits = class(TMenu)
+ public
+
+ Credits_X: Real;
+ Credits_Time: Cardinal;
+ Credits_Alpha: Cardinal;
+ CTime: Cardinal;
+ CTime_hold: Cardinal;
+ ESC_Alpha: Integer;
+
+ credits_entry_tex: TTexture;
+ credits_entry_dx_tex: TTexture;
+ credits_bg_tex: TTexture;
+ credits_bg_ovl: TTexture;
+// credits_bg_logo: TTexture;
+ credits_bg_scrollbox_left: TTexture;
+ credits_blindguard: TTexture;
+ credits_blindy: TTexture;
+ credits_canni: TTexture;
+ credits_commandio: TTexture;
+ credits_lazyjoker: TTexture;
+ credits_mog: TTexture;
+ credits_mota: TTexture;
+ credits_skillmaster: TTexture;
+ credits_whiteshark: TTexture;
+ intro_layer01: TTexture;
+ intro_layer02: TTexture;
+ intro_layer03: TTexture;
+ intro_layer04: TTexture;
+ intro_layer05: TTexture;
+ intro_layer06: TTexture;
+ intro_layer07: TTexture;
+ intro_layer08: TTexture;
+ intro_layer09: TTexture;
+ outro_bg: TTexture;
+ outro_esc: TTexture;
+ outro_exd: TTexture;
+
+ deluxe_slidein: cardinal;
+
+ CurrentScrollText: String;
+ NextScrollUpdate: Real;
+ EndofLastScrollingPart: Cardinal;
+ CurrentScrollStart, CurrentScrollEnd: Integer;
+
+ CRDTS_Stage: TCreditsStages;
+
+ myTex: glUint;
+ mysdlimage,myconvertedsdlimage: PSDL_Surface;
+
+ Fadeout: boolean;
+ constructor Create; override;
+ function ParseInput(PressedKey: Cardinal; ScanCode: byte; PressedDown: Boolean): Boolean; override;
+ function Draw: boolean; override;
+ procedure onShow; override;
+ procedure onHide; override;
+ procedure DrawCredits;
+ procedure Draw_FunkyText;
+ end;
+
+const
+ Funky_Text: AnsiString =
+ 'Grandma Deluxe has arrived! Thanks to Corvus5 for the massive work on UltraStar, Wome for the nice tune you´re hearing, '+
+ 'all the people who put massive effort and work in new songs (don´t forget UltraStar w/o songs would be nothing), ppl from '+
+ 'irc helping us - eBandit and Gabari, scene ppl who really helped instead of compiling and running away. Greetings to DennisTheMenace for betatesting, '+
+ 'Demoscene.tv, pouet.net, KakiArts, Sourceforge,..';
+
+
+ Timings: array[0..21] of Cardinal=(
+ 20, // 0 Delay vor Start
+
+ 149, // 1 Ende erster Intro Zoom
+ 155, // 2 Start 2. Action im Intro
+ 170, // 3 Ende Separation im Intro
+ 271, // 4 Anfang Zoomout im Intro
+ 0, // 5 unused
+ 261, // 6 Start fade-to-white im Intro
+
+ 271, // 7 Start Main Part
+ 280, // 8 Start On-Beat-Sternchen Main Part
+
+ 396, // 9 Start BlindGuard
+ 666, // 10 Start blindy
+ 936, // 11 Start Canni
+ 1206, // 12 Start Commandio
+ 1476, // 13 Start LazyJoker
+ 1746, // 14 Start Mog
+ 2016, // 15 Start Mota
+ 2286, // 16 Start SkillMaster
+ 2556, // 17 Start WhiteShark
+ 2826, // 18 Ende Whiteshark
+ 3096, // 19 Start FadeOut Mainscreen
+ 3366, // 20 Ende Credits Tune
+ 60); // 21 start flare im intro
+
+
+ sdl32bpprgba: TSDL_Pixelformat=(palette: nil;
+ BitsPerPixel: 32;
+ BytesPerPixel: 4;
+ Rloss: 0;
+ Gloss: 0;
+ Bloss: 0;
+ Aloss: 0;
+ Rshift: 0;
+ Gshift: 8;
+ Bshift: 16;
+ Ashift: 24;
+ Rmask: $000000ff;
+ Gmask: $0000ff00;
+ Bmask: $00ff0000;
+ Amask: $ff000000;
+ colorkey: 0;
+ alpha: 255 );
+
+
+implementation
+
+uses {$IFDEF win32}
+ windows,
+ {$ELSE}
+ lclintf,
+ {$ENDIF}
+ ULog,
+ UGraphic,
+ UMain,
+ UIni,
+ USongs,
+ Textgl,
+ ULanguage,
+ UCommon,
+ Math,
+ dialogs;
+
+
+function TScreenCredits.ParseInput(PressedKey: Cardinal; ScanCode: byte; PressedDown: Boolean): Boolean;
+begin
+ Result := true;
+ If (PressedDown) Then
+ begin // Key Down
+ case PressedKey of
+
+ SDLK_ESCAPE,
+ SDLK_BACKSPACE :
+ begin
+ FadeTo(@ScreenMain);
+ AudioPlayback.PlaySound(SoundLib.Back);
+ end;
+{ SDLK_SPACE:
+ begin
+ setlength(CTime_hold,length(CTime_hold)+1);
+ CTime_hold[high(CTime_hold)]:=CTime;
+ end;
+}
+ end;//esac
+ end; //fi
+end;
+
+constructor TScreenCredits.Create;
+begin
+ inherited Create;
+
+ credits_bg_tex := Texture.LoadTexture(true, 'CRDTS_BG', 'PNG', 'Plain', 0);
+ credits_bg_ovl := Texture.LoadTexture(true, 'CRDTS_OVL', 'PNG', 'Transparent', 0);
+
+ credits_blindguard := Texture.LoadTexture(true, 'CRDTS_blindguard', 'PNG', 'Font Black', 0);
+ credits_blindy := Texture.LoadTexture(true, 'CRDTS_blindy', 'PNG', 'Font Black', 0);
+ credits_canni := Texture.LoadTexture(true, 'CRDTS_canni', 'PNG', 'Font Black', 0);
+ credits_commandio := Texture.LoadTexture(true, 'CRDTS_commandio', 'PNG', 'Font Black', 0);
+ credits_lazyjoker := Texture.LoadTexture(true, 'CRDTS_lazyjoker', 'PNG', 'Font Black', 0);
+ credits_mog := Texture.LoadTexture(true, 'CRDTS_mog', 'PNG', 'Font Black', 0);
+ credits_mota := Texture.LoadTexture(true, 'CRDTS_mota', 'PNG', 'Font Black', 0);
+ credits_skillmaster := Texture.LoadTexture(true, 'CRDTS_skillmaster', 'PNG', 'Font Black', 0);
+ credits_whiteshark := Texture.LoadTexture(true, 'CRDTS_whiteshark', 'PNG', 'Font Black', 0);
+
+ intro_layer01 := Texture.LoadTexture(true, 'INTRO_L01', 'PNG', 'Transparent', 0);
+ intro_layer02 := Texture.LoadTexture(true, 'INTRO_L02', 'PNG', 'Transparent', 0);
+ intro_layer03 := Texture.LoadTexture(true, 'INTRO_L03', 'PNG', 'Transparent', 0);
+ intro_layer04 := Texture.LoadTexture(true, 'INTRO_L04', 'PNG', 'Transparent', 0);
+ intro_layer05 := Texture.LoadTexture(true, 'INTRO_L05', 'PNG', 'Transparent', 0);
+ intro_layer06 := Texture.LoadTexture(true, 'INTRO_L06', 'PNG', 'Transparent', 0);
+ intro_layer07 := Texture.LoadTexture(true, 'INTRO_L07', 'PNG', 'Transparent', 0);
+ intro_layer08 := Texture.LoadTexture(true, 'INTRO_L08', 'PNG', 'Transparent', 0);
+ intro_layer09 := Texture.LoadTexture(true, 'INTRO_L09', 'PNG', 'Transparent', 0);
+
+ outro_bg := Texture.LoadTexture(true, 'OUTRO_BG', 'PNG', 'Plain', 0);
+ outro_esc := Texture.LoadTexture(true, 'OUTRO_ESC', 'PNG', 'Transparent', 0);
+ outro_exd := Texture.LoadTexture(true, 'OUTRO_EXD', 'PNG', 'Transparent', 0);
+
+ CRDTS_Stage:=InitialDelay;
+end;
+
+function TScreenCredits.Draw: boolean;
+begin
+ DrawCredits;
+ Draw:=true;
+end;
+
+function pixfmt_eq(fmt1,fmt2: TSDL_Pixelformat): boolean;
+begin
+ if (fmt1.BitsPerPixel = fmt2.BitsPerPixel) and
+ (fmt1.BytesPerPixel = fmt2.BytesPerPixel) and
+ (fmt1.Rloss = fmt2.Rloss) and
+ (fmt1.Gloss = fmt2.Gloss) and
+ (fmt1.Bloss = fmt2.Bloss) and
+ (fmt1.Rmask = fmt2.Rmask) and
+ (fmt1.Gmask = fmt2.Gmask) and
+ (fmt1.Bmask = fmt2.Bmask) and
+ (fmt1.Rshift = fmt2.Rshift) and
+ (fmt1.Gshift = fmt2.Gshift) and
+ (fmt1.Bshift = fmt2.Bshift)
+ then
+ pixfmt_eq:=True
+ else
+ pixfmt_eq:=False;
+end;
+
+function inttohexstr(i: cardinal):pchar;
+var helper, i2, c:cardinal;
+ tmpstr: string;
+begin
+ helper:=0;
+ i2:=i;
+ tmpstr:='';
+ for c:=1 to 8 do
+ begin
+ helper:=(helper shl 4) or (i2 and $f);
+ i2:=i2 shr 4;
+ end;
+ for c:=1 to 8 do
+ begin
+ i2:=helper and $f;
+ helper := helper shr 4;
+ case i2 of
+ 0: tmpstr:=tmpstr+'0';
+ 1: tmpstr:=tmpstr+'1';
+ 2: tmpstr:=tmpstr+'2';
+ 3: tmpstr:=tmpstr+'3';
+ 4: tmpstr:=tmpstr+'4';
+ 5: tmpstr:=tmpstr+'5';
+ 6: tmpstr:=tmpstr+'6';
+ 7: tmpstr:=tmpstr+'7';
+ 8: tmpstr:=tmpstr+'8';
+ 9: tmpstr:=tmpstr+'9';
+ 10: tmpstr:=tmpstr+'a';
+ 11: tmpstr:=tmpstr+'b';
+ 12: tmpstr:=tmpstr+'c';
+ 13: tmpstr:=tmpstr+'d';
+ 14: tmpstr:=tmpstr+'e';
+ 15: tmpstr:=tmpstr+'f';
+ end;
+ end;
+ inttohexstr:=pchar(tmpstr);
+end;
+
+procedure TScreenCredits.onShow;
+begin
+ CRDTS_Stage:=InitialDelay;
+ Credits_X := 580;
+ deluxe_slidein := 0;
+ Credits_Alpha := 0;
+ //Music.SetLoop(true); Loop looped ned, so ne scheisse
+ AudioPlayback.Open(soundpath + 'wome-credits-tune.mp3'); //danke kleinster liebster weeeetüüüüü!!
+// Music.Play;
+ CTime:=0;
+// setlength(CTime_hold,0);
+
+ mysdlimage:=IMG_Load('test.png');
+ if assigned(mysdlimage) then
+ begin
+ {$IFNDEF FPC}
+ showmessage('opened image via SDL_Image'+#13#10+
+ 'Width: '+inttostr(mysdlimage^.w)+#13#10+
+ 'Height: '+inttostr(mysdlimage^.h)+#13#10+
+ 'BitsPP: '+inttostr(mysdlimage^.format.BitsPerPixel)+#13#10+
+ 'BytesPP: '+inttostr(mysdlimage^.format.BytesPerPixel)+#13#10+
+ 'Rloss: '+inttostr(mysdlimage^.format.Rloss)+#13#10+
+ 'Gloss: '+inttostr(mysdlimage^.format.Gloss)+#13#10+
+ 'Bloss: '+inttostr(mysdlimage^.format.Bloss)+#13#10+
+ 'Aloss: '+inttostr(mysdlimage^.format.Aloss)+#13#10+
+ 'Rshift: '+inttostr(mysdlimage^.format.Rshift)+#13#10+
+ 'Gshift: '+inttostr(mysdlimage^.format.Gshift)+#13#10+
+ 'Bshift: '+inttostr(mysdlimage^.format.Bshift)+#13#10+
+ 'Ashift: '+inttostr(mysdlimage^.format.Ashift)+#13#10+
+ 'Rmask: '+inttohexstr(mysdlimage^.format.Rmask)+#13#10+
+ 'Gmask: '+inttohexstr(mysdlimage^.format.Gmask)+#13#10+
+ 'Bmask: '+inttohexstr(mysdlimage^.format.Bmask)+#13#10+
+ 'Amask: '+inttohexstr(mysdlimage^.format.Amask)+#13#10+
+ 'ColKey: '+inttostr(mysdlimage^.format.Colorkey)+#13#10+
+ 'Alpha: '+inttostr(mysdlimage^.format.Alpha));
+
+ if pixfmt_eq(mysdlimage^.format^,sdl32bpprgba) then
+ showmessage('equal pixelformats')
+ else
+ showmessage('different pixelformats');
+ {$ENDIF}
+
+ myconvertedsdlimage:=SDL_ConvertSurface(mysdlimage,@sdl32bpprgba,SDL_SWSURFACE);
+ glGenTextures(1,@myTex);
+ glBindTexture(GL_TEXTURE_2D, myTex);
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ glTexImage2D( GL_TEXTURE_2D, 0, 4, myconvertedsdlimage^.w, myconvertedsdlimage^.h, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, myconvertedsdlimage^.pixels );
+ SDL_FreeSurface(mysdlimage);
+ SDL_FreeSurface(myconvertedsdlimage);
+ end
+ else
+ {$IFDEF FPC}
+ writeln( 'could not open file - test.png');
+ {$ELSE}
+ showmessage('could not open file - test.png');
+ {$ENDIF}
+
+end;
+
+procedure TScreenCredits.onHide;
+begin
+ AudioPlayback.Stop;
+end;
+
+Procedure TScreenCredits.Draw_FunkyText;
+var
+ S: Integer;
+ X,Y,A: Real;
+ visibleText: PChar;
+begin
+ SetFontSize(10);
+ //Init ScrollingText
+ if (CTime = Timings[7]) then
+ begin
+ //Set Position of Text
+ Credits_X := 600;
+ CurrentScrollStart:=1;
+ CurrentScrollEnd:=1;
+ end;
+
+ if (CTime > Timings[7]) and (CurrentScrollStart < length(Funky_Text)) then
+ begin
+ X:=0;
+ visibleText:=pchar(Copy(Funky_Text, CurrentScrollStart, CurrentScrollEnd));
+ for S := 0 to length(visibleText)-1 do begin
+ Y:=abs(sin((Credits_X+X)*0.93{*(((Credits_X+X))/1200)}/100*pi));
+ SetFontPos(Credits_X+X,538-Y*(Credits_X+X)*(Credits_X+X)*(Credits_X+X)/1000000);
+ A:=0;
+ if (Credits_X+X < 15) then A:=0;
+ if (Credits_X+X >=15) then A:=Credits_X+X-15;
+ if Credits_X+X > 32 then A:=17;
+ glColor4f( 230/255-40/255+Y*(Credits_X+X)/900, 200/255-30/255+Y*(Credits_X+X)/1000, 155/255-20/255+Y*(Credits_X+X)/1100, A/17);
+ glPrintLetter(visibleText[S]);
+ X := X + Fonts[ActFont].Width[Ord(visibleText[S])] * Fonts[ActFont].Tex.H / 30 * Fonts[ActFont].AspectW;
+ end;
+ if (Credits_X<0) and (CurrentScrollStart < length(Funky_Text)) then begin
+ Credits_X:=Credits_X + Fonts[ActFont].Width[Ord(Funky_Text[CurrentScrollStart])] * Fonts[ActFont].Tex.H / 30 * Fonts[ActFont].AspectW;
+ inc(CurrentScrollStart);
+ end;
+ visibleText:=pchar(Copy(Funky_Text, CurrentScrollStart, CurrentScrollEnd));
+ if (Credits_X+glTextWidth(visibleText) < 600) and (CurrentScrollEnd < length(Funky_Text)) then begin
+ inc(CurrentScrollEnd);
+ end;
+ end;
+{ // timing hack
+ X:=5;
+ SetFontStyle (2);
+ SetFontItalic(False);
+ SetFontSize(9);
+ glColor4f(1, 1, 1, 1);
+ for S:=0 to high(CTime_hold) do begin
+ visibleText:=pchar(inttostr(CTime_hold[S]));
+ SetFontPos (500, X);
+ glPrint (Addr(visibleText[0]));
+ X:=X+20;
+ end;}
+end;
+
+procedure Start3D;
+begin
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix;
+ glLoadIdentity;
+ glFrustum(-0.3*4/3,0.3*4/3,-0.3,0.3,1,1000);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity;
+end;
+procedure End3D;
+begin
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix;
+ glMatrixMode(GL_MODELVIEW);
+end;
+
+procedure TScreenCredits.DrawCredits;
+var
+ T,I: Cardinal;
+ X: Real;
+ Ver: PChar;
+ RuntimeStr: AnsiString;
+ Data: TFFTData;
+ j,k,l:cardinal;
+ f,g,h: Real;
+ STime:cardinal;
+ Delay:cardinal;
+
+ myPixel: longword;
+ myColor: Cardinal;
+ myScale: Real;
+ myAngle: Real;
+
+
+const myLogoCoords: Array[0..27,0..1] of Cardinal = ((39,32),(84,32),(100,16),(125,24),
+ (154,31),(156,58),(168,32),(203,36),
+ (258,34),(251,50),(274,93),(294,84),
+ (232,54),(278,62),(319,34),(336,92),
+ (347,23),(374,32),(377,58),(361,83),
+ (385,91),(405,91),(429,35),(423,51),
+ (450,32),(485,34),(444,91),(486,93));
+
+begin
+ //dis does teh muiwk y0r
+ AudioPlayback.GetFFTData(Data);
+
+ Log.LogStatus('',' JB-1');
+
+ T := GetTickCount div 33;
+ if T <> Credits_Time then
+ begin
+ Credits_Time := T;
+ inc(CTime);
+ inc(CTime_hold);
+ Credits_X := Credits_X-2;
+
+ Log.LogStatus('',' JB-2');
+ if (CRDTS_Stage=InitialDelay) and (CTime=Timings[0]) then
+ begin
+// CTime:=Timings[20];
+// CRDTS_Stage:=Outro;
+
+ CRDTS_Stage:=Intro;
+ CTime:=0;
+ AudioPlayback.Play;
+
+ end;
+ if (CRDTS_Stage=Intro) and (CTime=Timings[7]) then
+ begin
+ CRDTS_Stage:=MainPart;
+ end;
+ if (CRDTS_Stage=MainPart) and (CTime=Timings[20]) then
+ begin
+ CRDTS_Stage:=Outro;
+ end;
+ end;
+
+ Log.LogStatus('',' JB-3');
+
+ //draw background
+ if CRDTS_Stage=InitialDelay then
+ begin
+ glClearColor(0,0,0,0);
+ glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
+ end
+ else
+ if CRDTS_Stage=Intro then
+ begin
+ Start3D;
+ glPushMatrix;
+
+ glClearColor(0,0,0,0);
+ glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
+
+ glEnable(GL_TEXTURE_2D);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+
+ if CTime < Timings[1] then begin
+ myScale:= 0.5+0.5*(Timings[1]-CTime)/(Timings[1]); // slowly move layers together
+ myAngle:=cos((CTime)*pi/((Timings[1])*2)); // and make logo face towards camera
+ end else begin // this is the part when the logo stands still
+ myScale:=0.5;
+ myAngle:=0;
+ end;
+ if CTime > Timings[2] then begin
+ myScale:= 0.5+0.5*(CTime-Timings[2])/(Timings[3]-Timings[2]); // get some space between layers
+ myAngle:=0;
+ end;
+// if CTime > Timings[3] then myScale:=1; // keep the space between layers
+ glTranslatef(0,0,-5+0.5*myScale);
+ if CTime > Timings[3] then myScale:=1; // keep the space between layers
+ if CTime > Timings[3] then begin // make logo rotate left and grow
+// myScale:=(CTime-Timings[4])/(Timings[7]-Timings[4]);
+ glRotatef(20*sqr(CTime-Timings[3])/sqr((Timings[7]-Timings[3])/2),0,0,1);
+ glScalef(1+sqr(CTime-Timings[3])/(32*(Timings[7]-Timings[3])),1+sqr(CTime-Timings[3])/(32*(Timings[7]-Timings[3])),1);
+ end;
+ if CTime < Timings[2] then
+ glRotatef(30*myAngle,0.5*myScale+myScale,1+myScale,0);
+// glScalef(0.5,0.5,0.5);
+ glScalef(4/3,-1,1);
+ glColor4f(1, 1, 1, 1);
+
+ glBindTexture(GL_TEXTURE_2D, intro_layer01.TexNum);
+ glbegin(gl_quads);
+ glTexCoord2f(0,0);glVertex3f(-1, -1, -0.4 * myScale);
+ glTexCoord2f(0,1);glVertex3f(-1, 1, -0.4 * myScale);
+ glTexCoord2f(1,1); glVertex3f(1, 1, -0.4 * myScale);
+ glTexCoord2f(1,0);glVertex3f(1, -1, -0.4 * myScale);
+ glEnd;
+ glBindTexture(GL_TEXTURE_2D, intro_layer02.TexNum);
+ glbegin(gl_quads);
+ glTexCoord2f(0,0);glVertex3f(-1, -1, -0.3 * myScale);
+ glTexCoord2f(0,1);glVertex3f(-1, 1, -0.3 * myScale);
+ glTexCoord2f(1,1); glVertex3f(1, 1, -0.3 * myScale);
+ glTexCoord2f(1,0);glVertex3f(1, -1, -0.3 * myScale);
+ glEnd;
+ glBindTexture(GL_TEXTURE_2D, intro_layer03.TexNum);
+ glbegin(gl_quads);
+ glTexCoord2f(0,0);glVertex3f(-1, -1, -0.2 * myScale);
+ glTexCoord2f(0,1);glVertex3f(-1, 1, -0.2 * myScale);
+ glTexCoord2f(1,1); glVertex3f(1, 1, -0.2 * myScale);
+ glTexCoord2f(1,0);glVertex3f(1, -1, -0.2 * myScale);
+ glEnd;
+ glBindTexture(GL_TEXTURE_2D, intro_layer04.TexNum);
+ glbegin(gl_quads);
+ glTexCoord2f(0,0);glVertex3f(-1, -1, -0.1 * myScale);
+ glTexCoord2f(0,1);glVertex3f(-1, 1, -0.1 * myScale);
+ glTexCoord2f(1,1); glVertex3f(1, 1, -0.1 * myScale);
+ glTexCoord2f(1,0);glVertex3f(1, -1, -0.1 * myScale);
+ glEnd;
+ glBindTexture(GL_TEXTURE_2D, intro_layer05.TexNum);
+ glbegin(gl_quads);
+ glTexCoord2f(0,0);glVertex3f(-1, -1, 0 * myScale);
+ glTexCoord2f(0,1);glVertex3f(-1, 1, 0 * myScale);
+ glTexCoord2f(1,1); glVertex3f(1, 1, 0 * myScale);
+ glTexCoord2f(1,0);glVertex3f(1, -1, 0 * myScale);
+ glEnd;
+ glBindTexture(GL_TEXTURE_2D, intro_layer06.TexNum);
+ glbegin(gl_quads);
+ glTexCoord2f(0,0);glVertex3f(-1, -1, 0.1 * myScale);
+ glTexCoord2f(0,1);glVertex3f(-1, 1, 0.1 * myScale);
+ glTexCoord2f(1,1); glVertex3f(1, 1, 0.1 * myScale);
+ glTexCoord2f(1,0);glVertex3f(1, -1, 0.1 * myScale);
+ glEnd;
+ glBindTexture(GL_TEXTURE_2D, intro_layer07.TexNum);
+ glbegin(gl_quads);
+ glTexCoord2f(0,0);glVertex3f(-1, -1, 0.2 * myScale);
+ glTexCoord2f(0,1);glVertex3f(-1, 1, 0.2 * myScale);
+ glTexCoord2f(1,1); glVertex3f(1, 1, 0.2 * myScale);
+ glTexCoord2f(1,0);glVertex3f(1, -1, 0.2 * myScale);
+ glEnd;
+ glBindTexture(GL_TEXTURE_2D, intro_layer08.TexNum);
+ glbegin(gl_quads);
+ glTexCoord2f(0,0);glVertex3f(-1, -1, 0.3 * myScale);
+ glTexCoord2f(0,1);glVertex3f(-1, 1, 0.3 * myScale);
+ glTexCoord2f(1,1); glVertex3f(1, 1, 0.3 * myScale);
+ glTexCoord2f(1,0);glVertex3f(1, -1, 0.3 * myScale);
+ glEnd;
+ glBindTexture(GL_TEXTURE_2D, intro_layer09.TexNum);
+ glbegin(gl_quads);
+ glTexCoord2f(0,0);glVertex3f(-1, -1, 0.22 * myScale);
+ glTexCoord2f(0,1);glVertex3f(-1, 1, 0.22 * myScale);
+ glTexCoord2f(1,1); glVertex3f(1, 1, 0.22 * myScale);
+ glTexCoord2f(1,0);glVertex3f(1, -1, 0.22 * myScale);
+ glEnd;
+ gldisable(gl_texture_2d);
+ glDisable(GL_BLEND);
+
+ glPopMatrix;
+ End3D;
+
+ // do some sparkling effects
+ if (CTime < Timings[1]) and (CTime > Timings[21]) then
+ begin
+ for k:=1 to 3 do begin
+ l:=410+floor((CTime-Timings[21])/(Timings[1]-Timings[21])*(536-410))+RandomRange(-5,5);
+ j:=floor((Timings[1]-CTime)/22)+RandomRange(285,301);
+ GoldenRec.Spawn(l, j, 1, 16, 0, -1, Flare, 0);
+ end;
+ end;
+
+ // fade to white at end
+ if Ctime > Timings[6] then
+ begin
+ glColor4f(1,1,1,sqr(Ctime-Timings[6])*(Ctime-Timings[6])/sqr(Timings[7]-Timings[6]));
+ glEnable(GL_BLEND);
+ glBegin(GL_QUADS);
+ glVertex2f(0,0);
+ glVertex2f(0,600);
+ glVertex2f(800,600);
+ glVertex2f(800,0);
+ glEnd;
+ glDisable(GL_BLEND);
+ end;
+
+ end;
+ if (CRDTS_Stage=MainPart) then
+ // main credits screen background, scroller, logo and girl
+ begin
+
+ glEnable(GL_TEXTURE_2D);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+
+ glColor4f(1, 1, 1, 1);
+ glBindTexture(GL_TEXTURE_2D, credits_bg_tex.TexNum);
+ glbegin(gl_quads);
+ glTexCoord2f(0,0);glVertex2f(0, 0);
+ glTexCoord2f(0,600/1024);glVertex2f(0, 600);
+ glTexCoord2f(800/1024,600/1024); glVertex2f(800, 600);
+ glTexCoord2f(800/1024,0);glVertex2f(800, 0);
+ glEnd;
+ glDisable(GL_TEXTURE_2D);
+ glDisable(GL_BLEND);
+
+ // draw scroller
+ Draw_FunkyText;
+
+//#########################################################################
+// draw credits names
+
+
+Log.LogStatus('',' JB-4');
+
+// BlindGuard (von links oben reindrehen, nach rechts unten rausdrehen)
+ STime:=Timings[9]-10;
+ Delay:=Timings[10]-Timings[9];
+ if CTime > STime then
+ begin
+ k:=0;
+ ESC_Alpha:=20;
+
+ try
+ for j:=0 to 40 do
+ begin
+ if ( j < length( Data ) ) AND
+ ( k < length( Data ) ) then
+ begin
+ if Data[j] >= Data[k] then
+ k:=j;
+ end;
+ end;
+ except
+ end;
+
+ if Data[k]>0.25 then ESC_Alpha:=5 else inc(ESC_Alpha);
+ if ESC_Alpha >20 then ESC_Alpha:=20;
+ if ((CTime-STime)<20) then ESC_Alpha:=20;
+ if CTime <=STime+10 then j:=CTime-STime else j:=10;
+ if (CTime >=STime+Delay-10) then if (CTime <=STime+Delay) then j:=(STime+Delay)-CTime else j:=0;
+ glColor4f(1, 1, 1, ESC_Alpha/20*j/10);
+
+ if (CTime >= STime+10) and (CTime<=STime+12) then begin
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5);
+ end;
+
+ glPushMatrix;
+ gltranslatef(0,329,0);
+ if CTime <= STime+10 then begin glrotatef((CTime-STime)*9+270,0,0,1);end;
+ gltranslatef(223,0,0);
+ if CTime >=STime+Delay-10 then if CTime <=STime+Delay then begin
+ gltranslatef(223,0,0);
+ glrotatef((integer(CTime)-(integer(STime+Delay)-10))*-9,0,0,1);
+ gltranslatef(-223,0,0);
+ end;
+ glBindTexture(GL_TEXTURE_2D, credits_blindguard.TexNum);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ glEnable(GL_TEXTURE_2D);
+ glbegin(gl_quads);
+ glTexCoord2f(0,0);glVertex2f(-163, -129);
+ glTexCoord2f(0,1);glVertex2f(-163, 129);
+ glTexCoord2f(1,1); glVertex2f(163, 129);
+ glTexCoord2f(1,0);glVertex2f(163, -129);
+ glEnd;
+ gldisable(gl_texture_2d);
+ gldisable(GL_BLEND);
+ glPopMatrix;
+ end;
+
+// Blindy (zoom von 0 auf volle grösse und drehung, zoom auf doppelte grösse und nach rechts oben schieben)
+ STime:=Timings[10]-10;
+ Delay:=Timings[11]-Timings[10]+5;
+ if CTime > STime then
+ begin
+ k:=0;
+ ESC_Alpha:=20;
+
+ try
+ for j:=0 to 40 do
+ begin
+ if ( j < length( Data ) ) AND
+ ( k < length( Data ) ) then
+ begin
+ if Data[j] >= Data[k] then
+ k:=j;
+ end;
+ end;
+ except
+ end;
+
+
+ if Data[k]>0.25 then ESC_Alpha:=5 else inc(ESC_Alpha);
+ if ESC_Alpha >20 then ESC_Alpha:=20;
+ if ((CTime-STime)<20) then ESC_Alpha:=20;
+ if CTime <=STime+10 then j:=CTime-STime else j:=10;
+ if (CTime >=STime+Delay-10) then if (CTime <=STime+Delay) then j:=(STime+Delay)-CTime else j:=0;
+ glColor4f(1, 1, 1, ESC_Alpha/20*j/10);
+
+ if (CTime >= STime+20) and (CTime<=STime+22) then begin
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5);
+ end;
+
+ glPushMatrix;
+ gltranslatef(223,329,0);
+ if CTime <= STime+20 then begin
+ j:=CTime-Stime;
+ glscalef(j*j/400,j*j/400,j*j/400);
+ glrotatef(j*18.0,0,0,1);
+ end;
+ if CTime >=STime+Delay-10 then if CTime <=STime+Delay then begin
+ j:=CTime-(STime+Delay-10);
+ f:=j*10.0;
+ gltranslatef(f*3,-f,0);
+ glscalef(1+j/10,1+j/10,1+j/10);
+ glrotatef(j*9.0,0,0,1);
+ end;
+ glBindTexture(GL_TEXTURE_2D, credits_blindy.TexNum);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ glEnable(GL_TEXTURE_2D);
+ glbegin(gl_quads);
+ glTexCoord2f(0,0);glVertex2f(-163, -129);
+ glTexCoord2f(0,1);glVertex2f(-163, 129);
+ glTexCoord2f(1,1); glVertex2f(163, 129);
+ glTexCoord2f(1,0);glVertex2f(163, -129);
+ glEnd;
+ gldisable(gl_texture_2d);
+ gldisable(GL_BLEND);
+ glPopMatrix;
+ end;
+
+// Canni (von links reinschieben, nach rechts oben rausschieben)
+ STime:=Timings[11]-10;
+ Delay:=Timings[12]-Timings[11]+5;
+ if CTime > STime then
+ begin
+ k:=0;
+ ESC_Alpha:=20;
+
+ try
+ for j:=0 to 40 do
+ begin
+ if ( j < length( Data ) ) AND
+ ( k < length( Data ) ) then
+ begin
+ if Data[j] >= Data[k] then
+ k:=j;
+ end;
+ end;
+ except
+ end;
+
+
+ if Data[k]>0.25 then ESC_Alpha:=5 else inc(ESC_Alpha);
+ if ESC_Alpha >20 then ESC_Alpha:=20;
+ if ((CTime-STime)<20) then ESC_Alpha:=20;
+ if CTime <=STime+10 then j:=CTime-STime else j:=10;
+ if (CTime >=STime+Delay-10) then if (CTime <=STime+Delay) then j:=(STime+Delay)-CTime else j:=0;
+ glColor4f(1, 1, 1, ESC_Alpha/20*j/10);
+
+ if (CTime >= STime+10) and (CTime<=STime+12) then begin
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5);
+ end;
+
+ glPushMatrix;
+ gltranslatef(223,329,0);
+ if CTime <= STime+10 then begin
+ gltranslatef(((CTime-STime)*21.0)-210,0,0);
+ end;
+ if CTime >=STime+Delay-10 then if CTime <=STime+Delay then begin
+ j:=(CTime-(STime+Delay-10))*21;
+ gltranslatef(j,-j/2,0);
+ end;
+ glBindTexture(GL_TEXTURE_2D, credits_canni.TexNum);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ glEnable(GL_TEXTURE_2D);
+ glbegin(gl_quads);
+ glTexCoord2f(0,0);glVertex2f(-163, -129);
+ glTexCoord2f(0,1);glVertex2f(-163, 129);
+ glTexCoord2f(1,1); glVertex2f(163, 129);
+ glTexCoord2f(1,0);glVertex2f(163, -129);
+ glEnd;
+ gldisable(gl_texture_2d);
+ gldisable(GL_BLEND);
+ glPopMatrix;
+ end;
+
+// Commandio (von unten reinklappen, nach rechts oben rausklappen)
+ STime:=Timings[12]-10;
+ Delay:=Timings[13]-Timings[12];
+ if CTime > STime then
+ begin
+ k:=0;
+ ESC_Alpha:=20;
+
+ try
+ for j:=0 to 40 do
+ begin
+ if ( j < length( Data ) ) AND
+ ( k < length( Data ) ) then
+ begin
+ if Data[j] >= Data[k] then
+ k:=j;
+ end;
+ end;
+ except
+ end;
+
+
+ if Data[k]>0.25 then ESC_Alpha:=5 else inc(ESC_Alpha);
+ if ESC_Alpha >20 then ESC_Alpha:=20;
+ if ((CTime-STime)<20) then ESC_Alpha:=20;
+ if CTime <=STime+10 then j:=CTime-STime else j:=10;
+ if (CTime >=STime+Delay-10) then if (CTime <=STime+Delay) then j:=(STime+Delay)-CTime else j:=0;
+ glColor4f(1, 1, 1, ESC_Alpha/20*j/10);
+
+ if (CTime >= STime+10) and (CTime<=STime+12) then begin
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5);
+ end;
+
+ glPushMatrix;
+ gltranslatef(223,329,0);
+ if CTime <= STime+10 then
+ f:=258.0-25.8*(CTime-STime)
+ else
+ f:=0;
+ g:=0;
+ if CTime >=STime+Delay-10 then if CTime <=STime+Delay then begin
+ j:=CTime-(STime+Delay-10);
+ g:=32.6*j;
+ end;
+ glBindTexture(GL_TEXTURE_2D, credits_commandio.TexNum);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ glEnable(GL_TEXTURE_2D);
+ glbegin(gl_quads);
+ glTexCoord2f(0,0);glVertex2f(-163+g-f*1.5, -129+f*1.5-g/2);
+ glTexCoord2f(0,1);glVertex2f(-163+g*1.5, 129-(g*1.5*258/326));
+ glTexCoord2f(1,1); glVertex2f(163+g, 129+g/4);
+ glTexCoord2f(1,0);glVertex2f(163+f*1.5+g/4, -129+f*1.5-g/4);
+ glEnd;
+ gldisable(gl_texture_2d);
+ gldisable(GL_BLEND);
+ glPopMatrix;
+ end;
+
+// lazy joker (just scrolls from left to right, no twinkling stars, no on-beat flashing)
+ STime:=Timings[13]-35;
+ Delay:=Timings[14]-Timings[13]+5;
+ if CTime > STime then
+ begin
+ k:=0;
+
+ try
+ for j:=0 to 40 do
+ begin
+ if ( j < length( Data ) ) AND
+ ( k < length( Data ) ) then
+ begin
+ if Data[j] >= Data[k] then
+ k:=j;
+ end;
+ end;
+ except
+ end;
+
+
+ if Data[k]>0.25 then ESC_Alpha:=5 else inc(ESC_Alpha);
+ if ESC_Alpha >20 then ESC_Alpha:=20;
+ if ((CTime-STime)>10) and ((CTime-STime)<20) then ESC_Alpha:=20;
+ ESC_Alpha:=10;
+ f:=CTime-STime;
+ if CTime <=STime+40 then j:=CTime-STime else j:=40;
+ if (CTime >=STime+Delay-40) then if (CTime <=STime+Delay) then j:=(STime+Delay)-CTime else j:=0;
+ glColor4f(1, 1, 1, ESC_Alpha/20*j*j/1600);
+
+ glPushMatrix;
+ gltranslatef(180+(f-70),329,0);
+ glBindTexture(GL_TEXTURE_2D, credits_lazyjoker.TexNum);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ glEnable(GL_TEXTURE_2D);
+ glbegin(gl_quads);
+ glTexCoord2f(0,0);glVertex2f(-163, -129);
+ glTexCoord2f(0,1);glVertex2f(-163, 129);
+ glTexCoord2f(1,1); glVertex2f(163, 129);
+ glTexCoord2f(1,0);glVertex2f(163, -129);
+ glEnd;
+ gldisable(gl_texture_2d);
+ gldisable(GL_BLEND);
+ glPopMatrix;
+ end;
+
+// Mog (von links reinklappen, nach rechts unten rausklappen)
+ STime:=Timings[14]-10;
+ Delay:=Timings[15]-Timings[14]+5;
+ if CTime > STime then
+ begin
+ k:=0;
+ ESC_Alpha:=20;
+
+
+ try
+ for j:=0 to 40 do
+ begin
+ if ( j < length( Data ) ) AND
+ ( k < length( Data ) ) then
+ begin
+ if Data[j] >= Data[k] then
+ k:=j;
+ end;
+ end;
+ except
+ end;
+
+
+ if Data[k]>0.25 then ESC_Alpha:=5 else inc(ESC_Alpha);
+ if ESC_Alpha >20 then ESC_Alpha:=20;
+ if ((CTime-STime)<20) then ESC_Alpha:=20;
+ if CTime <=STime+10 then j:=CTime-STime else j:=10;
+ if (CTime >=STime+Delay-10) then if (CTime <=STime+Delay) then j:=(STime+Delay)-CTime else j:=0;
+ glColor4f(1, 1, 1, ESC_Alpha/20*j/10);
+
+ if (CTime >= STime+10) and (CTime<=STime+12) then begin
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5);
+ end;
+
+ glPushMatrix;
+ gltranslatef(223,329,0);
+ if CTime <= STime+10 then
+ f:=326.0-32.6*(CTime-STime)
+ else
+ f:=0;
+
+ g:=0;
+ if CTime >=STime+Delay-10 then if CTime <=STime+Delay then begin
+ j:=CTime-(STime+Delay-10);
+ g:=32.6*j;
+ end;
+ glBindTexture(GL_TEXTURE_2D, credits_mog.TexNum);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ glEnable(GL_TEXTURE_2D);
+ glbegin(gl_quads);
+ glTexCoord2f(0,0);glVertex2f(-163+g*1.5, -129+g*1.5);
+ glTexCoord2f(0,1);glVertex2f(-163+g*1.2, 129+g);
+ glTexCoord2f(1,1); glVertex2f(163-f+g/2, 129+f*1.5+g/4);
+ glTexCoord2f(1,0);glVertex2f(163-f+g*1.5, -129-f*1.5);
+ glEnd;
+ gldisable(gl_texture_2d);
+ gldisable(GL_BLEND);
+ glPopMatrix;
+ end;
+
+// Mota (von rechts oben reindrehen, nach links unten rausschieben und verkleinern und dabei drehen)
+ STime:=Timings[15]-10;
+ Delay:=Timings[16]-Timings[15]+5;
+ if CTime > STime then
+ begin
+ k:=0;
+ ESC_Alpha:=20;
+
+ try
+ for j:=0 to 40 do
+ begin
+ if ( j < length( Data ) ) AND
+ ( k < length( Data ) ) then
+ begin
+ if Data[j] >= Data[k] then
+ k:=j;
+ end;
+ end;
+ except
+ end;
+
+
+ if Data[k]>0.25 then ESC_Alpha:=5 else inc(ESC_Alpha);
+ if ESC_Alpha >20 then ESC_Alpha:=20;
+ if ((CTime-STime)<20) then ESC_Alpha:=20;
+ if CTime <=STime+10 then j:=CTime-STime else j:=10;
+ if (CTime >=STime+Delay-10) then if (CTime <=STime+Delay) then j:=(STime+Delay)-CTime else j:=0;
+ glColor4f(1, 1, 1, ESC_Alpha/20*j/10);
+
+ if (CTime >= STime+10) and (CTime<=STime+12) then begin
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5);
+ end;
+
+ glPushMatrix;
+ gltranslatef(223,329,0);
+ if CTime <= STime+10 then begin
+ gltranslatef(223,0,0);
+ glrotatef((10-(CTime-STime))*9,0,0,1);
+ gltranslatef(-223,0,0);
+ end;
+ if CTime >=STime+Delay-10 then if CTime <=STime+Delay then begin
+ j:=CTime-(STime+Delay-10);
+ f:=j*10.0;
+ gltranslatef(-f*2,-f,0);
+ glscalef(1-j/10,1-j/10,1-j/10);
+ glrotatef(-j*9.0,0,0,1);
+ end;
+ glBindTexture(GL_TEXTURE_2D, credits_mota.TexNum);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ glEnable(GL_TEXTURE_2D);
+ glbegin(gl_quads);
+ glTexCoord2f(0,0);glVertex2f(-163, -129);
+ glTexCoord2f(0,1);glVertex2f(-163, 129);
+ glTexCoord2f(1,1); glVertex2f(163, 129);
+ glTexCoord2f(1,0);glVertex2f(163, -129);
+ glEnd;
+ gldisable(gl_texture_2d);
+ gldisable(GL_BLEND);
+ glPopMatrix;
+ end;
+
+// Skillmaster (von rechts unten reinschieben, nach rechts oben rausdrehen)
+ STime:=Timings[16]-10;
+ Delay:=Timings[17]-Timings[16]+5;
+ if CTime > STime then
+ begin
+ k:=0;
+ ESC_Alpha:=20;
+
+ try
+ for j:=0 to 40 do
+ begin
+ if ( j < length( Data ) ) AND
+ ( k < length( Data ) ) then
+ begin
+ if Data[j] >= Data[k] then
+ k:=j;
+ end;
+ end;
+ except
+ end;
+
+
+ if Data[k]>0.25 then ESC_Alpha:=5 else inc(ESC_Alpha);
+ if ESC_Alpha >20 then ESC_Alpha:=20;
+ if ((CTime-STime)<20) then ESC_Alpha:=20;
+ if CTime <=STime+10 then j:=CTime-STime else j:=10;
+ if (CTime >=STime+Delay-10) then if (CTime <=STime+Delay) then j:=(STime+Delay)-CTime else j:=0;
+ glColor4f(1, 1, 1, ESC_Alpha/20*j/10);
+
+ if (CTime >= STime+10) and (CTime<=STime+12) then begin
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5);
+ end;
+
+ glPushMatrix;
+ gltranslatef(223,329,0);
+ if CTime <= STime+10 then begin
+ j:=STime+10-CTime;
+ f:=j*10.0;
+ gltranslatef(+f*2,+f/2,0);
+ end;
+ if CTime >=STime+Delay-10 then if CTime <=STime+Delay then begin
+ j:=CTime-(STime+Delay-10);
+ gltranslatef(0,-223,0);
+ glrotatef(integer(j)*-9,0,0,1);
+ gltranslatef(0,223,0);
+ glrotatef(j*9,0,0,1);
+ end;
+ glBindTexture(GL_TEXTURE_2D, credits_skillmaster.TexNum);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ glEnable(GL_TEXTURE_2D);
+ glbegin(gl_quads);
+ glTexCoord2f(0,0);glVertex2f(-163, -129);
+ glTexCoord2f(0,1);glVertex2f(-163, 129);
+ glTexCoord2f(1,1); glVertex2f(163, 129);
+ glTexCoord2f(1,0);glVertex2f(163, -129);
+ glEnd;
+ gldisable(gl_texture_2d);
+ gldisable(GL_BLEND);
+ glPopMatrix;
+ end;
+
+// WhiteShark (von links unten reinklappen, nach rechts oben rausklappen)
+ STime:=Timings[17]-10;
+ Delay:=Timings[18]-Timings[17];
+ if CTime > STime then
+ begin
+ k:=0;
+ ESC_Alpha:=20;
+
+ try
+ for j:=0 to 40 do
+ begin
+ if ( j < length( Data ) ) AND
+ ( k < length( Data ) ) then
+ begin
+ if Data[j] >= Data[k] then
+ k:=j;
+ end;
+ end;
+ except
+ end;
+
+
+ if Data[k]>0.25 then ESC_Alpha:=5 else inc(ESC_Alpha);
+ if ESC_Alpha >20 then ESC_Alpha:=20;
+ if ((CTime-STime)<20) then ESC_Alpha:=20;
+ if CTime <=STime+10 then j:=CTime-STime else j:=10;
+ if (CTime >=STime+Delay-10) then if (CTime <=STime+Delay) then j:=(STime+Delay)-CTime else j:=0;
+ glColor4f(1, 1, 1, ESC_Alpha/20*j/10);
+
+ if (CTime >= STime+10) and (CTime<=STime+12) then begin
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 0);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 1);
+ GoldenRec.Spawn(RandomRange(65,390), RandomRange(200,460), 1, 16, 0, -1, PerfectLineTwinkle, 5);
+ end;
+
+ glPushMatrix;
+ gltranslatef(223,329,0);
+ if CTime <= STime+10 then
+ f:=326.0-32.6*(CTime-STime)
+ else
+ f:=0;
+
+ if CTime >=STime+Delay-10 then if CTime <=STime+Delay then begin
+ j:=CTime-(STime+Delay-10);
+ g:=32.6*j;
+ end else
+ g:=0;
+ glBindTexture(GL_TEXTURE_2D, credits_whiteshark.TexNum);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ glEnable(GL_TEXTURE_2D);
+ glbegin(gl_quads);
+ glTexCoord2f(0,0);glVertex2f(-163-f+g, -129+f/4-g/2);
+ glTexCoord2f(0,1);glVertex2f(-163-f/4+g, 129+g/2+f/4);
+ glTexCoord2f(1,1); glVertex2f(163-f*1.2+g/4, 129+f/2-g/4);
+ glTexCoord2f(1,0);glVertex2f(163-f*1.5+g/4, -129+f*1.5+g/4);
+ glEnd;
+ gldisable(gl_texture_2d);
+ gldisable(GL_BLEND);
+ glPopMatrix;
+ end;
+
+
+ Log.LogStatus('',' JB-103');
+
+// ####################################################################
+// do some twinkle stuff (kinda on beat)
+ if (CTime > Timings[8] ) and
+ (CTime < Timings[19] ) then
+ begin
+ k := 0;
+
+ try
+ for j:=0 to 40 do
+ begin
+ if ( j < length( Data ) ) AND
+ ( k < length( Data ) ) then
+ begin
+ if Data[j] >= Data[k] then
+ k:=j;
+ end;
+ end;
+ except
+ end;
+
+ if Data[k]>0.2 then
+ begin
+ l := RandomRange(6,16);
+ j := RandomRange(0,27);
+
+ GoldenRec.Spawn(myLogoCoords[j,0], myLogoCoords[j,1], 16-l, l, 0, -1, PerfectNote, 0);
+ end;
+ end;
+
+//#################################################
+// draw the rest of the main screen (girl and logo
+ glEnable(GL_TEXTURE_2D);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ glColor4f(1, 1, 1, 1);
+ glBindTexture(GL_TEXTURE_2D, credits_bg_ovl.TexNum);
+ glbegin(gl_quads);
+ glTexCoord2f(0,0);glVertex2f(800-393, 0);
+ glTexCoord2f(0,600/1024);glVertex2f(800-393, 600);
+ glTexCoord2f(393/512,600/1024); glVertex2f(800, 600);
+ glTexCoord2f(393/512,0);glVertex2f(800, 0);
+ glEnd;
+{ glBindTexture(GL_TEXTURE_2D, credits_bg_logo.TexNum);
+ glbegin(gl_quads);
+ glTexCoord2f(0,0);glVertex2f(0, 0);
+ glTexCoord2f(0,112/128);glVertex2f(0, 112);
+ glTexCoord2f(497/512,112/128); glVertex2f(497, 112);
+ glTexCoord2f(497/512,0);glVertex2f(497, 0);
+ glEnd;
+}
+ gldisable(gl_texture_2d);
+ glDisable(GL_BLEND);
+
+ // fade out at end of main part
+ if Ctime > Timings[19] then
+ begin
+ glColor4f(0,0,0,(Ctime-Timings[19])/(Timings[20]-Timings[19]));
+ glEnable(GL_BLEND);
+ glBegin(GL_QUADS);
+ glVertex2f(0,0);
+ glVertex2f(0,600);
+ glVertex2f(800,600);
+ glVertex2f(800,0);
+ glEnd;
+ glDisable(GL_BLEND);
+ end;
+ end
+ else
+ if (CRDTS_Stage=Outro) then
+ begin
+ if CTime=Timings[20] then begin
+ CTime_hold:=0;
+ AudioPlayback.Stop;
+ AudioPlayback.Open(soundpath + 'credits-outro-tune.mp3');
+ AudioPlayback.Play;
+ AudioPlayback.SetVolume(20);
+ AudioPlayback.SetLoop(True);
+ end;
+ if CTime_hold > 231 then begin
+ AudioPlayback.Play;
+ Ctime_hold:=0;
+ end;
+ glClearColor(0,0,0,0);
+ glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
+
+ // do something useful
+ // outro background
+ glEnable(GL_TEXTURE_2D);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+
+ glColor4f(1, 1, 1, 1);
+ glBindTexture(GL_TEXTURE_2D, outro_bg.TexNum);
+ glbegin(gl_quads);
+ glTexCoord2f(0,0);glVertex2f(0, 0);
+ glTexCoord2f(0,600/1024);glVertex2f(0, 600);
+ glTexCoord2f(800/1024,600/1024); glVertex2f(800, 600);
+ glTexCoord2f(800/1024,0);glVertex2f(800, 0);
+ glEnd;
+
+ //outro overlays
+ glColor4f(1, 1, 1, (1+sin(CTime/15))/3+1/3);
+ glBindTexture(GL_TEXTURE_2D, outro_esc.TexNum);
+ glbegin(gl_quads);
+ glTexCoord2f(0,0);glVertex2f(0, 0);
+ glTexCoord2f(0,223/256);glVertex2f(0, 223);
+ glTexCoord2f(487/512,223/256); glVertex2f(487, 223);
+ glTexCoord2f(487/512,0);glVertex2f(487, 0);
+ glEnd;
+
+ ESC_Alpha:=20;
+ if (RandomRange(0,20) > 18) and (ESC_Alpha=20) then
+ ESC_Alpha:=0
+ else inc(ESC_Alpha);
+ if ESC_Alpha > 20 then ESC_Alpha:=20;
+ glColor4f(1, 1, 1, ESC_Alpha/20);
+ glBindTexture(GL_TEXTURE_2D, outro_exd.TexNum);
+ glbegin(gl_quads);
+ glTexCoord2f(0,0);glVertex2f(800-310, 600-247);
+ glTexCoord2f(0,247/256);glVertex2f(800-310, 600);
+ glTexCoord2f(310/512,247/256); glVertex2f(800, 600);
+ glTexCoord2f(310/512,0);glVertex2f(800, 600-247);
+ glEnd;
+ glDisable(GL_TEXTURE_2D);
+ glDisable(GL_BLEND);
+
+ // outro scrollers?
+ // ...
+ end;
+
+{ // draw credits runtime counter
+ SetFontStyle (2);
+ SetFontItalic(False);
+ SetFontSize(9);
+ SetFontPos (5, 5);
+ glColor4f(1, 1, 1, 1);
+// RuntimeStr:='CTime: '+inttostr(floor(CTime/30.320663991914489602156136106092))+'.'+inttostr(floor(CTime/3.0320663991914489602156136106092)-floor(CTime/30.320663991914489602156136106092)*10);
+ RuntimeStr:='CTime: '+inttostr(CTime);
+ glPrint (Addr(RuntimeStr[1]));
+}
+
+
+ glEnable(GL_TEXTURE_2D);
+ glEnable(GL_BLEND);
+ glColor4f(1, 1, 1, 1);
+ glBindTexture(GL_TEXTURE_2D, myTex);
+ glbegin(gl_quads);
+ glTexCoord2f(0,0);glVertex2f(100, 100);
+ glTexCoord2f(0,1);glVertex2f(100, 200);
+ glTexCoord2f(1,1); glVertex2f(200, 200);
+ glTexCoord2f(1,0);glVertex2f(200, 100);
+ glEnd;
+ glDisable(GL_TEXTURE_2D);
+ glDisable(GL_BLEND);
+
+
+ // make the stars shine
+ GoldenRec.Draw;
+end;
+
+end.
diff --git a/Game/Code/Screens/UScreenEdit.pas b/Game/Code/Screens/UScreenEdit.pas index 49adb994..00feddbf 100644 --- a/Game/Code/Screens/UScreenEdit.pas +++ b/Game/Code/Screens/UScreenEdit.pas @@ -38,7 +38,7 @@ begin SDLK_ESCAPE,
SDLK_BACKSPACE :
begin
- AudioPlayback.PlayBack;
+ AudioPlayback.PlaySound(SoundLib.Back);
FadeTo(@ScreenMain);
// Result := false;
end;
@@ -46,7 +46,7 @@ begin begin
if Interaction = 0 then
begin
- AudioPlayback.PlayStart;
+ AudioPlayback.PlaySound(SoundLib.Start);
FadeTo(@ScreenEditConvert);
end;
// if Interaction = 1 then begin
@@ -56,7 +56,7 @@ begin if Interaction = 1 then
begin
- AudioPlayback.PlayBack;
+ AudioPlayback.PlaySound(SoundLib.Back);
FadeTo(@ScreenMain);
end;
end;
diff --git a/Game/Code/Screens/UScreenEditConvert.pas b/Game/Code/Screens/UScreenEditConvert.pas index a523afd2..304c2259 100644 --- a/Game/Code/Screens/UScreenEditConvert.pas +++ b/Game/Code/Screens/UScreenEditConvert.pas @@ -121,7 +121,7 @@ begin {$IFDEF UseMIDIPort} MidiFile.StopPlaying; {$ENDIF} - AudioPlayback.PlayBack; + AudioPlayback.PlaySound(SoundLib.Back); FadeTo(@ScreenEdit); end; @@ -129,7 +129,7 @@ begin begin if Interaction = 0 then begin - AudioPlayback.PlayStart; + AudioPlayback.PlaySound(SoundLib.Start); ScreenOpen.BackScreen := @ScreenEditConvert; FadeTo(@ScreenOpen); end; diff --git a/Game/Code/Screens/UScreenEditSub.pas b/Game/Code/Screens/UScreenEditSub.pas index 57d6777e..4d971c63 100644 --- a/Game/Code/Screens/UScreenEditSub.pas +++ b/Game/Code/Screens/UScreenEditSub.pas @@ -1277,7 +1277,7 @@ begin for Pet := 0 to Czesci[0].Czesc[Czesci[0].Akt].HighNut do if (Czesci[0].Czesc[Czesci[0].Akt].Nuta[Pet].Start = AktBeat) then begin - AudioPlayback.PlayClick; + AudioPlayback.PlaySound(SoundLib.Click); LastClick := AktBeat; end; end; diff --git a/Game/Code/Screens/UScreenLevel.pas b/Game/Code/Screens/UScreenLevel.pas index e5deb6ba..16e24027 100644 --- a/Game/Code/Screens/UScreenLevel.pas +++ b/Game/Code/Screens/UScreenLevel.pas @@ -38,7 +38,7 @@ begin SDLK_ESCAPE,
SDLK_BACKSPACE :
begin
- AudioPlayback.PlayBack;
+ AudioPlayback.PlaySound(SoundLib.Back);
FadeTo(@ScreenName);
end;
@@ -46,7 +46,7 @@ begin begin
Ini.Difficulty := Interaction;
Ini.SaveLevel;
- AudioPlayback.PlayStart;
+ AudioPlayback.PlaySound(SoundLib.Start);
//Set Standard Mode
ScreenSong.Mode := smNormal;
FadeTo(@ScreenSong);
diff --git a/Game/Code/Screens/UScreenMain.pas b/Game/Code/Screens/UScreenMain.pas index a4dc5f0d..5824d9fe 100644 --- a/Game/Code/Screens/UScreenMain.pas +++ b/Game/Code/Screens/UScreenMain.pas @@ -94,7 +94,7 @@ begin //Credits_Y := 600; //Credits_Alpha := 0; //Credits_Visible := True; - AudioPlayback.PlayStart; + AudioPlayback.PlaySound(SoundLib.Start); FadeTo(@ScreenCredits); end; end; @@ -102,20 +102,20 @@ begin begin if (Ini.Players >= 1) AND (Length(DLLMan.Plugins)>=1) then begin - AudioPlayback.PlayStart; + AudioPlayback.PlaySound(SoundLib.Start); FadeTo(@ScreenPartyOptions); end; end; SDLK_S: begin - AudioPlayback.PlayStart; + AudioPlayback.PlaySound(SoundLib.Start); FadeTo(@ScreenStatMain); end; SDLK_E: begin - AudioPlayback.PlayStart; + AudioPlayback.PlaySound(SoundLib.Start); FadeTo(@ScreenEdit); end; @@ -126,7 +126,7 @@ begin begin if (Songs.SongList.Count >= 1) then begin - AudioPlayback.PlayStart; + AudioPlayback.PlaySound(SoundLib.Start); if (Ini.Players >= 0) and (Ini.Players <= 3) then PlayersPlay := Ini.Players + 1; if (Ini.Players = 4) then PlayersPlay := 6; @@ -144,7 +144,7 @@ begin begin if (Length(DLLMan.Plugins)>=1) then begin - AudioPlayback.PlayStart; + AudioPlayback.PlaySound(SoundLib.Start); FadeTo(@ScreenPartyOptions); end else //show error message, No Plugins Loaded @@ -157,21 +157,21 @@ begin //Stats if Interaction = 2 then begin - AudioPlayback.PlayStart; + AudioPlayback.PlaySound(SoundLib.Start); FadeTo(@ScreenStatMain); end; //Editor if Interaction = 3 then begin - AudioPlayback.PlayStart; + AudioPlayback.PlaySound(SoundLib.Start); FadeTo(@ScreenEdit); end; //Options if Interaction = 4 then begin - AudioPlayback.PlayStart; + AudioPlayback.PlaySound(SoundLib.Start); FadeTo(@ScreenOptions); end; diff --git a/Game/Code/Screens/UScreenName.pas b/Game/Code/Screens/UScreenName.pas index 76e79a3b..f33d6409 100644 --- a/Game/Code/Screens/UScreenName.pas +++ b/Game/Code/Screens/UScreenName.pas @@ -158,7 +158,7 @@ begin SDLK_ESCAPE :
begin
Ini.SaveNames;
- AudioPlayback.PlayBack;
+ AudioPlayback.PlaySound(SoundLib.Back);
if GoTo_SingScreen then
FadeTo(@ScreenSong)
else
@@ -170,7 +170,7 @@ begin for I := 1 to 6 do
Ini.Name[I-1] := Button[I-1].Text[0].Text;
Ini.SaveNames;
- AudioPlayback.PlayStart;
+ AudioPlayback.PlaySound(SoundLib.Start);
if GoTo_SingScreen then
FadeTo(@ScreenSing)
diff --git a/Game/Code/Screens/UScreenOpen.pas b/Game/Code/Screens/UScreenOpen.pas index 30404d6e..5d78fb31 100644 --- a/Game/Code/Screens/UScreenOpen.pas +++ b/Game/Code/Screens/UScreenOpen.pas @@ -59,7 +59,7 @@ begin begin
//Empty Filename and go to last Screen
FileName := '';
- AudioPlayback.PlayBack;
+ AudioPlayback.PlaySound(SoundLib.Back);
FadeTo(BackScreen);
end;
@@ -68,14 +68,14 @@ begin if (Interaction = 2) then begin
//Update Filename and go to last Screen
FileName := Text[TextN].Text;
- AudioPlayback.PlayBack;
+ AudioPlayback.PlaySound(SoundLib.Back);
FadeTo(BackScreen);
end
else if (Interaction = 1) then
begin
//Empty Filename and go to last Screen
FileName := '';
- AudioPlayback.PlayBack;
+ AudioPlayback.PlaySound(SoundLib.Back);
FadeTo(BackScreen);
end;
end;
diff --git a/Game/Code/Screens/UScreenOptions.pas b/Game/Code/Screens/UScreenOptions.pas index bcd781cc..4e39fe21 100644 --- a/Game/Code/Screens/UScreenOptions.pas +++ b/Game/Code/Screens/UScreenOptions.pas @@ -38,57 +38,57 @@ begin SDLK_BACKSPACE :
begin
Ini.Save;
- AudioPlayback.PlayBack;
+ AudioPlayback.PlaySound(SoundLib.Back);
FadeTo(@ScreenMain);
end;
SDLK_RETURN:
begin
if SelInteraction = 0 then
begin
- AudioPlayback.PlayStart;
+ AudioPlayback.PlaySound(SoundLib.Start);
FadeTo(@ScreenOptionsGame);
end;
if SelInteraction = 1 then
begin
- AudioPlayback.PlayStart;
+ AudioPlayback.PlaySound(SoundLib.Start);
FadeTo(@ScreenOptionsGraphics);
end;
if SelInteraction = 2 then
begin
- AudioPlayback.PlayStart;
+ AudioPlayback.PlaySound(SoundLib.Start);
FadeTo(@ScreenOptionsSound);
end;
if SelInteraction = 3 then
begin
- AudioPlayback.PlayStart;
+ AudioPlayback.PlaySound(SoundLib.Start);
FadeTo(@ScreenOptionsLyrics);
end;
if SelInteraction = 4 then
begin
- AudioPlayback.PlayStart;
+ AudioPlayback.PlaySound(SoundLib.Start);
FadeTo(@ScreenOptionsThemes);
end;
if SelInteraction = 5 then
begin
- AudioPlayback.PlayStart;
+ AudioPlayback.PlaySound(SoundLib.Start);
FadeTo(@ScreenOptionsRecord);
end;
if SelInteraction = 6 then
begin
- AudioPlayback.PlayStart;
+ AudioPlayback.PlaySound(SoundLib.Start);
FadeTo(@ScreenOptionsAdvanced);
end;
if SelInteraction = 7 then
begin
Ini.Save;
- AudioPlayback.PlayBack;
+ AudioPlayback.PlaySound(SoundLib.Back);
FadeTo(@ScreenMain);
end;
end;
diff --git a/Game/Code/Screens/UScreenOptionsAdvanced.pas b/Game/Code/Screens/UScreenOptionsAdvanced.pas index 0d40b7ec..e2c30bf1 100644 --- a/Game/Code/Screens/UScreenOptionsAdvanced.pas +++ b/Game/Code/Screens/UScreenOptionsAdvanced.pas @@ -34,7 +34,7 @@ begin SDLK_BACKSPACE :
begin
Ini.Save;
- AudioPlayback.PlayBack;
+ AudioPlayback.PlaySound(SoundLib.Back);
FadeTo(@ScreenOptions);
end;
SDLK_RETURN:
@@ -43,7 +43,7 @@ begin //if SelInteraction = 7 then begin
if SelInteraction = 6 then begin
Ini.Save;
- AudioPlayback.PlayBack;
+ AudioPlayback.PlaySound(SoundLib.Back);
FadeTo(@ScreenOptions);
end;
end;
@@ -56,7 +56,7 @@ begin //SelectLoadAnimation Hidden because it is useless atm
//if (SelInteraction >= 0) and (SelInteraction <= 6) then begin
if (SelInteraction >= 0) and (SelInteraction <= 5) then begin
- AudioPlayback.PlayOption;
+ AudioPlayback.PlaySound(SoundLib.Option);
InteractInc;
end;
end;
@@ -65,7 +65,7 @@ begin //SelectLoadAnimation Hidden because it is useless atm
//if (SelInteraction >= 0) and (SelInteraction <= 6) then begin
if (SelInteraction >= 0) and (SelInteraction <= 5) then begin
- AudioPlayback.PlayOption;
+ AudioPlayback.PlaySound(SoundLib.Option);
InteractDec;
end;
end;
diff --git a/Game/Code/Screens/UScreenOptionsGame.pas b/Game/Code/Screens/UScreenOptionsGame.pas index 6cd0a20c..15b538a5 100644 --- a/Game/Code/Screens/UScreenOptionsGame.pas +++ b/Game/Code/Screens/UScreenOptionsGame.pas @@ -35,14 +35,14 @@ begin SDLK_ESCAPE,
SDLK_BACKSPACE :
begin
- AudioPlayback.PlayBack;
+ AudioPlayback.PlaySound(SoundLib.Back);
RefreshSongs;
FadeTo(@ScreenOptions);
end;
SDLK_RETURN:
begin
if SelInteraction = 6 then begin
- AudioPlayback.PlayBack;
+ AudioPlayback.PlaySound(SoundLib.Back);
RefreshSongs;
FadeTo(@ScreenOptions);
end;
@@ -55,7 +55,7 @@ begin begin
if (SelInteraction >= 0) and (SelInteraction <= 5) then
begin
- AudioPlayback.PlayOption;
+ AudioPlayback.PlaySound(SoundLib.Option);
InteractInc;
end;
end;
@@ -63,7 +63,7 @@ begin begin
if (SelInteraction >= 0) and (SelInteraction <= 5) then
begin
- AudioPlayback.PlayOption;
+ AudioPlayback.PlaySound(SoundLib.Option);
InteractDec;
end;
end;
diff --git a/Game/Code/Screens/UScreenOptionsGraphics.pas b/Game/Code/Screens/UScreenOptionsGraphics.pas index 947d506b..4ceeeb32 100644 --- a/Game/Code/Screens/UScreenOptionsGraphics.pas +++ b/Game/Code/Screens/UScreenOptionsGraphics.pas @@ -34,7 +34,7 @@ begin SDLK_BACKSPACE :
begin
Ini.Save;
- AudioPlayback.PlayBack;
+ AudioPlayback.PlaySound(SoundLib.Back);
FadeTo(@ScreenOptions);
end;
SDLK_RETURN:
@@ -44,7 +44,7 @@ begin end;}
if SelInteraction = 5 then begin
Ini.Save;
- AudioPlayback.PlayBack;
+ AudioPlayback.PlaySound(SoundLib.Back);
FadeTo(@ScreenOptions);
end;
end;
@@ -55,14 +55,14 @@ begin SDLK_RIGHT:
begin
if (SelInteraction >= 0) and (SelInteraction <= 4) then begin
- AudioPlayback.PlayOption;
+ AudioPlayback.PlaySound(SoundLib.Option);
InteractInc;
end;
end;
SDLK_LEFT:
begin
if (SelInteraction >= 0) and (SelInteraction <= 4) then begin
- AudioPlayback.PlayOption;
+ AudioPlayback.PlaySound(SoundLib.Option);
InteractDec;
end;
end;
diff --git a/Game/Code/Screens/UScreenOptionsLyrics.pas b/Game/Code/Screens/UScreenOptionsLyrics.pas index 8d70eec9..7275efed 100644 --- a/Game/Code/Screens/UScreenOptionsLyrics.pas +++ b/Game/Code/Screens/UScreenOptionsLyrics.pas @@ -34,14 +34,14 @@ begin SDLK_BACKSPACE :
begin
Ini.Save;
- AudioPlayback.PlayBack;
+ AudioPlayback.PlaySound(SoundLib.Back);
FadeTo(@ScreenOptions);
end;
SDLK_RETURN:
begin
if SelInteraction = 3 then begin
Ini.Save;
- AudioPlayback.PlayBack;
+ AudioPlayback.PlaySound(SoundLib.Back);
FadeTo(@ScreenOptions);
end;
end;
@@ -52,14 +52,14 @@ begin SDLK_RIGHT:
begin
if (SelInteraction >= 0) and (SelInteraction <= 2) then begin
- AudioPlayback.PlayOption;
+ AudioPlayback.PlaySound(SoundLib.Option);
InteractInc;
end;
end;
SDLK_LEFT:
begin
if (SelInteraction >= 0) and (SelInteraction <= 2) then begin
- AudioPlayback.PlayOption;
+ AudioPlayback.PlaySound(SoundLib.Option);
InteractDec;
end;
end;
diff --git a/Game/Code/Screens/UScreenOptionsRecord.pas b/Game/Code/Screens/UScreenOptionsRecord.pas index 65d016c7..130c3551 100644 --- a/Game/Code/Screens/UScreenOptionsRecord.pas +++ b/Game/Code/Screens/UScreenOptionsRecord.pas @@ -1,212 +1,232 @@ -unit UScreenOptionsRecord; - -interface - -{$I switches.inc} - -uses - UMenu, SDL, UDisplay, UMusic, UFiles, UIni, UThemes; - -type - TScreenOptionsRecord = class(TMenu) - private - SelectSlideInput: integer; - SelectSlideChannelL: integer; - SelectSlideChannelR: integer; - public - constructor Create; override; - function Draw: boolean; override; - function ParseInput(PressedKey: Cardinal; ScanCode: byte; PressedDown: Boolean): Boolean; override; - procedure onShow; override; - procedure onHide; override; - procedure UpdateCard; - end; - -implementation - -uses SysUtils, - UGraphic, - URecord, - UDraw, - UMain, - ULog; - -function TScreenOptionsRecord.ParseInput(PressedKey: Cardinal; ScanCode: byte; PressedDown: Boolean): Boolean; -begin - Result := true; - If (PressedDown) Then - begin // Key Down - case PressedKey of - SDLK_Q: - begin - Result := false; - end; - SDLK_ESCAPE, - SDLK_BACKSPACE: - begin - Ini.Save; - AudioPlayback.PlayBack; - FadeTo(@ScreenOptions); - end; - SDLK_RETURN: - begin - if SelInteraction = 5 then begin - Ini.Save; - AudioPlayback.PlayBack; - FadeTo(@ScreenOptions); - end; - end; - SDLK_DOWN: - InteractNext; - SDLK_UP : - InteractPrev; - SDLK_RIGHT: - begin - if (SelInteraction >= 0) and (SelInteraction <= 4) then begin - AudioPlayback.PlayOption; - InteractInc; - end; -// if SelInteraction = 0 then UpdateCard; - UpdateCard; - end; - SDLK_LEFT: - begin - if (SelInteraction >= 0) and (SelInteraction <= 4) then begin - AudioPlayback.PlayOption; - InteractDec; - end; - UpdateCard; -// if SelInteraction = 0 then UpdateCard; - end; - end; - end; -end; - -constructor TScreenOptionsRecord.Create; -var - I: integer; - SC: integer; - SCI: integer; -begin - inherited Create; - - LoadFromTheme(Theme.OptionsRecord); - - SetLength(ICard, Length(AudioInputProcessor.SoundCard)); - for SC := 0 to High(AudioInputProcessor.SoundCard) do - ICard[SC] := AudioInputProcessor.SoundCard[SC].Description; - - if (Length(AudioInputProcessor.SoundCard) > 0) then - begin - SetLength(IInput, Length(AudioInputProcessor.SoundCard[Ini.Card].Input)); - for SCI := 0 to High(AudioInputProcessor.SoundCard[Ini.Card].Input) do - IInput[SCI] := AudioInputProcessor.SoundCard[Ini.Card].Input[SCI].Name; - - - AddSelectSlide(Theme.OptionsRecord.SelectSlideCard, Ini.Card, ICard); - - SelectSlideInput := AddSelectSlide(Theme.OptionsRecord.SelectSlideInput, Ini.CardList[0].Input, IInput); - SelectSlideChannelL := AddSelectSlide(Theme.OptionsRecord.SelectSlideChannelL, Ini.CardList[0].ChannelL, IChannel); - SelectSlideChannelR := AddSelectSlide(Theme.OptionsRecord.SelectSlideChannelR, Ini.CardList[0].ChannelR, IChannel); - - AddSelect(Theme.OptionsSound.SelectMicBoost, Ini.MicBoost, IMicBoost); - end; - - AddButton(Theme.OptionsRecord.ButtonExit); - if (Length(Button[0].Text)=0) then - AddButtonText(14, 20, Theme.Options.Description[7]); - - Interaction := 0; -end; - -procedure TScreenOptionsRecord.onShow; -begin - Interaction := 0; - writeln( 'AudioInput.CaptureStart') ; - - PlayersPlay := 2; // TODO : This needs fixing - AudioInput.CaptureStart; - -end; - -procedure TScreenOptionsRecord.onHide; -begin - AudioInput.CaptureStop; -end; - -procedure TScreenOptionsRecord.UpdateCard; -var - SC: integer; - SCI: integer; -begin - writeln( 'Update Card') ; - AudioInput.CaptureStop; - try - SC := Ini.Card; - // if SC = 1 then beep; - - SetLength(IInput, Length(AudioInputProcessor.SoundCard[SC].Input)); - for SCI := 0 to High(AudioInputProcessor.SoundCard[SC].Input) do begin - IInput[SCI] := AudioInputProcessor.SoundCard[SC].Input[SCI].Name; - // Log.LogError(IInput[SCI]); - end; - - - UpdateSelectSlideOptions(Theme.OptionsRecord.SelectSlideInput, SelectSlideInput, IInput, Ini.CardList[SC].Input); - UpdateSelectSlideOptions(Theme.OptionsRecord.SelectSlideChannelL, SelectSlideChannelL, IChannel, Ini.CardList[SC].ChannelL); - UpdateSelectSlideOptions(Theme.OptionsRecord.SelectSlideChannelR, SelectSlideChannelR, IChannel, Ini.CardList[SC].ChannelR); - - finally - AudioInput.CaptureStart; - end; -end; - -function TScreenOptionsRecord.Draw: boolean; -begin - DrawBG; - DrawFG; - - // TODO : this needs to be positioned correctly - if PlayersPlay = 1 then - SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 0); - - if PlayersPlay = 2 then begin - SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 0); - SingDrawOscilloscope(425 + 10*ScreenX, 55, 180, 40, 1); - end; - - if PlayersPlay = 4 then begin - if ScreenAct = 1 then begin - SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 0); - SingDrawOscilloscope(425 + 10*ScreenX, 55, 180, 40, 1); - end; - if ScreenAct = 2 then begin - SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 2); - SingDrawOscilloscope(425 + 10*ScreenX, 55, 180, 40, 3); - end; - end; - - if PlayersPlay = 3 then begin - SingDrawOscilloscope(75 + 10*ScreenX, 95, 100, 20, 0); - SingDrawOscilloscope(370 + 10*ScreenX, 95, 100, 20, 1); - SingDrawOscilloscope(670 + 10*ScreenX, 95, 100, 20, 2); - end; - - if PlayersPlay = 6 then begin - if ScreenAct = 1 then begin - SingDrawOscilloscope( 75 + 10*ScreenX, 95, 100, 20, 0); - SingDrawOscilloscope(370 + 10*ScreenX, 95, 100, 20, 1); - SingDrawOscilloscope(670 + 10*ScreenX, 95, 100, 20, 2); - end; - if ScreenAct = 2 then begin - SingDrawOscilloscope( 75 + 10*ScreenX, 95, 100, 20, 3); - SingDrawOscilloscope(370 + 10*ScreenX, 95, 100, 20, 4); - SingDrawOscilloscope(670 + 10*ScreenX, 95, 100, 20, 5); - end; - end; - - Result := True; -end; - - -end. +unit UScreenOptionsRecord;
+
+interface
+
+{$I switches.inc}
+
+uses
+ UMenu, SDL, UDisplay, UMusic, UFiles, UIni, UThemes;
+
+type
+ TScreenOptionsRecord = class(TMenu)
+ private
+ Card: integer; // current input device
+
+ SelectSlideInput: integer;
+ SelectSlideChannelL: integer;
+ SelectSlideChannelR: integer;
+ public
+ constructor Create; override;
+ function Draw: boolean; override;
+ function ParseInput(PressedKey: Cardinal; ScanCode: byte; PressedDown: Boolean): Boolean; override;
+ procedure onShow; override;
+ procedure onHide; override;
+ procedure UpdateCard;
+ end;
+
+implementation
+
+uses SysUtils,
+ UGraphic,
+ URecord,
+ UDraw,
+ UMain,
+ ULog;
+
+function TScreenOptionsRecord.ParseInput(PressedKey: Cardinal; ScanCode: byte; PressedDown: Boolean): Boolean;
+begin
+ Result := true;
+ If (PressedDown) Then
+ begin // Key Down
+ case PressedKey of
+ SDLK_Q:
+ begin
+ Result := false;
+ end;
+ SDLK_ESCAPE,
+ SDLK_BACKSPACE:
+ begin
+ Ini.Save;
+ AudioPlayback.PlaySound(SoundLib.Back);
+ FadeTo(@ScreenOptions);
+ end;
+ SDLK_RETURN:
+ begin
+ if SelInteraction = 5 then begin
+ Ini.Save;
+ AudioPlayback.PlaySound(SoundLib.Back);
+ FadeTo(@ScreenOptions);
+ end;
+ end;
+ SDLK_DOWN:
+ InteractNext;
+ SDLK_UP :
+ InteractPrev;
+ SDLK_RIGHT:
+ begin
+ if (SelInteraction >= 0) and (SelInteraction <= 4) then begin
+ AudioPlayback.PlaySound(SoundLib.Option);
+ InteractInc;
+ end;
+// if SelInteraction = 0 then UpdateCard;
+ UpdateCard;
+ end;
+ SDLK_LEFT:
+ begin
+ if (SelInteraction >= 0) and (SelInteraction <= 4) then begin
+ AudioPlayback.PlaySound(SoundLib.Option);
+ InteractDec;
+ end;
+ UpdateCard;
+// if SelInteraction = 0 then UpdateCard;
+ end;
+ end;
+ end;
+end;
+
+constructor TScreenOptionsRecord.Create;
+var
+ SC: integer;
+ SCI: integer;
+ InputDevice: TAudioInputDevice;
+ InputDeviceCfg: PInputDeviceConfig;
+begin
+ inherited Create;
+
+ Card := 0;
+
+ LoadFromTheme(Theme.OptionsRecord);
+
+ SetLength(ICard, Length(AudioInputProcessor.Device));
+ for SC := 0 to High(AudioInputProcessor.Device) do
+ ICard[SC] := AudioInputProcessor.Device[SC].Description;
+
+ if (Card > High(AudioInputProcessor.Device)) then
+ Card := 0;
+
+ if (Length(AudioInputProcessor.Device) > 0) then
+ begin
+ InputDevice := AudioInputProcessor.Device[Card];
+ InputDeviceCfg := @Ini.InputDeviceConfig[InputDevice.CfgIndex];
+
+ SetLength(IInput, Length(InputDevice.Source));
+ for SCI := 0 to High(InputDevice.Source) do
+ IInput[SCI] := InputDevice.Source[SCI].Name;
+
+ AddSelectSlide(Theme.OptionsRecord.SelectSlideCard, Card, ICard);
+
+ SelectSlideInput := AddSelectSlide(Theme.OptionsRecord.SelectSlideInput,
+ InputDeviceCfg^.Input, IInput);
+ SelectSlideChannelL := AddSelectSlide(Theme.OptionsRecord.SelectSlideChannelL,
+ InputDeviceCfg^.ChannelToPlayerMap[0], IChannel);
+ SelectSlideChannelR := AddSelectSlide(Theme.OptionsRecord.SelectSlideChannelR,
+ InputDeviceCfg^.ChannelToPlayerMap[1], IChannel);
+
+ AddSelect(Theme.OptionsSound.SelectMicBoost, Ini.MicBoost, IMicBoost);
+ end;
+
+ AddButton(Theme.OptionsRecord.ButtonExit);
+ if (Length(Button[0].Text)=0) then
+ AddButtonText(14, 20, Theme.Options.Description[7]);
+
+ Interaction := 0;
+end;
+
+procedure TScreenOptionsRecord.onShow;
+begin
+ Interaction := 0;
+ writeln( 'AudioInput.CaptureStart') ;
+
+ PlayersPlay := 2; // TODO : This needs fixing
+ AudioInput.CaptureStart;
+
+end;
+
+procedure TScreenOptionsRecord.onHide;
+begin
+ AudioInput.CaptureStop;
+end;
+
+procedure TScreenOptionsRecord.UpdateCard;
+var
+ SourceIndex: integer;
+ InputDevice: TAudioInputDevice;
+ InputDeviceCfg: PInputDeviceConfig;
+begin
+ Log.LogStatus('Update input-device', 'TScreenOptionsRecord.UpdateCard') ;
+
+ AudioInput.CaptureStop;
+
+ if (Card > High(AudioInputProcessor.Device)) then
+ Card := 0;
+
+ if (Length(AudioInputProcessor.Device) > 0) then
+ begin
+ InputDevice := AudioInputProcessor.Device[Card];
+ InputDeviceCfg := @Ini.InputDeviceConfig[InputDevice.CfgIndex];
+
+ SetLength(IInput, Length(InputDevice.Source));
+ for SourceIndex := 0 to High(InputDevice.Source) do begin
+ IInput[SourceIndex] := InputDevice.Source[SourceIndex].Name;
+ end;
+
+ UpdateSelectSlideOptions(Theme.OptionsRecord.SelectSlideInput, SelectSlideInput, IInput,
+ InputDeviceCfg^.Input);
+ UpdateSelectSlideOptions(Theme.OptionsRecord.SelectSlideChannelL, SelectSlideChannelL, IChannel,
+ InputDeviceCfg^.ChannelToPlayerMap[0]);
+ UpdateSelectSlideOptions(Theme.OptionsRecord.SelectSlideChannelR, SelectSlideChannelR, IChannel,
+ InputDeviceCfg^.ChannelToPlayerMap[1]);
+ end;
+
+ AudioInput.CaptureStart;
+end;
+
+function TScreenOptionsRecord.Draw: boolean;
+begin
+ DrawBG;
+ DrawFG;
+
+ // TODO : this needs to be positioned correctly
+ if PlayersPlay = 1 then
+ SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 0);
+
+ if PlayersPlay = 2 then begin
+ SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 0);
+ SingDrawOscilloscope(425 + 10*ScreenX, 55, 180, 40, 1);
+ end;
+
+ if PlayersPlay = 4 then begin
+ if ScreenAct = 1 then begin
+ SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 0);
+ SingDrawOscilloscope(425 + 10*ScreenX, 55, 180, 40, 1);
+ end;
+ if ScreenAct = 2 then begin
+ SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 2);
+ SingDrawOscilloscope(425 + 10*ScreenX, 55, 180, 40, 3);
+ end;
+ end;
+
+ if PlayersPlay = 3 then begin
+ SingDrawOscilloscope(75 + 10*ScreenX, 95, 100, 20, 0);
+ SingDrawOscilloscope(370 + 10*ScreenX, 95, 100, 20, 1);
+ SingDrawOscilloscope(670 + 10*ScreenX, 95, 100, 20, 2);
+ end;
+
+ if PlayersPlay = 6 then begin
+ if ScreenAct = 1 then begin
+ SingDrawOscilloscope( 75 + 10*ScreenX, 95, 100, 20, 0);
+ SingDrawOscilloscope(370 + 10*ScreenX, 95, 100, 20, 1);
+ SingDrawOscilloscope(670 + 10*ScreenX, 95, 100, 20, 2);
+ end;
+ if ScreenAct = 2 then begin
+ SingDrawOscilloscope( 75 + 10*ScreenX, 95, 100, 20, 3);
+ SingDrawOscilloscope(370 + 10*ScreenX, 95, 100, 20, 4);
+ SingDrawOscilloscope(670 + 10*ScreenX, 95, 100, 20, 5);
+ end;
+ end;
+
+ Result := True;
+end;
+
+
+end.
diff --git a/Game/Code/Screens/UScreenOptionsSound.pas b/Game/Code/Screens/UScreenOptionsSound.pas index 64a0413f..da5c6e90 100644 --- a/Game/Code/Screens/UScreenOptionsSound.pas +++ b/Game/Code/Screens/UScreenOptionsSound.pas @@ -34,14 +34,14 @@ begin SDLK_BACKSPACE :
begin
Ini.Save;
- AudioPlayback.PlayBack;
+ AudioPlayback.PlaySound(SoundLib.Back);
FadeTo(@ScreenOptions);
end;
SDLK_RETURN:
begin
if SelInteraction = 6 then begin
Ini.Save;
- AudioPlayback.PlayBack;
+ AudioPlayback.PlaySound(SoundLib.Back);
FadeTo(@ScreenOptions);
end;
end;
@@ -52,14 +52,14 @@ begin SDLK_RIGHT:
begin
if (SelInteraction >= 0) and (SelInteraction <= 6) then begin
- AudioPlayback.PlayOption;
+ AudioPlayback.PlaySound(SoundLib.Option);
InteractInc;
end;
end;
SDLK_LEFT:
begin
if (SelInteraction >= 0) and (SelInteraction <= 6) then begin
- AudioPlayback.PlayOption;
+ AudioPlayback.PlaySound(SoundLib.Option);
InteractDec;
end;
end;
diff --git a/Game/Code/Screens/UScreenOptionsThemes.pas b/Game/Code/Screens/UScreenOptionsThemes.pas index 114a5e45..239f98fe 100644 --- a/Game/Code/Screens/UScreenOptionsThemes.pas +++ b/Game/Code/Screens/UScreenOptionsThemes.pas @@ -53,7 +53,7 @@ begin UGraphic.UnLoadScreens(); UGraphic.LoadScreens(); - AudioPlayback.PlayBack; + AudioPlayback.PlaySound(SoundLib.Back); FadeTo(@ScreenOptions); end; SDLK_RETURN: @@ -67,7 +67,7 @@ begin UGraphic.UnLoadScreens(); UGraphic.LoadScreens(); - AudioPlayback.PlayBack; + AudioPlayback.PlaySound(SoundLib.Back); FadeTo(@ScreenOptions); end; end; @@ -79,7 +79,7 @@ begin begin if (SelInteraction >= 0) and (SelInteraction <= 2) then begin - AudioPlayback.PlayOption; + AudioPlayback.PlaySound(SoundLib.Option); InteractInc; end; end; @@ -87,7 +87,7 @@ begin begin if (SelInteraction >= 0) and (SelInteraction <= 2) then begin - AudioPlayback.PlayOption; + AudioPlayback.PlaySound(SoundLib.Option); InteractDec; end; end; diff --git a/Game/Code/Screens/UScreenPartyNewRound.pas b/Game/Code/Screens/UScreenPartyNewRound.pas index 2f07dcb0..198708cc 100644 --- a/Game/Code/Screens/UScreenPartyNewRound.pas +++ b/Game/Code/Screens/UScreenPartyNewRound.pas @@ -101,13 +101,13 @@ begin SDLK_ESCAPE, SDLK_BACKSPACE : begin - AudioPlayback.PlayBack; + AudioPlayback.PlaySound(SoundLib.Back); CheckFadeTo(@ScreenMain,'MSG_END_PARTY'); end; SDLK_RETURN: begin - AudioPlayback.PlayStart; + AudioPlayback.PlaySound(SoundLib.Start); if DLLMan.Selected.LoadSong then begin //Select PartyMode ScreenSong diff --git a/Game/Code/Screens/UScreenPartyOptions.pas b/Game/Code/Screens/UScreenPartyOptions.pas index c8cb2bb5..1b5cf976 100644 --- a/Game/Code/Screens/UScreenPartyOptions.pas +++ b/Game/Code/Screens/UScreenPartyOptions.pas @@ -66,7 +66,7 @@ begin SDLK_ESCAPE, SDLK_BACKSPACE : begin - AudioPlayback.PlayBack; + AudioPlayback.PlaySound(SoundLib.Back); FadeTo(@ScreenMain); end; @@ -125,7 +125,7 @@ begin // to-do : Party //PartySession.StartNewParty(Rounds + 2); - AudioPlayback.PlayStart; + AudioPlayback.PlaySound(SoundLib.Start); //Go to Player Screen FadeTo(@ScreenPartyPlayer); end; @@ -137,7 +137,7 @@ begin SDLK_UP: InteractPrev; SDLK_RIGHT: begin - AudioPlayback.PlayOption; + AudioPlayback.PlaySound(SoundLib.Option); InteractInc; //Change Playlist2 if Playlist is Changed @@ -152,7 +152,7 @@ begin end; SDLK_LEFT: begin - AudioPlayback.PlayOption; + AudioPlayback.PlaySound(SoundLib.Option); InteractDec; //Change Playlist2 if Playlist is Changed diff --git a/Game/Code/Screens/UScreenPartyPlayer.pas b/Game/Code/Screens/UScreenPartyPlayer.pas index 3bd33a5c..68f76952 100644 --- a/Game/Code/Screens/UScreenPartyPlayer.pas +++ b/Game/Code/Screens/UScreenPartyPlayer.pas @@ -186,7 +186,7 @@ begin SDLK_ESCAPE:
begin
Ini.SaveNames;
- AudioPlayback.PlayBack;
+ AudioPlayback.PlaySound(SoundLib.Back);
FadeTo(@ScreenPartyOptions);
end;
diff --git a/Game/Code/Screens/UScreenPartyScore.pas b/Game/Code/Screens/UScreenPartyScore.pas index 6215e65a..6b21323b 100644 --- a/Game/Code/Screens/UScreenPartyScore.pas +++ b/Game/Code/Screens/UScreenPartyScore.pas @@ -59,7 +59,7 @@ begin SDLK_ESCAPE,
SDLK_BACKSPACE :
begin
- AudioPlayback.PlayStart;
+ AudioPlayback.PlaySound(SoundLib.Start);
{if (PartySession.CurRound < High(PartySession.Rounds)) then
FadeTo(@ScreenPartyNewRound)
else // to-do : Party
@@ -71,7 +71,7 @@ begin SDLK_RETURN:
begin
- AudioPlayback.PlayStart;
+ AudioPlayback.PlaySound(SoundLib.Start);
// to-do : Party
{if (PartySession.CurRound < High(PartySession.Rounds)) then
FadeTo(@ScreenPartyNewRound)
diff --git a/Game/Code/Screens/UScreenPartyWin.pas b/Game/Code/Screens/UScreenPartyWin.pas index d8a3bd71..5960db06 100644 --- a/Game/Code/Screens/UScreenPartyWin.pas +++ b/Game/Code/Screens/UScreenPartyWin.pas @@ -52,13 +52,13 @@ begin SDLK_ESCAPE,
SDLK_BACKSPACE :
begin
- AudioPlayback.PlayStart;
+ AudioPlayback.PlaySound(SoundLib.Start);
FadeTo(@ScreenMain);
end;
SDLK_RETURN:
begin
- AudioPlayback.PlayStart;
+ AudioPlayback.PlaySound(SoundLib.Start);
FadeTo(@ScreenMain);
end;
end;
diff --git a/Game/Code/Screens/UScreenSing.pas b/Game/Code/Screens/UScreenSing.pas index 5216477d..6a5b4e90 100644 --- a/Game/Code/Screens/UScreenSing.pas +++ b/Game/Code/Screens/UScreenSing.pas @@ -153,7 +153,7 @@ begin //Sound[0].BufferLong Finish; - AudioPlayback.PlayBack; + AudioPlayback.PlaySound(SoundLib.Back); FadeTo(@ScreenScore); end; diff --git a/Game/Code/Screens/UScreenSingModi.pas b/Game/Code/Screens/UScreenSingModi.pas index 7d2eba07..ed827ec8 100644 --- a/Game/Code/Screens/UScreenSingModi.pas +++ b/Game/Code/Screens/UScreenSingModi.pas @@ -75,6 +75,16 @@ type //procedure Pause; //Pause Mod(Toggles Pause) end; +type + TCustomSoundEntry = record
+ Filename : String;
+ Stream : TAudioPlaybackStream;
+ end;
+
+var + //Custom Sounds + CustomSounds: array of TCustomSoundEntry; + //Procedured for Plugin function LoadTex (const Name, Typ: PChar): TsmallTexture; stdcall; //function Translate (const Name: PChar): PChar; stdcall; @@ -101,7 +111,7 @@ begin SDLK_BACKSPACE : begin Finish; - AudioPlayback.PlayBack; + AudioPlayback.PlaySound(SoundLib.Back); FadeTo(@ScreenPartyScore); end; @@ -656,14 +666,34 @@ begin end; function LoadSound (const Name: PChar): Cardinal; stdcall; //Procedure that loads a Custom Sound +var + S: TAudioPlaybackStream; + I: Integer; + F: String; begin - Result := AudioPlayback.LoadCustomSound(String(Name)); + //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 := AudioPlayback.OpenSound(SoundPath + String(Name)); + if (S <> nil) then + Result := High(CustomSounds) + else + Result := 0; end; procedure PlaySound (const Index: Cardinal); stdcall; //Plays a Custom Sound begin - AudioPlayback.PlayCustomSound(Index); + if (Index <= High(CustomSounds)) then + AudioPlayback.PlaySound(CustomSounds[Index].Stream); end; end. ->>>>>>> .r429 + diff --git a/Game/Code/Screens/UScreenSong.pas b/Game/Code/Screens/UScreenSong.pas index 4773cdac..3be0be84 100644 --- a/Game/Code/Screens/UScreenSong.pas +++ b/Game/Code/Screens/UScreenSong.pas @@ -29,6 +29,11 @@ uses type TScreenSong = class(TMenu) + private + EqualizerData: TFFTData; // moved here to avoid stack overflows + EqualizerBands: array of Byte; + EqualizerTime: Cardinal; + EqualizerTime2: Byte; public TextArtist: integer; TextTitle: integer; @@ -52,10 +57,6 @@ type is_jump: boolean; // Jump to Song Mod is_jump_title:boolean; //Jump to SOng MOd-YTrue if search for Title - EqualizerBands: array of Byte; - EqualizerTime: Cardinal; - EqualizerTime2: Byte; - //Party Mod Mode: TSingMode; @@ -270,7 +271,7 @@ begin begin SkipTo(CatSongs.VisibleIndex((I + Interaction) mod I2)); - AudioPlayback.PlayChange; + AudioPlayback.PlaySound(SoundLib.Change); ChangeMusic; SetScroll4; @@ -291,7 +292,7 @@ begin begin SkipTo(CatSongs.VisibleIndex((I + Interaction) mod I2)); - AudioPlayback.PlayChange; + AudioPlayback.PlaySound(SoundLib.Change); ChangeMusic; SetScroll4; @@ -369,7 +370,7 @@ begin else begin AudioPlayback.Stop; - AudioPlayback.PlayBack; + AudioPlayback.PlaySound(SoundLib.Back); FadeTo(@ScreenMain); end; @@ -379,7 +380,7 @@ begin //When in party Mode then Ask before Close else if (Mode = smPartyMode) then begin - AudioPlayback.PlayBack; + AudioPlayback.PlaySound(SoundLib.Back); CheckFadeTo(@ScreenMain,'MSG_END_PARTY'); end; end; @@ -504,7 +505,7 @@ begin FixSelected; //Play Music: - AudioPlayback.PlayChange; + AudioPlayback.PlaySound(SoundLib.Change); ChangeMusic; end; @@ -547,7 +548,7 @@ begin FixSelected; //Play Music: - AudioPlayback.PlayChange; + AudioPlayback.PlaySound(SoundLib.Change); ChangeMusic; end; end; @@ -559,7 +560,7 @@ begin begin if (Songs.SongList.Count > 0) AND (Mode = smNormal) then begin - AudioPlayback.PlayChange; + AudioPlayback.PlaySound(SoundLib.Change); SelectNext; // InteractNext; // SongTarget := Interaction; @@ -573,7 +574,7 @@ begin SDLK_LEFT: begin if (Songs.SongList.Count > 0)AND (Mode = smNormal) then begin - AudioPlayback.PlayChange; + AudioPlayback.PlaySound(SoundLib.Change); SelectPrev; ChangeMusic; SetScroll4; @@ -655,7 +656,7 @@ begin begin SkipTo(Random(CatSongs.VisibleSongs)); end; - AudioPlayback.PlayChange; + AudioPlayback.PlaySound(SoundLib.Change); ChangeMusic; SetScroll4; @@ -1804,7 +1805,6 @@ end; procedure TScreenSong.DrawEqualizer; var - Data: TFFTData; //Audio Data I, J: Integer; Res: byte; A, B: Integer; @@ -1822,7 +1822,7 @@ begin if (A <> EqualizerTime) then begin EqualizerTime := A; - Data := AudioPlayback.GetFFTData; + AudioPlayback.GetFFTData(EqualizerData); B := 0; Pos := 0; @@ -1850,23 +1850,23 @@ begin end; if I > 35 then - Data[i] := Data[i] * 8 + EqualizerData[i] := EqualizerData[i] * 8 else if I > 11 then - Data[i] := Data[i] * 4.5 + EqualizerData[i] := EqualizerData[i] * 4.5 else - Data[i] := Data[i] * 1.1; + EqualizerData[i] := EqualizerData[i] * 1.1; - if (Data[i] >= 1) then - Data[i] := 0.9999999999999; + if (EqualizerData[i] >= 1) then + EqualizerData[i] := 0.9999999999999; try if ( assigned( Theme ) ) AND ( assigned( Theme.Song ) ) AND - ( i < length( Data ) ) THEN + ( i < length( EqualizerData ) ) THEN begin - if single( Data[i] ) > 1 then + if single( EqualizerData[i] ) > 1 then begin - lTmp := Single(Data[i]) * Theme.Song.Equalizer.Length; + lTmp := Single(EqualizerData[i]) * Theme.Song.Equalizer.Length; if lTmp > Pos then Pos := lTmp; end; @@ -1874,7 +1874,7 @@ begin except {$IFDEF FPC} on E:EInvalidOp do - writeln( 'UScreenSong - DOH !!!! ('+inttostr(i)+' '+ inttostr( integer( Data[i] ) )+' * '+ ')' ); + writeln( 'UScreenSong - DOH !!!! ('+inttostr(i)+' '+ inttostr( integer( EqualizerData[i] ) )+' * '+ ')' ); {$ENDIF} end @@ -1989,7 +1989,7 @@ begin end; end; - AudioPlayback.PlayChange; + AudioPlayback.PlaySound(SoundLib.Change); ChangeMusic; SetScroll; UpdateLCD; @@ -2129,7 +2129,7 @@ begin if (Songs.SongList.Count > 0) and (not CatSongs.Song[Interaction].Main) AND (Mode = smNormal) then begin AudioPlayback.Stop; - AudioPlayback.PlayStart; + AudioPlayback.PlaySound(SoundLib.Start); ScreenEditSub.Path := CatSongs.Song[Interaction].Path; ScreenEditSub.FileName := CatSongs.Song[Interaction].FileName; FadeTo(@ScreenEditSub); diff --git a/Game/Code/Screens/UScreenSongJumpto.pas b/Game/Code/Screens/UScreenSongJumpto.pas index 14228964..dfa90009 100644 --- a/Game/Code/Screens/UScreenSongJumpto.pas +++ b/Game/Code/Screens/UScreenSongJumpto.pas @@ -67,7 +67,7 @@ begin SDLK_ESCAPE:
begin
Visible := False;
- AudioPlayback.PlayBack;
+ AudioPlayback.PlaySound(SoundLib.Back);
if (VisSongs = 0) AND (Length(Button[0].Text[0].Text) > 0) then
begin
ScreenSong.UnLoadDetailedCover;
diff --git a/Game/Code/Screens/UScreenSongMenu.pas b/Game/Code/Screens/UScreenSongMenu.pas index 88b0de32..ae0bc9ba 100644 --- a/Game/Code/Screens/UScreenSongMenu.pas +++ b/Game/Code/Screens/UScreenSongMenu.pas @@ -96,7 +96,7 @@ begin SDLK_ESCAPE, SDLK_BACKSPACE : begin - AudioPlayback.PlayBack; + AudioPlayback.PlaySound(SoundLib.Back); Visible := False; end; diff --git a/Game/Code/Screens/UScreenStatDetail.pas b/Game/Code/Screens/UScreenStatDetail.pas index 414055f9..d793baf0 100644 --- a/Game/Code/Screens/UScreenStatDetail.pas +++ b/Game/Code/Screens/UScreenStatDetail.pas @@ -53,7 +53,7 @@ begin SDLK_ESCAPE,
SDLK_BACKSPACE :
begin
- AudioPlayback.PlayBack;
+ AudioPlayback.PlaySound(SoundLib.Back);
FadeTo(@ScreenStatMain);
end;
SDLK_RETURN:
@@ -76,7 +76,7 @@ begin end;
if Interaction = 3 then begin
- AudioPlayback.PlayBack;
+ AudioPlayback.PlaySound(SoundLib.Back);
FadeTo(@ScreenStatMain);
end;
end;
diff --git a/Game/Code/Screens/UScreenStatMain.pas b/Game/Code/Screens/UScreenStatMain.pas index f7257201..53154d6e 100644 --- a/Game/Code/Screens/UScreenStatMain.pas +++ b/Game/Code/Screens/UScreenStatMain.pas @@ -62,7 +62,7 @@ begin SDLK_BACKSPACE : begin Ini.Save; - AudioPlayback.PlayBack; + AudioPlayback.PlaySound(SoundLib.Back); FadeTo(@ScreenMain); end; SDLK_RETURN: @@ -70,12 +70,12 @@ begin //Exit Button Pressed if Interaction = 4 then begin - AudioPlayback.PlayBack; + AudioPlayback.PlaySound(SoundLib.Back); FadeTo(@ScreenMain); end else //One of the Stats Buttons Pressed begin - AudioPlayback.PlayBack; + AudioPlayback.PlaySound(SoundLib.Back); ScreenStatDetail.Typ := Interaction; FadeTo(@ScreenStatDetail); end; |