From 5ed6620bad808381fce94f2cd67ee911b4d45bff Mon Sep 17 00:00:00 2001 From: whiteshark0 Date: Wed, 21 Mar 2007 19:19:04 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@1 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UMusic.pas | 783 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 783 insertions(+) create mode 100644 Game/Code/Classes/UMusic.pas (limited to 'Game/Code/Classes/UMusic.pas') diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas new file mode 100644 index 00000000..db1675c5 --- /dev/null +++ b/Game/Code/Classes/UMusic.pas @@ -0,0 +1,783 @@ +unit UMusic; + +interface + +uses Classes, MPlayer, Windows, Messages, SysUtils, Forms, ULog, USongs, Bass;//, DXSounds; + +procedure InitializeSound; + +type + TSoundCard = record + Name: string; + Source: array of string; + end; + + TFFTData = array [0..256] of Single; + + TCustomSoundEntry = record + Filename: String; + Handle: hStream; + end; + + + TMusic = class + private +// MediaPlayer: TMediaPlayer; // It will be replaced by another component; +{ MediaPlayerStart: TMediaPlayer; // or maybe not if done this way ;) + MediaPlayerBack: TMediaPlayer; + MediaPlayerSwoosh: TMediaPlayer; + MediaPlayerChange: TMediaPlayer; + MediaPlayerOption: TMediaPlayer; + MediaPlayerClick: TMediaPlayer; + MediaPlayerDrum: TMediaPlayer; + MediaPlayerHihat: TMediaPlayer; + MediaPlayerClap: TMediaPlayer; + MediaPlayerShuffle: TMediaPlayer;} + BassStart: hStream; // Wait, I've replaced this with BASS + BassBack: hStream; // It has almost all features we need + BassSwoosh: hStream; + BassChange: hStream; // Almost? It aleady has them all :) + BassOption: hStream; + BassClick: hStream; + BassDrum: hStream; + BassHihat: hStream; + BassClap: hStream; + BassShuffle: hStream; + + //Custom Sounds + CustomSounds: array of TCustomSoundEntry; + + + Loaded: boolean; + Loop: boolean; +// DXSound: TDXSound; +// Player: TcmxMp3; + public + Bass: hStream; + +// SoundCard: array of TSoundCard; + procedure InitializePlayback; + procedure InitializeRecord; + procedure SetVolume(Volume: integer); + procedure SetLoop(Enabled: boolean); + function Open(Name: string): boolean; // true if succeed + procedure Rewind; + procedure MoveTo(Time: real); + procedure Play; + procedure Pause; //Pause Mod + procedure Stop; + procedure Close; + function Finished: boolean; + function Length: real; + function Position: real; + procedure PlayStart; + procedure PlayBack; + procedure PlaySwoosh; + procedure PlayChange; + procedure PlayOption; + procedure PlayClick; + procedure PlayDrum; + procedure PlayHihat; + procedure PlayClap; + procedure PlayShuffle; + procedure StopShuffle; + procedure CaptureStart; + procedure CaptureStop; + procedure CaptureCard(RecordI, PlayerLeft, PlayerRight: byte); + procedure StopCard(Card: byte); + function LoadPlayerFromFile(var MediaPlayer: TMediaPlayer; Name: string): boolean; + function LoadSoundFromFile(var hStream: hStream; Name: string): boolean; + + //Equalizer + function GetFFTData: TFFTData; + + //Custom Sounds + function LoadCustomSound(const Filename: String): Cardinal; + procedure PlayCustomSound(const Index: Cardinal); + +end; + +const + RecordSystem = 1; + +type + TMuzyka = record + Path: string; + Start: integer; // start of song in ms +// BPM: array of TBPM; +// Gap: real; + IlNut: integer; + DlugoscNut: integer; +// WartoscNut: integer; + end; + + TCzesci = record + Akt: integer; // aktualna czesc utworu do rysowania + High: integer; + Ilosc: integer; + Resolution: integer; + NotesGAP: integer; + Wartosc: integer; + Czesc: array of 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; + end; + + TCzas = record // wszystko, co dotyczy aktualnej klatki +// BajtowTotal: integer; +// BajtowTeraz: integer; +// BajtowNaSek: integer; + OldBeat: integer; // poprzednio wykryty beat w utworze + AktBeat: integer; // aktualny beat w utworze + MidBeat: real; // dokladny AktBeat + + // should not be used +// OldHalf: integer; // poprzednio wykryta polowka +// AktHalf: integer; // aktualna polowka w utworze +// MidHalf: real; // dokladny AktHalf + + // 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 +// TerazSek: integer; + end; + +var + Form: TForm; + Music: TMusic; + + // muzyka + Muzyka: TMuzyka; + + // czesci z nutami; + Czesci: array of TCzesci; + + // czas + Czas: TCzas; + + fHWND: Thandle; + +const + ModeStr: array[TMPModes] of string = ('Not ready', 'Stopped', 'Playing', 'Recording', 'Seeking', 'Paused', 'Open'); + +implementation +uses UGraphic, URecord, UPliki, UIni, UMain, UThemes; + +procedure InitializeSound; +begin + Log.LogStatus('Initializing Playback', 'InitializeSound'); Music.InitializePlayback; + Log.LogStatus('Initializing Record', 'InitializeSound'); Music.InitializeRecord; +end; + +procedure TMusic.InitializePlayback; +var + Pet: integer; + S: integer; +begin + Log.BenchmarkStart(4); + Log.LogStatus('Initializing Playback Subsystem', 'Music Initialize'); + Loaded := false; + Loop := false; + fHWND := AllocateHWND( nil); + + if not BASS_Init(1, 44100, 0, fHWND, nil) then begin + Application.MessageBox ('Could not initialize BASS', 'Error'); + Exit; + end; + + Log.BenchmarkEnd(4); Log.LogBenchmark('--> Bass Init', 4); + + // config playing buffer +// BASS_SetConfig(BASS_CONFIG_UPDATEPERIOD, 10); +// BASS_SetConfig(BASS_CONFIG_BUFFER, 100); + +{ MediaPlayer := TMediaPlayer.Create( nil ); + MediaPlayer.ParentWindow := fHWND; + MediaPlayer.Wait := true;} + + Log.LogStatus('Loading Sounds', 'Music Initialize'); + +{ LoadPlayerFromFile(MediaPlayerStart, SoundPath + 'Common Start.mp3'); + LoadPlayerFromFile(MediaPlayerBack, SoundPath + 'Common Back.mp3'); + LoadPlayerFromFile(MediaPlayerSwoosh, SoundPath + 'menu swoosh.mp3'); + LoadPlayerFromFile(MediaPlayerChange, SoundPath + 'select music change music.mp3'); + LoadPlayerFromFile(MediaPlayerOption, SoundPath + 'option change col.mp3'); + LoadPlayerFromFile(MediaPlayerClick, SoundPath + 'rimshot022b.mp3'); + + LoadPlayerFromFile(MediaPlayerDrum, SoundPath + 'bassdrumhard076b.mp3'); + LoadPlayerFromFile(MediaPlayerHihat, SoundPath + 'hihatclosed068b.mp3'); + LoadPlayerFromFile(MediaPlayerClap, SoundPath + 'claps050b.mp3'); + + LoadPlayerFromFile(MediaPlayerShuffle, SoundPath + 'Shuffle.mp3');} + + Log.BenchmarkStart(4); + LoadSoundFromFile(BassStart, SoundPath + 'Common Start.mp3'); + LoadSoundFromFile(BassBack, SoundPath + 'Common Back.mp3'); + LoadSoundFromFile(BassSwoosh, SoundPath + 'menu swoosh.mp3'); + LoadSoundFromFile(BassChange, SoundPath + 'select music change music 50.mp3'); + LoadSoundFromFile(BassOption, SoundPath + 'option change col.mp3'); + LoadSoundFromFile(BassClick, SoundPath + 'rimshot022b.mp3'); + +// LoadSoundFromFile(BassDrum, SoundPath + 'bassdrumhard076b.mp3'); +// LoadSoundFromFile(BassHihat, SoundPath + 'hihatclosed068b.mp3'); +// LoadSoundFromFile(BassClap, SoundPath + 'claps050b.mp3'); + +// LoadSoundFromFile(BassShuffle, SoundPath + 'Shuffle.mp3'); + + Log.BenchmarkEnd(4); Log.LogBenchmark('--> Loading Sounds', 4); +end; + +procedure TMusic.InitializeRecord; +var + S: integer; + device: integer; + descr: string; + input: integer; + input2: integer; + flags: integer; + mic: array[0..15] of integer; + SC: integer; // soundcard + SCI: integer; // soundcard input +begin + if RecordSystem = 1 then 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; + + + // check for recording devices; + {device := 0; + descr := BASS_RecordGetDeviceDescription(device); + + SetLength(SoundCard, 0); + while (descr <> '') do begin + SC := High(SoundCard) + 1; + SetLength(SoundCard, SC+1); + + Log.LogAnalyze('Device #'+IntToStr(device)+': '+ descr); + SoundCard[SC].Description := Descr; + + // check for recording inputs + mic[device] := -1; // default to no change + input := 0; + BASS_RecordInit(device); + Log.LogAnalyze('Input #' + IntToStr(Input) + ': ' + BASS_RecordGetInputName(input)); + flags := BASS_RecordGetInput(input); + + SetLength(SoundCard[SC].Input, 0); + while (flags <> -1) do begin + SCI := High(SoundCard[SC].Input) + 1; + SetLength(SoundCard[SC].Input, SCI+1); + + Log.LogAnalyze('Input #' + IntToStr(Input) + ': ' + BASS_RecordGetInputName(input)); + SoundCard[SC].Input[SCI].Name := BASS_RecordGetInputName(Input); + + if (flags and BASS_INPUT_TYPE_MASK) = BASS_INPUT_TYPE_MIC then begin + mic[device] := input; // auto set microphone + end; + Inc(Input); + flags := BASS_RecordGetInput(input); + end; + + if mic[device] <> -1 then begin + Log.LogAnalyze('Found the mic at input ' + IntToStr(Mic[device])) + end else begin + Log.LogAnalyze('Mic not found'); + mic[device] := 0; // setting to the first one (for kxproject) + end; + SoundCard[SC].InputSeleceted := Mic[Device]; + + + BASS_RecordFree; + + inc(Device); + descr := BASS_RecordGetDeviceDescription(Device); + end; // while} + end; // if +end; + +procedure TMusic.SetVolume(Volume: integer); +begin + BASS_SetVolume(Volume); +end; + +procedure TMusic.SetLoop(Enabled: boolean); +begin + Loop := Enabled; +end; + +function TMusic.Open(Name: string): boolean; +begin + Loaded := false; + if FileExists(Name) then begin +{ MediaPlayer.FileName := Name; + MediaPlayer.Open;} + + Bass := Bass_StreamCreateFile(false, pchar(Name), 0, 0, 0); + Loaded := true; + end; + + Result := Loaded; + +// Player := TcmxMp3.Create(Name); +end; + +procedure TMusic.Rewind; +begin + if Loaded then begin +// MediaPlayer.Position := 0; + + end; +end; + +procedure TMusic.MoveTo(Time: real); +var + bytes: integer; +begin +// if Loaded then begin +// MediaPlayer.StartPos := Round(Time); + bytes := BASS_ChannelSeconds2Bytes(Bass, Time); + BASS_ChannelSetPosition(Bass, bytes); +// end; +end; + +procedure TMusic.Play; +begin + if Loaded then begin +// MediaPlayer.Play; + BASS_ChannelPlay(Bass, False); // for setting position before playing + end; +end; + +procedure TMusic.Pause; //Pause Mod +begin + if Loaded then begin + BASS_ChannelPause(Bass); // Pauses Song + end; +end; + +procedure TMusic.Stop; +begin + Bass_ChannelStop(Bass); +// Bass_StreamFree(Bass); +// if ModeStr[MediaPlayer.Mode] = 'Playing' then begin +// MediaPlayer.Stop; +// end; +end; + +procedure TMusic.Close; +begin + Bass_StreamFree(Bass); +// Player.Free; +// MediaPlayer.Close; +end; + +function TMusic.Length: real; +var + bytes: integer; +begin + Result := 60; + + bytes := BASS_StreamGetLength(Bass); + Result := BASS_ChannelBytes2Seconds(Bass, bytes); + +{ if Assigned(MediaPlayer) then begin + if Loaded then Result := MediaPlayer.Length / 1000; + end;} +// if Assigned(Player) then +// Result := Player.LengthInSeconds; +end; + +function TMusic.Position: real; +var + bytes: integer; +begin + Result := 0;//MediaPlayer.Position / 1000; + bytes := BASS_ChannelGetPosition(BASS); + Result := BASS_ChannelBytes2Seconds(BASS, bytes); +end; + +function TMusic.Finished: boolean; +begin + Result := false; +// if ModeStr[MediaPlayer.Mode] = 'Stopped' then Result := true; + if BASS_ChannelIsActive(BASS) = BASS_ACTIVE_STOPPED then begin +// beep; + Result := true; + end; +end; + +{function myeffect( chan : integer; stream : Pointer; len : integer; udata : Pointer ): Pointer; cdecl; +var + dane: pwordarray; + pet: integer; + Prev: smallint; + PrevNew: smallint; +begin + dane := stream; + Prev := 0; + for pet := 0 to len div 2 -1 do begin + PrevNew := Dane[Pet]; + +// Dane[pet] := Round(PrevNew*1/8 + Prev*7/8); + + Prev := Dane[Pet]; + end; +end;} + +procedure TMusic.PlayStart; +{var + Music: PMix_Chunk;} +begin +{ Mix_OpenAudio(44100, 16, 1, 16*1024); + Music := Mix_LoadWAV('D:\Rozne\UltraStar\Old\Boys - Hej Sokoly 30s.wav'); + Mix_RegisterEffect(0, myeffect, nil, 0); + Mix_PlayChannel(0, Music, 0);} + +// MediaPlayerStart.Rewind; +// MediaPlayerStart.Play; + BASS_ChannelPlay(BassStart, True); +end; + +procedure TMusic.PlayBack; +begin +// MediaPlayerBack.Rewind; +// MediaPlayerBack.Play; +// if not + BASS_ChannelPlay(BassBack, True);// then +// Application.MessageBox ('Error playing stream!', 'Error'); +end; + +procedure TMusic.PlaySwoosh; +begin +// MediaPlayerSwoosh.Rewind; +// MediaPlayerSwoosh.Play; + BASS_ChannelPlay(BassSwoosh, True); +end; + +procedure TMusic.PlayChange; +begin +// MediaPlayerChange.Rewind; +// MediaPlayerChange.Play; + BASS_ChannelPlay(BassChange, True); +end; + +procedure TMusic.PlayOption; +begin +// MediaPlayerOption.Rewind; +// MediaPlayerOption.Play; + BASS_ChannelPlay(BassOption, True); +end; + +procedure TMusic.PlayClick; +begin +// MediaPlayerClick.Rewind; +// MediaPlayerClick.Play; + BASS_ChannelPlay(BassClick, True); +end; + +procedure TMusic.PlayDrum; +begin +// MediaPlayerDrum.Rewind; +// MediaPlayerDrum.Play; + BASS_ChannelPlay(BassDrum, True); +end; + +procedure TMusic.PlayHihat; +begin +// MediaPlayerHihat.Rewind; +// MediaPlayerHihat.Play; + BASS_ChannelPlay(BassHihat, True); +end; + +procedure TMusic.PlayClap; +begin +// MediaPlayerClap.Rewind; +// MediaPlayerClap.Play; + BASS_ChannelPlay(BassClap, True); +end; + +procedure TMusic.PlayShuffle; +begin +// MediaPlayerShuffle.Rewind; +// MediaPlayerShuffle.Play; + BASS_ChannelPlay(BassShuffle, True); +end; + +procedure TMusic.StopShuffle; +begin + BASS_ChannelStop(BassShuffle); +end; + +procedure TMusic.CaptureStart; +var + S: integer; + SC: integer; + P1: integer; + P2: integer; +begin + for S := 0 to High(Sound) do + Sound[S].BufferLong[0].Clear; + +{ case PlayersPlay of + 1: begin + CaptureCard(0, 0, 1, 0); + end; + 2: begin + if Ini.TwoPlayerMode = 0 then begin + CaptureCard(0, 0, 1, 2); + end else begin + CaptureCard(0, 0, 1, 0); + CaptureCard(1, 1, 2, 0); + end; + end; + 3: begin + CaptureCard(0, 0, 1, 2); + CaptureCard(1, 1, 3, 0); + end; + end; // case} + +// CaptureCard(0, 0, 0, 0); +// end; + + {for SC := 0 to High(SoundCard) do begin + P1 := Ini.SoundCard[SC, 1]; + P2 := Ini.SoundCard[SC, 2]; + if P1 > PlayersPlay then P1 := 0; + if P2 > PlayersPlay then P2 := 0; + CaptureCard(SC, P1, P2); + end; } + // 0.5.2: new + for SC := 0 to High(Ini.CardList) do begin + P1 := Ini.CardList[SC].ChannelL; + P2 := Ini.CardList[SC].ChannelR; + if P1 > PlayersPlay then P1 := 0; + if P2 > PlayersPlay then P2 := 0; + if (P1 > 0) or (P2 > 0) then + CaptureCard(SC, P1, P2); + end; +end; + +procedure TMusic.CaptureStop; +var + SC: integer; + P1: integer; + P2: integer; +begin +{ if RecordSystem = 1 then begin + case PlayersPlay of + 1: begin + StopCard(0); + end; + 2: begin + if Ini.TwoPlayerMode = 0 then begin + StopCard(0); + end else begin + StopCard(0); + StopCard(1); + end; + end; + 3: begin + StopCard(0); + StopCard(1); + end; + end; + end;} + + {for SC := 0 to High(SoundCard) do begin + StopCard(SC); + end; } + + // 0.5.2 + for SC := 0 to High(Ini.CardList) do begin + P1 := Ini.CardList[SC].ChannelL; + P2 := Ini.CardList[SC].ChannelR; + if P1 > PlayersPlay then P1 := 0; + if P2 > PlayersPlay then P2 := 0; + if (P1 > 0) or (P2 > 0) then StopCard(SC); + end; + +end; + +//procedure TMusic.CaptureCard(RecordI, SoundNum, PlayerLeft, PlayerRight: byte); +procedure TMusic.CaptureCard(RecordI, PlayerLeft, PlayerRight: byte); +var + Error: integer; + ErrorMsg: string; +begin + if not BASS_RecordInit(RecordI) 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.LogAnalyze('Error initializing record [' + IntToStr(RecordI) + ', ' + + IntToStr(PlayerLeft) + ', '+ IntToStr(PlayerRight) + ']: ' + + ErrorMsg);} + Log.LogError('Error initializing record [' + IntToStr(RecordI) + ', ' + + IntToStr(PlayerLeft) + ', '+ IntToStr(PlayerRight) + ']: ' + + ErrorMsg); + Log.LogError('Music -> CaptureCard: Error initializing record: ' + ErrorMsg); + + + end else begin + + //SoundCard[RecordI].BassRecordStream := BASS_RecordStart(44100, 2, MakeLong(0, 20) , @GetMicrophone, PlayerLeft + PlayerRight*256); + Recording.SoundCard[RecordI].BassRecordStream := BASS_RecordStart(44100, 2, MakeLong(0, 20) , @GetMicrophone, PlayerLeft + PlayerRight*256); + + {if SoundCard[RecordI].BassRecordStream = 0 then begin + Error := BASS_ErrorGetCode; + + ErrorMsg := IntToStr(Error); + if Error = BASS_ERROR_INIT then ErrorMsg := 'Not successfully called'; + if Error = BASS_ERROR_ALREADY then ErrorMsg := 'Recording is already in progress'; + if Error = BASS_ERROR_NOTAVAIL then ErrorMsg := 'The recording device is not available'; + if Error = BASS_ERROR_FORMAT then ErrorMsg := 'The specified format is not supported'; + if Error = BASS_ERROR_MEM then ErrorMsg := 'There is insufficent memory'; + if Error = BASS_ERROR_UNKNOWN then ErrorMsg := 'Unknown'; + + Log.LogError('Error creating record stream [' + IntToStr(RecordI) + ', ' + + IntToStr(PlayerLeft) + ', '+ IntToStr(PlayerRight) + ']: ' + + ErrorMsg); + end; } + end; +end; + +procedure TMusic.StopCard(Card: byte); +begin + BASS_RecordSetDevice(Card); + BASS_RecordFree; +end; + +function TMusic.LoadPlayerFromFile(var MediaPlayer: TMediaPlayer; Name: string): boolean; +begin + Log.LogStatus('Loading Sound: "' + Name + '"', 'LoadPlayerFromFile'); + if FileExists(Name) then begin + try + MediaPlayer := TMediaPlayer.Create( nil ); + except + Log.LogError('Failed to create MediaPlayer', 'LoadPlayerFromFile'); + end; + try + MediaPlayer.ParentWindow := fHWND; + MediaPlayer.Wait := true; + MediaPlayer.FileName := Name; + MediaPlayer.DeviceType := dtAutoSelect; + MediaPlayer.Display := nil; + except + Log.LogError('Failed setting MediaPlayer: ' + MediaPlayer.ErrorMessage, 'LoadPlayerFromFile'); + end; + try + MediaPlayer.Open; + except + Log.LogError('Failed to open using MediaPlayer', 'LoadPlayerFromFile'); + end; + end else begin + Log.LogError('Sound not found: "' + Name + '"', 'LoadPlayerFromFile'); + exit; + end; +end; + +function TMusic.LoadSoundFromFile(var hStream: hStream; Name: string): boolean; +begin + if FileExists(Name) then begin + Log.LogStatus('Loading Sound: "' + Name + '"', 'LoadPlayerFromFile'); + try + hStream := BASS_StreamCreateFile(False, pchar(Name), 0, 0, 0); + except + Log.LogError('Failed to open using BASS', 'LoadPlayerFromFile'); + end; + end else begin + Log.LogError('Sound not found: "' + Name + '"', 'LoadPlayerFromFile'); + exit; + end; +end; + +//Equalizer +function TMusic.GetFFTData: TFFTData; +var +Data: TFFTData; +begin + //Get Channel Data Mono and 256 Values + BASS_ChannelGetData(Bass, @Result, BASS_DATA_FFT512); + //Result := Data; +end; + +function TMusic.LoadCustomSound(const Filename: String): Cardinal; +var + S: hStream; + I: Integer; + F: String; +begin + //Search for Sound in already loaded Sounds + F := UpperCase(FileName); + For I := 0 to High(CustomSounds) do + begin + if (UpperCase(CustomSounds[I].Filename) = F) then + begin + Result := I; + Exit; + end; + end; + + if LoadSoundFromFile(S, Filename) then + Result := High(CustomSounds) + else + Result := 0; +end; + +procedure TMusic.PlayCustomSound(const Index: Cardinal); +begin +if Index <= High(CustomSounds) then + BASS_ChannelPlay(CustomSounds[Index].Handle, True); +end; + + +end. -- cgit v1.2.3 From ccb5946db9ae26b5b40a171110e4a5fc595cb0bf Mon Sep 17 00:00:00 2001 From: whiteshark0 Date: Sun, 25 Mar 2007 15:20:46 +0000 Subject: Changed Music.SetVolume from Global Wave Volume to Application-Only BassConfig git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@35 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UMusic.pas | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'Game/Code/Classes/UMusic.pas') diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas index db1675c5..f7f0e20d 100644 --- a/Game/Code/Classes/UMusic.pas +++ b/Game/Code/Classes/UMusic.pas @@ -342,7 +342,12 @@ end; procedure TMusic.SetVolume(Volume: integer); begin - BASS_SetVolume(Volume); + //Old Sets Wave Volume + //BASS_SetVolume(Volume); + //New: Sets Volume only for this Application + BASS_SetConfig(BASS_CONFIG_GVOL_SAMPLE, Volume); + BASS_SetConfig(BASS_CONFIG_GVOL_STREAM, Volume); + BASS_SetConfig(BASS_CONFIG_GVOL_MUSIC, Volume); end; procedure TMusic.SetLoop(Enabled: boolean); -- cgit v1.2.3 From 563375e18e4aeba0152a9761f1f84d66aaeb27d2 Mon Sep 17 00:00:00 2001 From: whiteshark0 Date: Fri, 30 Mar 2007 12:19:08 +0000 Subject: Finished Code for Plugin Sound PlayBack Removed Debug Message from ULanguage git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@50 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UMusic.pas | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'Game/Code/Classes/UMusic.pas') diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas index f7f0e20d..0e4e4ddd 100644 --- a/Game/Code/Classes/UMusic.pas +++ b/Game/Code/Classes/UMusic.pas @@ -731,11 +731,18 @@ begin end; function TMusic.LoadSoundFromFile(var hStream: hStream; Name: string): boolean; +var + L: Integer; begin if FileExists(Name) then begin Log.LogStatus('Loading Sound: "' + Name + '"', 'LoadPlayerFromFile'); try hStream := BASS_StreamCreateFile(False, pchar(Name), 0, 0, 0); + //Add CustomSound + L := High(CustomSounds) + 1; + SetLength (CustomSounds, L + 1); + CustomSounds[L].Filename := Name; + CustomSounds[L].Handle := hStream; except Log.LogError('Failed to open using BASS', 'LoadPlayerFromFile'); end; @@ -762,7 +769,7 @@ var F: String; begin //Search for Sound in already loaded Sounds - F := UpperCase(FileName); + F := UpperCase(SoundPath + FileName); For I := 0 to High(CustomSounds) do begin if (UpperCase(CustomSounds[I].Filename) = F) then @@ -772,7 +779,7 @@ begin end; end; - if LoadSoundFromFile(S, Filename) then + if LoadSoundFromFile(S, SoundPath + Filename) then Result := High(CustomSounds) else Result := 0; -- cgit v1.2.3 From 4a731514163a14bd3a9222d99707880b56772663 Mon Sep 17 00:00:00 2001 From: whiteshark0 Date: Wed, 16 May 2007 19:19:35 +0000 Subject: all SongFile Loading and Saving procedures moved to UFiles. Added Some Tolerance in Song File Loading and Song Header Loading. Fix: Programm doesn't Crash anymore when a coruppted Song is loaded for Singing or Editing. Now Jump back to SongScreen and show an Error Message. Also Party Mode is not Interupted, a new Song will be selected automatically. git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@197 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UMusic.pas | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Game/Code/Classes/UMusic.pas') diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas index 0e4e4ddd..6e997c11 100644 --- a/Game/Code/Classes/UMusic.pas +++ b/Game/Code/Classes/UMusic.pas @@ -199,7 +199,7 @@ const ModeStr: array[TMPModes] of string = ('Not ready', 'Stopped', 'Playing', 'Recording', 'Seeking', 'Paused', 'Open'); implementation -uses UGraphic, URecord, UPliki, UIni, UMain, UThemes; +uses UGraphic, URecord, UFiles, UIni, UMain, UThemes; procedure InitializeSound; begin -- cgit v1.2.3 From 49ada15c935658c5d90416e26acfb360f1e7c047 Mon Sep 17 00:00:00 2001 From: whiteshark0 Date: Sun, 3 Jun 2007 19:45:43 +0000 Subject: Added SongPreview Fading Song Preview Max Volume is now 70 % Need Testing because of timing git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@243 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UMusic.pas | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'Game/Code/Classes/UMusic.pas') diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas index 6e997c11..52bae3c9 100644 --- a/Game/Code/Classes/UMusic.pas +++ b/Game/Code/Classes/UMusic.pas @@ -59,6 +59,7 @@ type procedure InitializePlayback; procedure InitializeRecord; procedure SetVolume(Volume: integer); + procedure SetMusicVolume(Volume: Byte); procedure SetLoop(Enabled: boolean); function Open(Name: string): boolean; // true if succeed procedure Rewind; @@ -350,6 +351,16 @@ begin BASS_SetConfig(BASS_CONFIG_GVOL_MUSIC, Volume); end; +procedure TMusic.SetMusicVolume(Volume: Byte); +begin + //Max Volume Prevention + if Volume > 100 then + Volume := 100; + + //Set Volume + BASS_ChannelSetAttributes (Bass, -1, Integer(Volume), -101); +end; + procedure TMusic.SetLoop(Enabled: boolean); begin Loop := Enabled; @@ -364,6 +375,8 @@ begin Bass := Bass_StreamCreateFile(false, pchar(Name), 0, 0, 0); Loaded := true; + //Set Max Volume + SetMusicVolume (100); end; Result := Loaded; -- cgit v1.2.3 From d08356e3b64d8738ff9672229c1bbe963b58337c Mon Sep 17 00:00:00 2001 From: whiteshark0 Date: Wed, 6 Jun 2007 20:24:29 +0000 Subject: Fixed some Bugs in Song Fading Added Ini Values to change the Fading and the Preview Volume git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@245 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UMusic.pas | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Game/Code/Classes/UMusic.pas') diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas index 52bae3c9..3fcd2a21 100644 --- a/Game/Code/Classes/UMusic.pas +++ b/Game/Code/Classes/UMusic.pas @@ -59,7 +59,7 @@ type procedure InitializePlayback; procedure InitializeRecord; procedure SetVolume(Volume: integer); - procedure SetMusicVolume(Volume: Byte); + procedure SetMusicVolume(Volume: integer); procedure SetLoop(Enabled: boolean); function Open(Name: string): boolean; // true if succeed procedure Rewind; @@ -351,14 +351,14 @@ begin BASS_SetConfig(BASS_CONFIG_GVOL_MUSIC, Volume); end; -procedure TMusic.SetMusicVolume(Volume: Byte); +procedure TMusic.SetMusicVolume(Volume: Integer); begin //Max Volume Prevention if Volume > 100 then Volume := 100; //Set Volume - BASS_ChannelSetAttributes (Bass, -1, Integer(Volume), -101); + BASS_ChannelSetAttributes (Bass, -1, Volume, -101); end; procedure TMusic.SetLoop(Enabled: boolean); -- cgit v1.2.3 From 0ea8eaa9fcf83bb7c014109eba6a8c4e25fd1a9f Mon Sep 17 00:00:00 2001 From: b1indy Date: Fri, 20 Jul 2007 21:26:39 +0000 Subject: UGraphicClasses.pas: minor modification to Flare effect UMusic.pas: modified Music.Play to play from start if Loop is set (dunno if this conflicts with something else, don't hope so) git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@303 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UMusic.pas | 1 + 1 file changed, 1 insertion(+) (limited to 'Game/Code/Classes/UMusic.pas') diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas index 3fcd2a21..4e647ed3 100644 --- a/Game/Code/Classes/UMusic.pas +++ b/Game/Code/Classes/UMusic.pas @@ -407,6 +407,7 @@ procedure TMusic.Play; begin if Loaded then begin // MediaPlayer.Play; + if Loop then BASS_ChannelPlay(Bass, True); // start from beginning... actually bass itself does not loop, nor does this TMusic Class BASS_ChannelPlay(Bass, False); // for setting position before playing end; end; -- cgit v1.2.3 From bf62fe40a0986e0791eb462ef5adebf079e744e6 Mon Sep 17 00:00:00 2001 From: whiteshark0 Date: Sun, 2 Sep 2007 14:31:51 +0000 Subject: Some Cleanup in URecord Some Cleanup in UMusic Some Cleanup in ProjectFile Upgrade from Bass 2.1 to Bass 2.3 git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@361 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UMusic.pas | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Game/Code/Classes/UMusic.pas') diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas index 4e647ed3..979ba4e5 100644 --- a/Game/Code/Classes/UMusic.pas +++ b/Game/Code/Classes/UMusic.pas @@ -441,7 +441,7 @@ var begin Result := 60; - bytes := BASS_StreamGetLength(Bass); + bytes := BASS_ChannelGetLength(Bass); Result := BASS_ChannelBytes2Seconds(Bass, bytes); { if Assigned(MediaPlayer) then begin -- cgit v1.2.3 From 611f516b33a0c109893354593e28afe10f48e7db Mon Sep 17 00:00:00 2001 From: jaybinks Date: Tue, 18 Sep 2007 12:07:57 +0000 Subject: major tidy up of Umusic ... removes mplayer unit and dependency. tidy up of other units in move to compile in lazarus. git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@392 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UMusic.pas | 266 ++++++------------------------------------- 1 file changed, 32 insertions(+), 234 deletions(-) (limited to 'Game/Code/Classes/UMusic.pas') diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas index 979ba4e5..f9c6457d 100644 --- a/Game/Code/Classes/UMusic.pas +++ b/Game/Code/Classes/UMusic.pas @@ -2,7 +2,16 @@ unit UMusic; interface -uses Classes, MPlayer, Windows, Messages, SysUtils, Forms, ULog, USongs, Bass;//, DXSounds; +uses Classes, + Windows, + Messages, + SysUtils, + {$IFNDEF FPC} + Forms, + {$ENDIF} + ULog, + USongs, + Bass; procedure InitializeSound; @@ -22,17 +31,6 @@ type TMusic = class private -// MediaPlayer: TMediaPlayer; // It will be replaced by another component; -{ MediaPlayerStart: TMediaPlayer; // or maybe not if done this way ;) - MediaPlayerBack: TMediaPlayer; - MediaPlayerSwoosh: TMediaPlayer; - MediaPlayerChange: TMediaPlayer; - MediaPlayerOption: TMediaPlayer; - MediaPlayerClick: TMediaPlayer; - MediaPlayerDrum: TMediaPlayer; - MediaPlayerHihat: TMediaPlayer; - MediaPlayerClap: TMediaPlayer; - MediaPlayerShuffle: TMediaPlayer;} BassStart: hStream; // Wait, I've replaced this with BASS BassBack: hStream; // It has almost all features we need BassSwoosh: hStream; @@ -50,12 +48,8 @@ type Loaded: boolean; Loop: boolean; -// DXSound: TDXSound; -// Player: TcmxMp3; public Bass: hStream; - -// SoundCard: array of TSoundCard; procedure InitializePlayback; procedure InitializeRecord; procedure SetVolume(Volume: integer); @@ -86,7 +80,6 @@ type procedure CaptureStop; procedure CaptureCard(RecordI, PlayerLeft, PlayerRight: byte); procedure StopCard(Card: byte); - function LoadPlayerFromFile(var MediaPlayer: TMediaPlayer; Name: string): boolean; function LoadSoundFromFile(var hStream: hStream; Name: string): boolean; //Equalizer @@ -105,11 +98,8 @@ type TMuzyka = record Path: string; Start: integer; // start of song in ms -// BPM: array of TBPM; -// Gap: real; IlNut: integer; DlugoscNut: integer; -// WartoscNut: integer; end; TCzesci = record @@ -138,27 +128,15 @@ type Tekst: string; FreeStyle: boolean; Wartosc: integer; // zwykla nuta x1, zlota nuta x2 - - - - end; end; end; TCzas = record // wszystko, co dotyczy aktualnej klatki -// BajtowTotal: integer; -// BajtowTeraz: integer; -// BajtowNaSek: integer; OldBeat: integer; // poprzednio wykryty beat w utworze AktBeat: integer; // aktualny beat w utworze MidBeat: real; // dokladny AktBeat - // should not be used -// OldHalf: integer; // poprzednio wykryta polowka -// AktHalf: integer; // aktualna polowka w utworze -// MidHalf: real; // dokladny AktHalf - // now we use this for super synchronization! // only used when analyzing voice OldBeatD: integer; // poprzednio wykryty beat w utworze @@ -178,11 +156,9 @@ type Teraz: real; // aktualny czas w utworze Razem: real; // caly czas utworu -// TerazSek: integer; end; var - Form: TForm; Music: TMusic; // muzyka @@ -196,6 +172,10 @@ var fHWND: Thandle; +type + TMPModes = (mpNotReady, mpStopped, mpPlaying, mpRecording, mpSeeking, + mpPaused, mpOpen); + const ModeStr: array[TMPModes] of string = ('Not ready', 'Stopped', 'Playing', 'Recording', 'Seeking', 'Paused', 'Open'); @@ -230,25 +210,8 @@ begin // BASS_SetConfig(BASS_CONFIG_UPDATEPERIOD, 10); // BASS_SetConfig(BASS_CONFIG_BUFFER, 100); -{ MediaPlayer := TMediaPlayer.Create( nil ); - MediaPlayer.ParentWindow := fHWND; - MediaPlayer.Wait := true;} - Log.LogStatus('Loading Sounds', 'Music Initialize'); -{ LoadPlayerFromFile(MediaPlayerStart, SoundPath + 'Common Start.mp3'); - LoadPlayerFromFile(MediaPlayerBack, SoundPath + 'Common Back.mp3'); - LoadPlayerFromFile(MediaPlayerSwoosh, SoundPath + 'menu swoosh.mp3'); - LoadPlayerFromFile(MediaPlayerChange, SoundPath + 'select music change music.mp3'); - LoadPlayerFromFile(MediaPlayerOption, SoundPath + 'option change col.mp3'); - LoadPlayerFromFile(MediaPlayerClick, SoundPath + 'rimshot022b.mp3'); - - LoadPlayerFromFile(MediaPlayerDrum, SoundPath + 'bassdrumhard076b.mp3'); - LoadPlayerFromFile(MediaPlayerHihat, SoundPath + 'hihatclosed068b.mp3'); - LoadPlayerFromFile(MediaPlayerClap, SoundPath + 'claps050b.mp3'); - - LoadPlayerFromFile(MediaPlayerShuffle, SoundPath + 'Shuffle.mp3');} - Log.BenchmarkStart(4); LoadSoundFromFile(BassStart, SoundPath + 'Common Start.mp3'); LoadSoundFromFile(BassBack, SoundPath + 'Common Back.mp3'); @@ -370,9 +333,6 @@ function TMusic.Open(Name: string): boolean; begin Loaded := false; if FileExists(Name) then begin -{ MediaPlayer.FileName := Name; - MediaPlayer.Open;} - Bass := Bass_StreamCreateFile(false, pchar(Name), 0, 0, 0); Loaded := true; //Set Max Volume @@ -380,15 +340,11 @@ begin end; Result := Loaded; - -// Player := TcmxMp3.Create(Name); end; procedure TMusic.Rewind; begin if Loaded then begin -// MediaPlayer.Position := 0; - end; end; @@ -396,18 +352,17 @@ procedure TMusic.MoveTo(Time: real); var bytes: integer; begin -// if Loaded then begin -// MediaPlayer.StartPos := Round(Time); bytes := BASS_ChannelSeconds2Bytes(Bass, Time); BASS_ChannelSetPosition(Bass, bytes); -// end; end; procedure TMusic.Play; begin - if Loaded then begin -// MediaPlayer.Play; - if Loop then BASS_ChannelPlay(Bass, True); // start from beginning... actually bass itself does not loop, nor does this TMusic Class + if Loaded then + begin + if Loop then + BASS_ChannelPlay(Bass, True); // start from beginning... actually bass itself does not loop, nor does this TMusic Class + BASS_ChannelPlay(Bass, False); // for setting position before playing end; end; @@ -422,17 +377,11 @@ end; procedure TMusic.Stop; begin Bass_ChannelStop(Bass); -// Bass_StreamFree(Bass); -// if ModeStr[MediaPlayer.Mode] = 'Playing' then begin -// MediaPlayer.Stop; -// end; end; procedure TMusic.Close; begin Bass_StreamFree(Bass); -// Player.Free; -// MediaPlayer.Close; end; function TMusic.Length: real; @@ -441,129 +390,76 @@ var begin Result := 60; - bytes := BASS_ChannelGetLength(Bass); + bytes := BASS_ChannelGetLength(Bass); Result := BASS_ChannelBytes2Seconds(Bass, bytes); - -{ if Assigned(MediaPlayer) then begin - if Loaded then Result := MediaPlayer.Length / 1000; - end;} -// if Assigned(Player) then -// Result := Player.LengthInSeconds; end; function TMusic.Position: real; var bytes: integer; begin - Result := 0;//MediaPlayer.Position / 1000; - bytes := BASS_ChannelGetPosition(BASS); + Result := 0; + bytes := BASS_ChannelGetPosition(BASS); Result := BASS_ChannelBytes2Seconds(BASS, bytes); end; function TMusic.Finished: boolean; begin Result := false; -// if ModeStr[MediaPlayer.Mode] = 'Stopped' then Result := true; - if BASS_ChannelIsActive(BASS) = BASS_ACTIVE_STOPPED then begin -// beep; + + if BASS_ChannelIsActive(BASS) = BASS_ACTIVE_STOPPED then + begin Result := true; end; end; -{function myeffect( chan : integer; stream : Pointer; len : integer; udata : Pointer ): Pointer; cdecl; -var - dane: pwordarray; - pet: integer; - Prev: smallint; - PrevNew: smallint; -begin - dane := stream; - Prev := 0; - for pet := 0 to len div 2 -1 do begin - PrevNew := Dane[Pet]; - -// Dane[pet] := Round(PrevNew*1/8 + Prev*7/8); - - Prev := Dane[Pet]; - end; -end;} - procedure TMusic.PlayStart; -{var - Music: PMix_Chunk;} begin -{ Mix_OpenAudio(44100, 16, 1, 16*1024); - Music := Mix_LoadWAV('D:\Rozne\UltraStar\Old\Boys - Hej Sokoly 30s.wav'); - Mix_RegisterEffect(0, myeffect, nil, 0); - Mix_PlayChannel(0, Music, 0);} - -// MediaPlayerStart.Rewind; -// MediaPlayerStart.Play; BASS_ChannelPlay(BassStart, True); end; procedure TMusic.PlayBack; begin -// MediaPlayerBack.Rewind; -// MediaPlayerBack.Play; -// if not BASS_ChannelPlay(BassBack, True);// then -// Application.MessageBox ('Error playing stream!', 'Error'); end; procedure TMusic.PlaySwoosh; begin -// MediaPlayerSwoosh.Rewind; -// MediaPlayerSwoosh.Play; BASS_ChannelPlay(BassSwoosh, True); end; procedure TMusic.PlayChange; begin -// MediaPlayerChange.Rewind; -// MediaPlayerChange.Play; BASS_ChannelPlay(BassChange, True); end; procedure TMusic.PlayOption; begin -// MediaPlayerOption.Rewind; -// MediaPlayerOption.Play; BASS_ChannelPlay(BassOption, True); end; procedure TMusic.PlayClick; begin -// MediaPlayerClick.Rewind; -// MediaPlayerClick.Play; BASS_ChannelPlay(BassClick, True); end; procedure TMusic.PlayDrum; begin -// MediaPlayerDrum.Rewind; -// MediaPlayerDrum.Play; BASS_ChannelPlay(BassDrum, True); end; procedure TMusic.PlayHihat; begin -// MediaPlayerHihat.Rewind; -// MediaPlayerHihat.Play; BASS_ChannelPlay(BassHihat, True); end; procedure TMusic.PlayClap; begin -// MediaPlayerClap.Rewind; -// MediaPlayerClap.Play; BASS_ChannelPlay(BassClap, True); end; procedure TMusic.PlayShuffle; begin -// MediaPlayerShuffle.Rewind; -// MediaPlayerShuffle.Play; BASS_ChannelPlay(BassShuffle, True); end; @@ -582,35 +478,6 @@ begin for S := 0 to High(Sound) do Sound[S].BufferLong[0].Clear; -{ case PlayersPlay of - 1: begin - CaptureCard(0, 0, 1, 0); - end; - 2: begin - if Ini.TwoPlayerMode = 0 then begin - CaptureCard(0, 0, 1, 2); - end else begin - CaptureCard(0, 0, 1, 0); - CaptureCard(1, 1, 2, 0); - end; - end; - 3: begin - CaptureCard(0, 0, 1, 2); - CaptureCard(1, 1, 3, 0); - end; - end; // case} - -// CaptureCard(0, 0, 0, 0); -// end; - - {for SC := 0 to High(SoundCard) do begin - P1 := Ini.SoundCard[SC, 1]; - P2 := Ini.SoundCard[SC, 2]; - if P1 > PlayersPlay then P1 := 0; - if P2 > PlayersPlay then P2 := 0; - CaptureCard(SC, P1, P2); - end; } - // 0.5.2: new for SC := 0 to High(Ini.CardList) do begin P1 := Ini.CardList[SC].ChannelL; P2 := Ini.CardList[SC].ChannelR; @@ -627,31 +494,7 @@ var P1: integer; P2: integer; begin -{ if RecordSystem = 1 then begin - case PlayersPlay of - 1: begin - StopCard(0); - end; - 2: begin - if Ini.TwoPlayerMode = 0 then begin - StopCard(0); - end else begin - StopCard(0); - StopCard(1); - end; - end; - 3: begin - StopCard(0); - StopCard(1); - end; - end; - end;} - - {for SC := 0 to High(SoundCard) do begin - StopCard(SC); - end; } - // 0.5.2 for SC := 0 to High(Ini.CardList) do begin P1 := Ini.CardList[SC].ChannelL; P2 := Ini.CardList[SC].ChannelR; @@ -686,26 +529,10 @@ begin Log.LogError('Music -> CaptureCard: Error initializing record: ' + ErrorMsg); - end else begin - - //SoundCard[RecordI].BassRecordStream := BASS_RecordStart(44100, 2, MakeLong(0, 20) , @GetMicrophone, PlayerLeft + PlayerRight*256); - Recording.SoundCard[RecordI].BassRecordStream := BASS_RecordStart(44100, 2, MakeLong(0, 20) , @GetMicrophone, PlayerLeft + PlayerRight*256); - - {if SoundCard[RecordI].BassRecordStream = 0 then begin - Error := BASS_ErrorGetCode; - - ErrorMsg := IntToStr(Error); - if Error = BASS_ERROR_INIT then ErrorMsg := 'Not successfully called'; - if Error = BASS_ERROR_ALREADY then ErrorMsg := 'Recording is already in progress'; - if Error = BASS_ERROR_NOTAVAIL then ErrorMsg := 'The recording device is not available'; - if Error = BASS_ERROR_FORMAT then ErrorMsg := 'The specified format is not supported'; - if Error = BASS_ERROR_MEM then ErrorMsg := 'There is insufficent memory'; - if Error = BASS_ERROR_UNKNOWN then ErrorMsg := 'Unknown'; - - Log.LogError('Error creating record stream [' + IntToStr(RecordI) + ', ' - + IntToStr(PlayerLeft) + ', '+ IntToStr(PlayerRight) + ']: ' - + ErrorMsg); - end; } + end + else + begin + Recording.SoundCard[RecordI].BassRecordStream := BASS_RecordStart(44100, 2, MakeLong(0, 20) , @GetMicrophone, PlayerLeft + PlayerRight*256); end; end; @@ -715,41 +542,12 @@ begin BASS_RecordFree; end; -function TMusic.LoadPlayerFromFile(var MediaPlayer: TMediaPlayer; Name: string): boolean; -begin - Log.LogStatus('Loading Sound: "' + Name + '"', 'LoadPlayerFromFile'); - if FileExists(Name) then begin - try - MediaPlayer := TMediaPlayer.Create( nil ); - except - Log.LogError('Failed to create MediaPlayer', 'LoadPlayerFromFile'); - end; - try - MediaPlayer.ParentWindow := fHWND; - MediaPlayer.Wait := true; - MediaPlayer.FileName := Name; - MediaPlayer.DeviceType := dtAutoSelect; - MediaPlayer.Display := nil; - except - Log.LogError('Failed setting MediaPlayer: ' + MediaPlayer.ErrorMessage, 'LoadPlayerFromFile'); - end; - try - MediaPlayer.Open; - except - Log.LogError('Failed to open using MediaPlayer', 'LoadPlayerFromFile'); - end; - end else begin - Log.LogError('Sound not found: "' + Name + '"', 'LoadPlayerFromFile'); - exit; - end; -end; - function TMusic.LoadSoundFromFile(var hStream: hStream; Name: string): boolean; var L: Integer; begin if FileExists(Name) then begin - Log.LogStatus('Loading Sound: "' + Name + '"', 'LoadPlayerFromFile'); + Log.LogStatus('Loading Sound: "' + Name + '"', 'LoadSoundFromFile'); try hStream := BASS_StreamCreateFile(False, pchar(Name), 0, 0, 0); //Add CustomSound @@ -758,10 +556,10 @@ begin CustomSounds[L].Filename := Name; CustomSounds[L].Handle := hStream; except - Log.LogError('Failed to open using BASS', 'LoadPlayerFromFile'); + Log.LogError('Failed to open using BASS', 'LoadSoundFromFile'); end; end else begin - Log.LogError('Sound not found: "' + Name + '"', 'LoadPlayerFromFile'); + Log.LogError('Sound not found: "' + Name + '"', 'LoadSoundFromFile'); exit; end; end; -- cgit v1.2.3 From 62c82114318ed04ce42617fa9ce2e179834dbda4 Mon Sep 17 00:00:00 2001 From: jaybinks Date: Wed, 19 Sep 2007 11:44:10 +0000 Subject: added UCommon ( in classes ) for lazarus... common functions needed for lazarus ( and others ) can be put in here. also this now compiles on lazarus.. ( dosnt link yet... but I dont get any critical compiler errors ) tested to compile in my delphi, and basic functionality is fine. git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@395 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UMusic.pas | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) (limited to 'Game/Code/Classes/UMusic.pas') diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas index f9c6457d..be585ee1 100644 --- a/Game/Code/Classes/UMusic.pas +++ b/Game/Code/Classes/UMusic.pas @@ -2,6 +2,11 @@ unit UMusic; interface +{$IFDEF FPC} + {$MODE Delphi} +{$ENDIF} + + uses Classes, Windows, Messages, @@ -180,7 +185,14 @@ const ModeStr: array[TMPModes] of string = ('Not ready', 'Stopped', 'Playing', 'Recording', 'Seeking', 'Paused', 'Open'); implementation -uses UGraphic, URecord, UFiles, UIni, UMain, UThemes; + +uses UCommon, + UGraphic, + URecord, + UFiles, + UIni, + UMain, + UThemes; procedure InitializeSound; begin @@ -195,12 +207,18 @@ var begin Log.BenchmarkStart(4); Log.LogStatus('Initializing Playback Subsystem', 'Music Initialize'); + Loaded := false; - Loop := false; - fHWND := AllocateHWND( nil); + Loop := false; + + fHWND := AllocateHWND( nil); // TODO : JB - can we do something different here ?? lazarus didnt like this function - if not BASS_Init(1, 44100, 0, fHWND, nil) then begin + if not BASS_Init(1, 44100, 0, fHWND, nil) then + begin + {$IFNDEF FPC} + // TODO : JB find a way to do this nice.. Application.MessageBox ('Could not initialize BASS', 'Error'); + {$ENDIF} Exit; end; -- cgit v1.2.3 From db82b7e30a1b58b56fdb4bfc6089b47200ca1da1 Mon Sep 17 00:00:00 2001 From: jaybinks Date: Thu, 20 Sep 2007 06:36:58 +0000 Subject: Ultrastar-DX now compiles in linux (using lazarus) Bass etc is commented out.. but it compiles, and im working through the runtime errors. git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@408 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UMusic.pas | 1356 +++++++++++++++++++++++------------------- 1 file changed, 731 insertions(+), 625 deletions(-) (limited to 'Game/Code/Classes/UMusic.pas') diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas index be585ee1..e2e1f27e 100644 --- a/Game/Code/Classes/UMusic.pas +++ b/Game/Code/Classes/UMusic.pas @@ -1,625 +1,731 @@ -unit UMusic; - -interface - -{$IFDEF FPC} - {$MODE Delphi} -{$ENDIF} - - -uses Classes, - Windows, - Messages, - SysUtils, - {$IFNDEF FPC} - Forms, - {$ENDIF} - ULog, - USongs, - Bass; - -procedure InitializeSound; - -type - TSoundCard = record - Name: string; - Source: array of string; - end; - - TFFTData = array [0..256] of Single; - - TCustomSoundEntry = record - Filename: String; - Handle: hStream; - end; - - - TMusic = class - private - BassStart: hStream; // Wait, I've replaced this with BASS - BassBack: hStream; // It has almost all features we need - BassSwoosh: hStream; - BassChange: hStream; // Almost? It aleady has them all :) - BassOption: hStream; - BassClick: hStream; - BassDrum: hStream; - BassHihat: hStream; - BassClap: hStream; - BassShuffle: hStream; - - //Custom Sounds - CustomSounds: array of TCustomSoundEntry; - - - Loaded: boolean; - Loop: boolean; - public - Bass: hStream; - procedure InitializePlayback; - procedure InitializeRecord; - procedure SetVolume(Volume: integer); - procedure SetMusicVolume(Volume: integer); - procedure SetLoop(Enabled: boolean); - function Open(Name: string): boolean; // true if succeed - procedure Rewind; - procedure MoveTo(Time: real); - procedure Play; - procedure Pause; //Pause Mod - procedure Stop; - procedure Close; - function Finished: boolean; - function Length: real; - function Position: real; - procedure PlayStart; - procedure PlayBack; - procedure PlaySwoosh; - procedure PlayChange; - procedure PlayOption; - procedure PlayClick; - procedure PlayDrum; - procedure PlayHihat; - procedure PlayClap; - procedure PlayShuffle; - procedure StopShuffle; - procedure CaptureStart; - procedure CaptureStop; - procedure CaptureCard(RecordI, PlayerLeft, PlayerRight: byte); - procedure StopCard(Card: byte); - function LoadSoundFromFile(var hStream: hStream; Name: string): boolean; - - //Equalizer - function GetFFTData: TFFTData; - - //Custom Sounds - function LoadCustomSound(const Filename: String): Cardinal; - procedure PlayCustomSound(const Index: Cardinal); - -end; - -const - RecordSystem = 1; - -type - TMuzyka = record - Path: string; - Start: integer; // start of song in ms - IlNut: integer; - DlugoscNut: integer; - end; - - TCzesci = record - Akt: integer; // aktualna czesc utworu do rysowania - High: integer; - Ilosc: integer; - Resolution: integer; - NotesGAP: integer; - Wartosc: integer; - Czesc: array of 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; - 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; - -var - Music: TMusic; - - // muzyka - Muzyka: TMuzyka; - - // czesci z nutami; - Czesci: array of TCzesci; - - // czas - Czas: TCzas; - - fHWND: Thandle; - -type - TMPModes = (mpNotReady, mpStopped, mpPlaying, mpRecording, mpSeeking, - mpPaused, mpOpen); - -const - ModeStr: array[TMPModes] of string = ('Not ready', 'Stopped', 'Playing', 'Recording', 'Seeking', 'Paused', 'Open'); - -implementation - -uses UCommon, - UGraphic, - URecord, - UFiles, - UIni, - UMain, - UThemes; - -procedure InitializeSound; -begin - Log.LogStatus('Initializing Playback', 'InitializeSound'); Music.InitializePlayback; - Log.LogStatus('Initializing Record', 'InitializeSound'); Music.InitializeRecord; -end; - -procedure TMusic.InitializePlayback; -var - Pet: integer; - S: integer; -begin - Log.BenchmarkStart(4); - Log.LogStatus('Initializing Playback Subsystem', 'Music Initialize'); - - Loaded := false; - Loop := false; - - fHWND := AllocateHWND( nil); // TODO : JB - can we do something different here ?? lazarus didnt like this function - - if not BASS_Init(1, 44100, 0, fHWND, nil) then - begin - {$IFNDEF FPC} - // TODO : JB find a way to do this nice.. - Application.MessageBox ('Could not initialize BASS', 'Error'); - {$ENDIF} - Exit; - end; - - Log.BenchmarkEnd(4); Log.LogBenchmark('--> Bass Init', 4); - - // config playing buffer -// BASS_SetConfig(BASS_CONFIG_UPDATEPERIOD, 10); -// BASS_SetConfig(BASS_CONFIG_BUFFER, 100); - - Log.LogStatus('Loading Sounds', 'Music Initialize'); - - Log.BenchmarkStart(4); - LoadSoundFromFile(BassStart, SoundPath + 'Common Start.mp3'); - LoadSoundFromFile(BassBack, SoundPath + 'Common Back.mp3'); - LoadSoundFromFile(BassSwoosh, SoundPath + 'menu swoosh.mp3'); - LoadSoundFromFile(BassChange, SoundPath + 'select music change music 50.mp3'); - LoadSoundFromFile(BassOption, SoundPath + 'option change col.mp3'); - LoadSoundFromFile(BassClick, SoundPath + 'rimshot022b.mp3'); - -// LoadSoundFromFile(BassDrum, SoundPath + 'bassdrumhard076b.mp3'); -// LoadSoundFromFile(BassHihat, SoundPath + 'hihatclosed068b.mp3'); -// LoadSoundFromFile(BassClap, SoundPath + 'claps050b.mp3'); - -// LoadSoundFromFile(BassShuffle, SoundPath + 'Shuffle.mp3'); - - Log.BenchmarkEnd(4); Log.LogBenchmark('--> Loading Sounds', 4); -end; - -procedure TMusic.InitializeRecord; -var - S: integer; - device: integer; - descr: string; - input: integer; - input2: integer; - flags: integer; - mic: array[0..15] of integer; - SC: integer; // soundcard - SCI: integer; // soundcard input -begin - if RecordSystem = 1 then 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; - - - // check for recording devices; - {device := 0; - descr := BASS_RecordGetDeviceDescription(device); - - SetLength(SoundCard, 0); - while (descr <> '') do begin - SC := High(SoundCard) + 1; - SetLength(SoundCard, SC+1); - - Log.LogAnalyze('Device #'+IntToStr(device)+': '+ descr); - SoundCard[SC].Description := Descr; - - // check for recording inputs - mic[device] := -1; // default to no change - input := 0; - BASS_RecordInit(device); - Log.LogAnalyze('Input #' + IntToStr(Input) + ': ' + BASS_RecordGetInputName(input)); - flags := BASS_RecordGetInput(input); - - SetLength(SoundCard[SC].Input, 0); - while (flags <> -1) do begin - SCI := High(SoundCard[SC].Input) + 1; - SetLength(SoundCard[SC].Input, SCI+1); - - Log.LogAnalyze('Input #' + IntToStr(Input) + ': ' + BASS_RecordGetInputName(input)); - SoundCard[SC].Input[SCI].Name := BASS_RecordGetInputName(Input); - - if (flags and BASS_INPUT_TYPE_MASK) = BASS_INPUT_TYPE_MIC then begin - mic[device] := input; // auto set microphone - end; - Inc(Input); - flags := BASS_RecordGetInput(input); - end; - - if mic[device] <> -1 then begin - Log.LogAnalyze('Found the mic at input ' + IntToStr(Mic[device])) - end else begin - Log.LogAnalyze('Mic not found'); - mic[device] := 0; // setting to the first one (for kxproject) - end; - SoundCard[SC].InputSeleceted := Mic[Device]; - - - BASS_RecordFree; - - inc(Device); - descr := BASS_RecordGetDeviceDescription(Device); - end; // while} - end; // if -end; - -procedure TMusic.SetVolume(Volume: integer); -begin - //Old Sets Wave Volume - //BASS_SetVolume(Volume); - //New: Sets Volume only for this Application - BASS_SetConfig(BASS_CONFIG_GVOL_SAMPLE, Volume); - BASS_SetConfig(BASS_CONFIG_GVOL_STREAM, Volume); - BASS_SetConfig(BASS_CONFIG_GVOL_MUSIC, Volume); -end; - -procedure TMusic.SetMusicVolume(Volume: Integer); -begin - //Max Volume Prevention - if Volume > 100 then - Volume := 100; - - //Set Volume - BASS_ChannelSetAttributes (Bass, -1, Volume, -101); -end; - -procedure TMusic.SetLoop(Enabled: boolean); -begin - Loop := Enabled; -end; - -function TMusic.Open(Name: string): boolean; -begin - Loaded := false; - if FileExists(Name) then begin - Bass := Bass_StreamCreateFile(false, pchar(Name), 0, 0, 0); - Loaded := true; - //Set Max Volume - SetMusicVolume (100); - end; - - Result := Loaded; -end; - -procedure TMusic.Rewind; -begin - if Loaded then begin - end; -end; - -procedure TMusic.MoveTo(Time: real); -var - bytes: integer; -begin - bytes := BASS_ChannelSeconds2Bytes(Bass, Time); - BASS_ChannelSetPosition(Bass, bytes); -end; - -procedure TMusic.Play; -begin - if Loaded then - begin - if Loop then - BASS_ChannelPlay(Bass, True); // start from beginning... actually bass itself does not loop, nor does this TMusic Class - - BASS_ChannelPlay(Bass, False); // for setting position before playing - end; -end; - -procedure TMusic.Pause; //Pause Mod -begin - if Loaded then begin - BASS_ChannelPause(Bass); // Pauses Song - end; -end; - -procedure TMusic.Stop; -begin - Bass_ChannelStop(Bass); -end; - -procedure TMusic.Close; -begin - Bass_StreamFree(Bass); -end; - -function TMusic.Length: real; -var - bytes: integer; -begin - Result := 60; - - bytes := BASS_ChannelGetLength(Bass); - Result := BASS_ChannelBytes2Seconds(Bass, bytes); -end; - -function TMusic.Position: real; -var - bytes: integer; -begin - Result := 0; - bytes := BASS_ChannelGetPosition(BASS); - Result := BASS_ChannelBytes2Seconds(BASS, bytes); -end; - -function TMusic.Finished: boolean; -begin - Result := false; - - if BASS_ChannelIsActive(BASS) = BASS_ACTIVE_STOPPED then - begin - Result := true; - end; -end; - -procedure TMusic.PlayStart; -begin - BASS_ChannelPlay(BassStart, True); -end; - -procedure TMusic.PlayBack; -begin - BASS_ChannelPlay(BassBack, True);// then -end; - -procedure TMusic.PlaySwoosh; -begin - BASS_ChannelPlay(BassSwoosh, True); -end; - -procedure TMusic.PlayChange; -begin - BASS_ChannelPlay(BassChange, True); -end; - -procedure TMusic.PlayOption; -begin - BASS_ChannelPlay(BassOption, True); -end; - -procedure TMusic.PlayClick; -begin - BASS_ChannelPlay(BassClick, True); -end; - -procedure TMusic.PlayDrum; -begin - BASS_ChannelPlay(BassDrum, True); -end; - -procedure TMusic.PlayHihat; -begin - BASS_ChannelPlay(BassHihat, True); -end; - -procedure TMusic.PlayClap; -begin - BASS_ChannelPlay(BassClap, True); -end; - -procedure TMusic.PlayShuffle; -begin - BASS_ChannelPlay(BassShuffle, True); -end; - -procedure TMusic.StopShuffle; -begin - BASS_ChannelStop(BassShuffle); -end; - -procedure TMusic.CaptureStart; -var - S: integer; - SC: integer; - P1: integer; - P2: integer; -begin - for S := 0 to High(Sound) do - Sound[S].BufferLong[0].Clear; - - for SC := 0 to High(Ini.CardList) do begin - P1 := Ini.CardList[SC].ChannelL; - P2 := Ini.CardList[SC].ChannelR; - if P1 > PlayersPlay then P1 := 0; - if P2 > PlayersPlay then P2 := 0; - if (P1 > 0) or (P2 > 0) then - CaptureCard(SC, P1, P2); - end; -end; - -procedure TMusic.CaptureStop; -var - SC: integer; - P1: integer; - P2: integer; -begin - - for SC := 0 to High(Ini.CardList) do begin - P1 := Ini.CardList[SC].ChannelL; - P2 := Ini.CardList[SC].ChannelR; - if P1 > PlayersPlay then P1 := 0; - if P2 > PlayersPlay then P2 := 0; - if (P1 > 0) or (P2 > 0) then StopCard(SC); - end; - -end; - -//procedure TMusic.CaptureCard(RecordI, SoundNum, PlayerLeft, PlayerRight: byte); -procedure TMusic.CaptureCard(RecordI, PlayerLeft, PlayerRight: byte); -var - Error: integer; - ErrorMsg: string; -begin - if not BASS_RecordInit(RecordI) 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.LogAnalyze('Error initializing record [' + IntToStr(RecordI) + ', ' - + IntToStr(PlayerLeft) + ', '+ IntToStr(PlayerRight) + ']: ' - + ErrorMsg);} - Log.LogError('Error initializing record [' + IntToStr(RecordI) + ', ' - + IntToStr(PlayerLeft) + ', '+ IntToStr(PlayerRight) + ']: ' - + ErrorMsg); - Log.LogError('Music -> CaptureCard: Error initializing record: ' + ErrorMsg); - - - end - else - begin - Recording.SoundCard[RecordI].BassRecordStream := BASS_RecordStart(44100, 2, MakeLong(0, 20) , @GetMicrophone, PlayerLeft + PlayerRight*256); - end; -end; - -procedure TMusic.StopCard(Card: byte); -begin - BASS_RecordSetDevice(Card); - BASS_RecordFree; -end; - -function TMusic.LoadSoundFromFile(var hStream: hStream; Name: string): boolean; -var - L: Integer; -begin - if FileExists(Name) then begin - Log.LogStatus('Loading Sound: "' + Name + '"', 'LoadSoundFromFile'); - try - hStream := BASS_StreamCreateFile(False, pchar(Name), 0, 0, 0); - //Add CustomSound - L := High(CustomSounds) + 1; - SetLength (CustomSounds, L + 1); - CustomSounds[L].Filename := Name; - CustomSounds[L].Handle := hStream; - except - Log.LogError('Failed to open using BASS', 'LoadSoundFromFile'); - end; - end else begin - Log.LogError('Sound not found: "' + Name + '"', 'LoadSoundFromFile'); - exit; - end; -end; - -//Equalizer -function TMusic.GetFFTData: TFFTData; -var -Data: TFFTData; -begin - //Get Channel Data Mono and 256 Values - BASS_ChannelGetData(Bass, @Result, BASS_DATA_FFT512); - //Result := Data; -end; - -function TMusic.LoadCustomSound(const Filename: String): Cardinal; -var - S: hStream; - I: Integer; - F: String; -begin - //Search for Sound in already loaded Sounds - F := UpperCase(SoundPath + FileName); - For I := 0 to High(CustomSounds) do - begin - if (UpperCase(CustomSounds[I].Filename) = F) then - begin - Result := I; - Exit; - end; - end; - - if LoadSoundFromFile(S, SoundPath + Filename) then - Result := High(CustomSounds) - else - Result := 0; -end; - -procedure TMusic.PlayCustomSound(const Index: Cardinal); -begin -if Index <= High(CustomSounds) then - BASS_ChannelPlay(CustomSounds[Index].Handle, True); -end; - - -end. +unit UMusic; + +interface + +{$I switches.inc} + +{$IFDEF FPC} + {$MODE Delphi} +{$ENDIF} + + +uses Classes, + {$IFDEF win32} + windows, + {$ENDIF} + UCommon, + Messages, + SysUtils, + {$IFNDEF FPC} + Forms, + {$ENDIF} + {$IFDEF useBASS} + bass, + {$ENDIF} + ULog, + USongs; + + +procedure InitializeSound; + +type + TSoundCard = record + Name: string; + Source: array of string; + end; + + TFFTData = array [0..256] of Single; + + TCustomSoundEntry = record + Filename : String; + Handle : hStream; + end; + + + TMusic = class + private + BassStart: hStream; // Wait, I've replaced this with BASS + BassBack: hStream; // It has almost all features we need + BassSwoosh: hStream; + BassChange: hStream; // Almost? It aleady has them all :) + BassOption: hStream; + BassClick: hStream; + BassDrum: hStream; + BassHihat: hStream; + BassClap: hStream; + BassShuffle: hStream; + + //Custom Sounds + CustomSounds: array of TCustomSoundEntry; + + + Loaded: boolean; + Loop: boolean; + public + Bass: hStream; + procedure InitializePlayback; + procedure InitializeRecord; + procedure SetVolume(Volume: integer); + procedure SetMusicVolume(Volume: integer); + procedure SetLoop(Enabled: boolean); + function Open(Name: string): boolean; // true if succeed + procedure Rewind; + procedure MoveTo(Time: real); + procedure Play; + procedure Pause; //Pause Mod + procedure Stop; + procedure Close; + function Finished: boolean; + function Length: real; + function Position: real; + procedure PlayStart; + procedure PlayBack; + procedure PlaySwoosh; + procedure PlayChange; + procedure PlayOption; + procedure PlayClick; + procedure PlayDrum; + procedure PlayHihat; + procedure PlayClap; + procedure PlayShuffle; + procedure StopShuffle; + procedure CaptureStart; + procedure CaptureStop; + procedure CaptureCard(RecordI, PlayerLeft, PlayerRight: byte); + procedure StopCard(Card: byte); + function LoadSoundFromFile(var hStream: hStream; Name: string): boolean; + + //Equalizer + function GetFFTData: TFFTData; + + //Custom Sounds + function LoadCustomSound(const Filename: String): Cardinal; + procedure PlayCustomSound(const Index: Cardinal); + +end; + +const + RecordSystem = 1; + +type + TMuzyka = record + Path: string; + Start: integer; // start of song in ms + IlNut: integer; + DlugoscNut: integer; + end; + + TCzesci = record + Akt: integer; // aktualna czesc utworu do rysowania + High: integer; + Ilosc: integer; + Resolution: integer; + NotesGAP: integer; + Wartosc: integer; + Czesc: array of 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; + 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; + +var + Music: TMusic; + + // muzyka + Muzyka: TMuzyka; + + // czesci z nutami; + Czesci: array of TCzesci; + + // czas + Czas: TCzas; + + fHWND: Thandle; + +type + TMPModes = (mpNotReady, mpStopped, mpPlaying, mpRecording, mpSeeking, + mpPaused, mpOpen); + +const + ModeStr: array[TMPModes] of string = ('Not ready', 'Stopped', 'Playing', 'Recording', 'Seeking', 'Paused', 'Open'); + +implementation + +uses + {$IFDEF FPC} + lclintf, + {$ENDIF} + UGraphic, + URecord, + UFiles, + UIni, + UMain, + UThemes; + +procedure InitializeSound; +begin + Log.LogStatus('Initializing Playback', 'InitializeSound'); Music.InitializePlayback; + Log.LogStatus('Initializing Record', 'InitializeSound'); Music.InitializeRecord; +end; + +procedure TMusic.InitializePlayback; +var + Pet: integer; + S: integer; +begin + Log.BenchmarkStart(4); + Log.LogStatus('Initializing Playback Subsystem', 'Music Initialize'); + + Loaded := false; + Loop := false; + + fHWND := AllocateHWND( nil); // TODO : JB_lazarus - can we do something different here ?? lazarus didnt like this function + + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + if not BASS_Init(1, 44100, 0, fHWND, nil) then + begin + {$IFNDEF FPC} + // TODO : JB_lazarus find a way to do this nice.. + Application.MessageBox ('Could not initialize BASS', 'Error'); + {$ENDIF} + Exit; + end; + {$ENDIF} + + Log.BenchmarkEnd(4); Log.LogBenchmark('--> Bass Init', 4); + + // config playing buffer +// BASS_SetConfig(BASS_CONFIG_UPDATEPERIOD, 10); +// BASS_SetConfig(BASS_CONFIG_BUFFER, 100); + + Log.LogStatus('Loading Sounds', 'Music Initialize'); + + Log.BenchmarkStart(4); + LoadSoundFromFile(BassStart, SoundPath + 'Common Start.mp3'); + LoadSoundFromFile(BassBack, SoundPath + 'Common Back.mp3'); + LoadSoundFromFile(BassSwoosh, SoundPath + 'menu swoosh.mp3'); + LoadSoundFromFile(BassChange, SoundPath + 'select music change music 50.mp3'); + LoadSoundFromFile(BassOption, SoundPath + 'option change col.mp3'); + LoadSoundFromFile(BassClick, SoundPath + 'rimshot022b.mp3'); + +// LoadSoundFromFile(BassDrum, SoundPath + 'bassdrumhard076b.mp3'); +// LoadSoundFromFile(BassHihat, SoundPath + 'hihatclosed068b.mp3'); +// LoadSoundFromFile(BassClap, SoundPath + 'claps050b.mp3'); + +// LoadSoundFromFile(BassShuffle, SoundPath + 'Shuffle.mp3'); + + Log.BenchmarkEnd(4); Log.LogBenchmark('--> Loading Sounds', 4); +end; + +procedure TMusic.InitializeRecord; +var + S: integer; + device: integer; + descr: string; + input: integer; + input2: integer; + flags: integer; + mic: array[0..15] of integer; + SC: integer; // soundcard + SCI: integer; // soundcard input +begin + if RecordSystem = 1 then 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; + + + // check for recording devices; + {device := 0; + descr := BASS_RecordGetDeviceDescription(device); + + SetLength(SoundCard, 0); + while (descr <> '') do begin + SC := High(SoundCard) + 1; + SetLength(SoundCard, SC+1); + + Log.LogAnalyze('Device #'+IntToStr(device)+': '+ descr); + SoundCard[SC].Description := Descr; + + // check for recording inputs + mic[device] := -1; // default to no change + input := 0; + BASS_RecordInit(device); + Log.LogAnalyze('Input #' + IntToStr(Input) + ': ' + BASS_RecordGetInputName(input)); + flags := BASS_RecordGetInput(input); + + SetLength(SoundCard[SC].Input, 0); + while (flags <> -1) do begin + SCI := High(SoundCard[SC].Input) + 1; + SetLength(SoundCard[SC].Input, SCI+1); + + Log.LogAnalyze('Input #' + IntToStr(Input) + ': ' + BASS_RecordGetInputName(input)); + SoundCard[SC].Input[SCI].Name := BASS_RecordGetInputName(Input); + + if (flags and BASS_INPUT_TYPE_MASK) = BASS_INPUT_TYPE_MIC then begin + mic[device] := input; // auto set microphone + end; + Inc(Input); + flags := BASS_RecordGetInput(input); + end; + + if mic[device] <> -1 then begin + Log.LogAnalyze('Found the mic at input ' + IntToStr(Mic[device])) + end else begin + Log.LogAnalyze('Mic not found'); + mic[device] := 0; // setting to the first one (for kxproject) + end; + SoundCard[SC].InputSeleceted := Mic[Device]; + + + BASS_RecordFree; + + inc(Device); + descr := BASS_RecordGetDeviceDescription(Device); + end; // while} + end; // if +end; + +procedure TMusic.SetVolume(Volume: integer); +begin + //Old Sets Wave Volume + //BASS_SetVolume(Volume); + //New: Sets Volume only for this Application + + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_SetConfig(BASS_CONFIG_GVOL_SAMPLE, Volume); + BASS_SetConfig(BASS_CONFIG_GVOL_STREAM, Volume); + BASS_SetConfig(BASS_CONFIG_GVOL_MUSIC, Volume); + {$ENDIF} +end; + +procedure TMusic.SetMusicVolume(Volume: Integer); +begin + //Max Volume Prevention + if Volume > 100 then + Volume := 100; + + //Set Volume + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_ChannelSetAttributes (Bass, -1, Volume, -101); + {$ENDIF} +end; + +procedure TMusic.SetLoop(Enabled: boolean); +begin + Loop := Enabled; +end; + +function TMusic.Open(Name: string): boolean; +begin + Loaded := false; + if FileExists(Name) then + begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + Bass := Bass_StreamCreateFile(false, pchar(Name), 0, 0, 0); + {$ENDIF} + + Loaded := true; + //Set Max Volume + SetMusicVolume (100); + end; + + Result := Loaded; +end; + +procedure TMusic.Rewind; +begin + if Loaded then begin + end; +end; + +procedure TMusic.MoveTo(Time: real); +var + bytes: integer; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + bytes := BASS_ChannelSeconds2Bytes(Bass, Time); + BASS_ChannelSetPosition(Bass, bytes); + {$ENDIF} +end; + +procedure TMusic.Play; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + if Loaded then + begin + if Loop then + BASS_ChannelPlay(Bass, True); // start from beginning... actually bass itself does not loop, nor does this TMusic Class + + BASS_ChannelPlay(Bass, False); // for setting position before playing + end; + {$ENDIF} +end; + +procedure TMusic.Pause; //Pause Mod +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + if Loaded then begin + BASS_ChannelPause(Bass); // Pauses Song + end; + {$ENDIF} +end; + +procedure TMusic.Stop; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + Bass_ChannelStop(Bass); + {$ENDIF} +end; + +procedure TMusic.Close; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + Bass_StreamFree(Bass); + {$ENDIF} +end; + +function TMusic.Length: real; +var + bytes: integer; +begin + Result := 60; + + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + bytes := BASS_ChannelGetLength(Bass); + Result := BASS_ChannelBytes2Seconds(Bass, bytes); + {$ENDIF} +end; + +function TMusic.Position: real; +var + bytes: integer; +begin + Result := 0; + + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + bytes := BASS_ChannelGetPosition(BASS); + Result := BASS_ChannelBytes2Seconds(BASS, bytes); + {$ENDIF} +end; + +function TMusic.Finished: boolean; +begin + Result := false; + + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + if BASS_ChannelIsActive(BASS) = BASS_ACTIVE_STOPPED then + begin + Result := true; + end; + {$ENDIF} +end; + +procedure TMusic.PlayStart; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_ChannelPlay(BassStart, True); + {$ENDIF} +end; + +procedure TMusic.PlayBack; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_ChannelPlay(BassBack, True);// then + {$ENDIF} +end; + +procedure TMusic.PlaySwoosh; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_ChannelPlay(BassSwoosh, True); + {$ENDIF} +end; + +procedure TMusic.PlayChange; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_ChannelPlay(BassChange, True); + {$ENDIF} +end; + +procedure TMusic.PlayOption; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_ChannelPlay(BassOption, True); + {$ENDIF} +end; + +procedure TMusic.PlayClick; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_ChannelPlay(BassClick, True); + {$ENDIF} +end; + +procedure TMusic.PlayDrum; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_ChannelPlay(BassDrum, True); + {$ENDIF} +end; + +procedure TMusic.PlayHihat; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_ChannelPlay(BassHihat, True); + {$ENDIF} +end; + +procedure TMusic.PlayClap; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_ChannelPlay(BassClap, True); + {$ENDIF} +end; + +procedure TMusic.PlayShuffle; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_ChannelPlay(BassShuffle, True); + {$ENDIF} +end; + +procedure TMusic.StopShuffle; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_ChannelStop(BassShuffle); + {$ENDIF} +end; + +procedure TMusic.CaptureStart; +var + S: integer; + SC: integer; + P1: integer; + P2: integer; +begin + for S := 0 to High(Sound) do + Sound[S].BufferLong[0].Clear; + + for SC := 0 to High(Ini.CardList) do begin + P1 := Ini.CardList[SC].ChannelL; + P2 := Ini.CardList[SC].ChannelR; + if P1 > PlayersPlay then P1 := 0; + if P2 > PlayersPlay then P2 := 0; + if (P1 > 0) or (P2 > 0) then + CaptureCard(SC, P1, P2); + end; +end; + +procedure TMusic.CaptureStop; +var + SC: integer; + P1: integer; + P2: integer; +begin + + for SC := 0 to High(Ini.CardList) do begin + P1 := Ini.CardList[SC].ChannelL; + P2 := Ini.CardList[SC].ChannelR; + if P1 > PlayersPlay then P1 := 0; + if P2 > PlayersPlay then P2 := 0; + if (P1 > 0) or (P2 > 0) then StopCard(SC); + end; + +end; + +//procedure TMusic.CaptureCard(RecordI, SoundNum, PlayerLeft, PlayerRight: byte); +procedure TMusic.CaptureCard(RecordI, PlayerLeft, PlayerRight: byte); +var + Error: integer; + ErrorMsg: string; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + + if not BASS_RecordInit(RecordI) 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.LogAnalyze('Error initializing record [' + IntToStr(RecordI) + ', ' + + IntToStr(PlayerLeft) + ', '+ IntToStr(PlayerRight) + ']: ' + + ErrorMsg);} + Log.LogError('Error initializing record [' + IntToStr(RecordI) + ', ' + + IntToStr(PlayerLeft) + ', '+ IntToStr(PlayerRight) + ']: ' + + ErrorMsg); + Log.LogError('Music -> CaptureCard: Error initializing record: ' + ErrorMsg); + + + end + else + begin + Recording.SoundCard[RecordI].BassRecordStream := BASS_RecordStart(44100, 2, MakeLong(0, 20) , @GetMicrophone, PlayerLeft + PlayerRight*256); + end; + + {$ENDIF} +end; + +procedure TMusic.StopCard(Card: byte); +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_RecordSetDevice(Card); + BASS_RecordFree; + {$ENDIF} +end; + +function TMusic.LoadSoundFromFile(var hStream: hStream; Name: string): boolean; +var + L: Integer; +begin + if FileExists(Name) then begin + Log.LogStatus('Loading Sound: "' + Name + '"', 'LoadSoundFromFile'); + try + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + hStream := BASS_StreamCreateFile(False, pchar(Name), 0, 0, 0); + {$ENDIF} + + //Add CustomSound + L := High(CustomSounds) + 1; + SetLength (CustomSounds, L + 1); + CustomSounds[L].Filename := Name; + CustomSounds[L].Handle := hStream; + except + Log.LogError('Failed to open using BASS', 'LoadSoundFromFile'); + end; + end else begin + Log.LogError('Sound not found: "' + Name + '"', 'LoadSoundFromFile'); + exit; + end; +end; + +//Equalizer +function TMusic.GetFFTData: TFFTData; +var +Data: TFFTData; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + + //Get Channel Data Mono and 256 Values + BASS_ChannelGetData(Bass, @Result, BASS_DATA_FFT512); + //Result := Data; + + {$ENDIF} +end; + +function TMusic.LoadCustomSound(const Filename: String): Cardinal; +var + S: hStream; + I: Integer; + F: String; +begin + //Search for Sound in already loaded Sounds + F := UpperCase(SoundPath + FileName); + For I := 0 to High(CustomSounds) do + begin + if (UpperCase(CustomSounds[I].Filename) = F) then + begin + Result := I; + Exit; + end; + end; + + if LoadSoundFromFile(S, SoundPath + Filename) then + Result := High(CustomSounds) + else + Result := 0; +end; + +procedure TMusic.PlayCustomSound(const Index: Cardinal); +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + + if Index <= High(CustomSounds) then + BASS_ChannelPlay(CustomSounds[Index].Handle, True); + + {$ENDIF} +end; + + +end. -- cgit v1.2.3 From 26d8c209beba866f111a9d047bf1a70fe245b75d Mon Sep 17 00:00:00 2001 From: b1indy Date: Thu, 20 Sep 2007 07:19:45 +0000 Subject: new lyrics stuff; it's broken (lyrics don't show) and in "debug" mode (weird stuff going on in the singscreen) but i'm tired of editing conflicts git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@412 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UMusic.pas | 1466 +++++++++++++++++++++--------------------- 1 file changed, 735 insertions(+), 731 deletions(-) (limited to 'Game/Code/Classes/UMusic.pas') diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas index e2e1f27e..b9ed47b4 100644 --- a/Game/Code/Classes/UMusic.pas +++ b/Game/Code/Classes/UMusic.pas @@ -1,731 +1,735 @@ -unit UMusic; - -interface - -{$I switches.inc} - -{$IFDEF FPC} - {$MODE Delphi} -{$ENDIF} - - -uses Classes, - {$IFDEF win32} - windows, - {$ENDIF} - UCommon, - Messages, - SysUtils, - {$IFNDEF FPC} - Forms, - {$ENDIF} - {$IFDEF useBASS} - bass, - {$ENDIF} - ULog, - USongs; - - -procedure InitializeSound; - -type - TSoundCard = record - Name: string; - Source: array of string; - end; - - TFFTData = array [0..256] of Single; - - TCustomSoundEntry = record - Filename : String; - Handle : hStream; - end; - - - TMusic = class - private - BassStart: hStream; // Wait, I've replaced this with BASS - BassBack: hStream; // It has almost all features we need - BassSwoosh: hStream; - BassChange: hStream; // Almost? It aleady has them all :) - BassOption: hStream; - BassClick: hStream; - BassDrum: hStream; - BassHihat: hStream; - BassClap: hStream; - BassShuffle: hStream; - - //Custom Sounds - CustomSounds: array of TCustomSoundEntry; - - - Loaded: boolean; - Loop: boolean; - public - Bass: hStream; - procedure InitializePlayback; - procedure InitializeRecord; - procedure SetVolume(Volume: integer); - procedure SetMusicVolume(Volume: integer); - procedure SetLoop(Enabled: boolean); - function Open(Name: string): boolean; // true if succeed - procedure Rewind; - procedure MoveTo(Time: real); - procedure Play; - procedure Pause; //Pause Mod - procedure Stop; - procedure Close; - function Finished: boolean; - function Length: real; - function Position: real; - procedure PlayStart; - procedure PlayBack; - procedure PlaySwoosh; - procedure PlayChange; - procedure PlayOption; - procedure PlayClick; - procedure PlayDrum; - procedure PlayHihat; - procedure PlayClap; - procedure PlayShuffle; - procedure StopShuffle; - procedure CaptureStart; - procedure CaptureStop; - procedure CaptureCard(RecordI, PlayerLeft, PlayerRight: byte); - procedure StopCard(Card: byte); - function LoadSoundFromFile(var hStream: hStream; Name: string): boolean; - - //Equalizer - function GetFFTData: TFFTData; - - //Custom Sounds - function LoadCustomSound(const Filename: String): Cardinal; - procedure PlayCustomSound(const Index: Cardinal); - -end; - -const - RecordSystem = 1; - -type - TMuzyka = record - Path: string; - Start: integer; // start of song in ms - IlNut: integer; - DlugoscNut: integer; - end; - - TCzesci = record - Akt: integer; // aktualna czesc utworu do rysowania - High: integer; - Ilosc: integer; - Resolution: integer; - NotesGAP: integer; - Wartosc: integer; - Czesc: array of 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; - 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; - -var - Music: TMusic; - - // muzyka - Muzyka: TMuzyka; - - // czesci z nutami; - Czesci: array of TCzesci; - - // czas - Czas: TCzas; - - fHWND: Thandle; - -type - TMPModes = (mpNotReady, mpStopped, mpPlaying, mpRecording, mpSeeking, - mpPaused, mpOpen); - -const - ModeStr: array[TMPModes] of string = ('Not ready', 'Stopped', 'Playing', 'Recording', 'Seeking', 'Paused', 'Open'); - -implementation - -uses - {$IFDEF FPC} - lclintf, - {$ENDIF} - UGraphic, - URecord, - UFiles, - UIni, - UMain, - UThemes; - -procedure InitializeSound; -begin - Log.LogStatus('Initializing Playback', 'InitializeSound'); Music.InitializePlayback; - Log.LogStatus('Initializing Record', 'InitializeSound'); Music.InitializeRecord; -end; - -procedure TMusic.InitializePlayback; -var - Pet: integer; - S: integer; -begin - Log.BenchmarkStart(4); - Log.LogStatus('Initializing Playback Subsystem', 'Music Initialize'); - - Loaded := false; - Loop := false; - - fHWND := AllocateHWND( nil); // TODO : JB_lazarus - can we do something different here ?? lazarus didnt like this function - - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - if not BASS_Init(1, 44100, 0, fHWND, nil) then - begin - {$IFNDEF FPC} - // TODO : JB_lazarus find a way to do this nice.. - Application.MessageBox ('Could not initialize BASS', 'Error'); - {$ENDIF} - Exit; - end; - {$ENDIF} - - Log.BenchmarkEnd(4); Log.LogBenchmark('--> Bass Init', 4); - - // config playing buffer -// BASS_SetConfig(BASS_CONFIG_UPDATEPERIOD, 10); -// BASS_SetConfig(BASS_CONFIG_BUFFER, 100); - - Log.LogStatus('Loading Sounds', 'Music Initialize'); - - Log.BenchmarkStart(4); - LoadSoundFromFile(BassStart, SoundPath + 'Common Start.mp3'); - LoadSoundFromFile(BassBack, SoundPath + 'Common Back.mp3'); - LoadSoundFromFile(BassSwoosh, SoundPath + 'menu swoosh.mp3'); - LoadSoundFromFile(BassChange, SoundPath + 'select music change music 50.mp3'); - LoadSoundFromFile(BassOption, SoundPath + 'option change col.mp3'); - LoadSoundFromFile(BassClick, SoundPath + 'rimshot022b.mp3'); - -// LoadSoundFromFile(BassDrum, SoundPath + 'bassdrumhard076b.mp3'); -// LoadSoundFromFile(BassHihat, SoundPath + 'hihatclosed068b.mp3'); -// LoadSoundFromFile(BassClap, SoundPath + 'claps050b.mp3'); - -// LoadSoundFromFile(BassShuffle, SoundPath + 'Shuffle.mp3'); - - Log.BenchmarkEnd(4); Log.LogBenchmark('--> Loading Sounds', 4); -end; - -procedure TMusic.InitializeRecord; -var - S: integer; - device: integer; - descr: string; - input: integer; - input2: integer; - flags: integer; - mic: array[0..15] of integer; - SC: integer; // soundcard - SCI: integer; // soundcard input -begin - if RecordSystem = 1 then 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; - - - // check for recording devices; - {device := 0; - descr := BASS_RecordGetDeviceDescription(device); - - SetLength(SoundCard, 0); - while (descr <> '') do begin - SC := High(SoundCard) + 1; - SetLength(SoundCard, SC+1); - - Log.LogAnalyze('Device #'+IntToStr(device)+': '+ descr); - SoundCard[SC].Description := Descr; - - // check for recording inputs - mic[device] := -1; // default to no change - input := 0; - BASS_RecordInit(device); - Log.LogAnalyze('Input #' + IntToStr(Input) + ': ' + BASS_RecordGetInputName(input)); - flags := BASS_RecordGetInput(input); - - SetLength(SoundCard[SC].Input, 0); - while (flags <> -1) do begin - SCI := High(SoundCard[SC].Input) + 1; - SetLength(SoundCard[SC].Input, SCI+1); - - Log.LogAnalyze('Input #' + IntToStr(Input) + ': ' + BASS_RecordGetInputName(input)); - SoundCard[SC].Input[SCI].Name := BASS_RecordGetInputName(Input); - - if (flags and BASS_INPUT_TYPE_MASK) = BASS_INPUT_TYPE_MIC then begin - mic[device] := input; // auto set microphone - end; - Inc(Input); - flags := BASS_RecordGetInput(input); - end; - - if mic[device] <> -1 then begin - Log.LogAnalyze('Found the mic at input ' + IntToStr(Mic[device])) - end else begin - Log.LogAnalyze('Mic not found'); - mic[device] := 0; // setting to the first one (for kxproject) - end; - SoundCard[SC].InputSeleceted := Mic[Device]; - - - BASS_RecordFree; - - inc(Device); - descr := BASS_RecordGetDeviceDescription(Device); - end; // while} - end; // if -end; - -procedure TMusic.SetVolume(Volume: integer); -begin - //Old Sets Wave Volume - //BASS_SetVolume(Volume); - //New: Sets Volume only for this Application - - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_SetConfig(BASS_CONFIG_GVOL_SAMPLE, Volume); - BASS_SetConfig(BASS_CONFIG_GVOL_STREAM, Volume); - BASS_SetConfig(BASS_CONFIG_GVOL_MUSIC, Volume); - {$ENDIF} -end; - -procedure TMusic.SetMusicVolume(Volume: Integer); -begin - //Max Volume Prevention - if Volume > 100 then - Volume := 100; - - //Set Volume - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_ChannelSetAttributes (Bass, -1, Volume, -101); - {$ENDIF} -end; - -procedure TMusic.SetLoop(Enabled: boolean); -begin - Loop := Enabled; -end; - -function TMusic.Open(Name: string): boolean; -begin - Loaded := false; - if FileExists(Name) then - begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - Bass := Bass_StreamCreateFile(false, pchar(Name), 0, 0, 0); - {$ENDIF} - - Loaded := true; - //Set Max Volume - SetMusicVolume (100); - end; - - Result := Loaded; -end; - -procedure TMusic.Rewind; -begin - if Loaded then begin - end; -end; - -procedure TMusic.MoveTo(Time: real); -var - bytes: integer; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - bytes := BASS_ChannelSeconds2Bytes(Bass, Time); - BASS_ChannelSetPosition(Bass, bytes); - {$ENDIF} -end; - -procedure TMusic.Play; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - if Loaded then - begin - if Loop then - BASS_ChannelPlay(Bass, True); // start from beginning... actually bass itself does not loop, nor does this TMusic Class - - BASS_ChannelPlay(Bass, False); // for setting position before playing - end; - {$ENDIF} -end; - -procedure TMusic.Pause; //Pause Mod -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - if Loaded then begin - BASS_ChannelPause(Bass); // Pauses Song - end; - {$ENDIF} -end; - -procedure TMusic.Stop; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - Bass_ChannelStop(Bass); - {$ENDIF} -end; - -procedure TMusic.Close; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - Bass_StreamFree(Bass); - {$ENDIF} -end; - -function TMusic.Length: real; -var - bytes: integer; -begin - Result := 60; - - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - bytes := BASS_ChannelGetLength(Bass); - Result := BASS_ChannelBytes2Seconds(Bass, bytes); - {$ENDIF} -end; - -function TMusic.Position: real; -var - bytes: integer; -begin - Result := 0; - - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - bytes := BASS_ChannelGetPosition(BASS); - Result := BASS_ChannelBytes2Seconds(BASS, bytes); - {$ENDIF} -end; - -function TMusic.Finished: boolean; -begin - Result := false; - - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - if BASS_ChannelIsActive(BASS) = BASS_ACTIVE_STOPPED then - begin - Result := true; - end; - {$ENDIF} -end; - -procedure TMusic.PlayStart; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_ChannelPlay(BassStart, True); - {$ENDIF} -end; - -procedure TMusic.PlayBack; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_ChannelPlay(BassBack, True);// then - {$ENDIF} -end; - -procedure TMusic.PlaySwoosh; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_ChannelPlay(BassSwoosh, True); - {$ENDIF} -end; - -procedure TMusic.PlayChange; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_ChannelPlay(BassChange, True); - {$ENDIF} -end; - -procedure TMusic.PlayOption; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_ChannelPlay(BassOption, True); - {$ENDIF} -end; - -procedure TMusic.PlayClick; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_ChannelPlay(BassClick, True); - {$ENDIF} -end; - -procedure TMusic.PlayDrum; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_ChannelPlay(BassDrum, True); - {$ENDIF} -end; - -procedure TMusic.PlayHihat; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_ChannelPlay(BassHihat, True); - {$ENDIF} -end; - -procedure TMusic.PlayClap; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_ChannelPlay(BassClap, True); - {$ENDIF} -end; - -procedure TMusic.PlayShuffle; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_ChannelPlay(BassShuffle, True); - {$ENDIF} -end; - -procedure TMusic.StopShuffle; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_ChannelStop(BassShuffle); - {$ENDIF} -end; - -procedure TMusic.CaptureStart; -var - S: integer; - SC: integer; - P1: integer; - P2: integer; -begin - for S := 0 to High(Sound) do - Sound[S].BufferLong[0].Clear; - - for SC := 0 to High(Ini.CardList) do begin - P1 := Ini.CardList[SC].ChannelL; - P2 := Ini.CardList[SC].ChannelR; - if P1 > PlayersPlay then P1 := 0; - if P2 > PlayersPlay then P2 := 0; - if (P1 > 0) or (P2 > 0) then - CaptureCard(SC, P1, P2); - end; -end; - -procedure TMusic.CaptureStop; -var - SC: integer; - P1: integer; - P2: integer; -begin - - for SC := 0 to High(Ini.CardList) do begin - P1 := Ini.CardList[SC].ChannelL; - P2 := Ini.CardList[SC].ChannelR; - if P1 > PlayersPlay then P1 := 0; - if P2 > PlayersPlay then P2 := 0; - if (P1 > 0) or (P2 > 0) then StopCard(SC); - end; - -end; - -//procedure TMusic.CaptureCard(RecordI, SoundNum, PlayerLeft, PlayerRight: byte); -procedure TMusic.CaptureCard(RecordI, PlayerLeft, PlayerRight: byte); -var - Error: integer; - ErrorMsg: string; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - - if not BASS_RecordInit(RecordI) 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.LogAnalyze('Error initializing record [' + IntToStr(RecordI) + ', ' - + IntToStr(PlayerLeft) + ', '+ IntToStr(PlayerRight) + ']: ' - + ErrorMsg);} - Log.LogError('Error initializing record [' + IntToStr(RecordI) + ', ' - + IntToStr(PlayerLeft) + ', '+ IntToStr(PlayerRight) + ']: ' - + ErrorMsg); - Log.LogError('Music -> CaptureCard: Error initializing record: ' + ErrorMsg); - - - end - else - begin - Recording.SoundCard[RecordI].BassRecordStream := BASS_RecordStart(44100, 2, MakeLong(0, 20) , @GetMicrophone, PlayerLeft + PlayerRight*256); - end; - - {$ENDIF} -end; - -procedure TMusic.StopCard(Card: byte); -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_RecordSetDevice(Card); - BASS_RecordFree; - {$ENDIF} -end; - -function TMusic.LoadSoundFromFile(var hStream: hStream; Name: string): boolean; -var - L: Integer; -begin - if FileExists(Name) then begin - Log.LogStatus('Loading Sound: "' + Name + '"', 'LoadSoundFromFile'); - try - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - hStream := BASS_StreamCreateFile(False, pchar(Name), 0, 0, 0); - {$ENDIF} - - //Add CustomSound - L := High(CustomSounds) + 1; - SetLength (CustomSounds, L + 1); - CustomSounds[L].Filename := Name; - CustomSounds[L].Handle := hStream; - except - Log.LogError('Failed to open using BASS', 'LoadSoundFromFile'); - end; - end else begin - Log.LogError('Sound not found: "' + Name + '"', 'LoadSoundFromFile'); - exit; - end; -end; - -//Equalizer -function TMusic.GetFFTData: TFFTData; -var -Data: TFFTData; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - - //Get Channel Data Mono and 256 Values - BASS_ChannelGetData(Bass, @Result, BASS_DATA_FFT512); - //Result := Data; - - {$ENDIF} -end; - -function TMusic.LoadCustomSound(const Filename: String): Cardinal; -var - S: hStream; - I: Integer; - F: String; -begin - //Search for Sound in already loaded Sounds - F := UpperCase(SoundPath + FileName); - For I := 0 to High(CustomSounds) do - begin - if (UpperCase(CustomSounds[I].Filename) = F) then - begin - Result := I; - Exit; - end; - end; - - if LoadSoundFromFile(S, SoundPath + Filename) then - Result := High(CustomSounds) - else - Result := 0; -end; - -procedure TMusic.PlayCustomSound(const Index: Cardinal); -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - - if Index <= High(CustomSounds) then - BASS_ChannelPlay(CustomSounds[Index].Handle, True); - - {$ENDIF} -end; - - -end. +unit UMusic; + +interface + +{$I switches.inc} + +{$IFDEF FPC} + {$MODE Delphi} +{$ENDIF} + + +uses Classes, + {$IFDEF win32} + windows, + {$ENDIF} + UCommon, + Messages, + SysUtils, + {$IFNDEF FPC} + Forms, + {$ENDIF} + {$IFDEF useBASS} + bass, + {$ENDIF} + ULog, + USongs; + + +procedure InitializeSound; + +type + TSoundCard = record + Name: string; + Source: array of string; + end; + + TFFTData = array [0..256] of Single; + + TCustomSoundEntry = record + Filename : String; + Handle : hStream; + end; + + + TMusic = class + private + BassStart: hStream; // Wait, I've replaced this with BASS + BassBack: hStream; // It has almost all features we need + BassSwoosh: hStream; + BassChange: hStream; // Almost? It aleady has them all :) + BassOption: hStream; + BassClick: hStream; + BassDrum: hStream; + BassHihat: hStream; + BassClap: hStream; + BassShuffle: hStream; + + //Custom Sounds + CustomSounds: array of TCustomSoundEntry; + + + Loaded: boolean; + Loop: boolean; + public + Bass: hStream; + procedure InitializePlayback; + procedure InitializeRecord; + procedure SetVolume(Volume: integer); + procedure SetMusicVolume(Volume: integer); + procedure SetLoop(Enabled: boolean); + function Open(Name: string): boolean; // true if succeed + procedure Rewind; + procedure MoveTo(Time: real); + procedure Play; + procedure Pause; //Pause Mod + procedure Stop; + procedure Close; + function Finished: boolean; + function Length: real; + function Position: real; + procedure PlayStart; + procedure PlayBack; + procedure PlaySwoosh; + procedure PlayChange; + procedure PlayOption; + procedure PlayClick; + procedure PlayDrum; + procedure PlayHihat; + procedure PlayClap; + procedure PlayShuffle; + procedure StopShuffle; + procedure CaptureStart; + procedure CaptureStop; + procedure CaptureCard(RecordI, PlayerLeft, PlayerRight: byte); + procedure StopCard(Card: byte); + function LoadSoundFromFile(var hStream: hStream; Name: string): boolean; + + //Equalizer + function GetFFTData: TFFTData; + + //Custom Sounds + function LoadCustomSound(const Filename: String): Cardinal; + procedure PlayCustomSound(const Index: Cardinal); + +end; + +const + RecordSystem = 1; + +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; + +var + Music: TMusic; + + // muzyka + Muzyka: TMuzyka; + + // czesci z nutami; + Czesci: array of TCzesci; + + // czas + Czas: TCzas; + + fHWND: Thandle; + +type + TMPModes = (mpNotReady, mpStopped, mpPlaying, mpRecording, mpSeeking, + mpPaused, mpOpen); + +const + ModeStr: array[TMPModes] of string = ('Not ready', 'Stopped', 'Playing', 'Recording', 'Seeking', 'Paused', 'Open'); + +implementation + +uses + {$IFDEF FPC} + lclintf, + {$ENDIF} + UGraphic, + URecord, + UFiles, + UIni, + UMain, + UThemes; + +procedure InitializeSound; +begin + Log.LogStatus('Initializing Playback', 'InitializeSound'); Music.InitializePlayback; + Log.LogStatus('Initializing Record', 'InitializeSound'); Music.InitializeRecord; +end; + +procedure TMusic.InitializePlayback; +var + Pet: integer; + S: integer; +begin + Log.BenchmarkStart(4); + Log.LogStatus('Initializing Playback Subsystem', 'Music Initialize'); + + Loaded := false; + Loop := false; + + fHWND := AllocateHWND( nil); // TODO : JB_lazarus - can we do something different here ?? lazarus didnt like this function + + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + if not BASS_Init(1, 44100, 0, fHWND, nil) then + begin + {$IFNDEF FPC} + // TODO : JB_lazarus find a way to do this nice.. + Application.MessageBox ('Could not initialize BASS', 'Error'); + {$ENDIF} + Exit; + end; + {$ENDIF} + + Log.BenchmarkEnd(4); Log.LogBenchmark('--> Bass Init', 4); + + // config playing buffer +// BASS_SetConfig(BASS_CONFIG_UPDATEPERIOD, 10); +// BASS_SetConfig(BASS_CONFIG_BUFFER, 100); + + Log.LogStatus('Loading Sounds', 'Music Initialize'); + + Log.BenchmarkStart(4); + LoadSoundFromFile(BassStart, SoundPath + 'Common Start.mp3'); + LoadSoundFromFile(BassBack, SoundPath + 'Common Back.mp3'); + LoadSoundFromFile(BassSwoosh, SoundPath + 'menu swoosh.mp3'); + LoadSoundFromFile(BassChange, SoundPath + 'select music change music 50.mp3'); + LoadSoundFromFile(BassOption, SoundPath + 'option change col.mp3'); + LoadSoundFromFile(BassClick, SoundPath + 'rimshot022b.mp3'); + +// LoadSoundFromFile(BassDrum, SoundPath + 'bassdrumhard076b.mp3'); +// LoadSoundFromFile(BassHihat, SoundPath + 'hihatclosed068b.mp3'); +// LoadSoundFromFile(BassClap, SoundPath + 'claps050b.mp3'); + +// LoadSoundFromFile(BassShuffle, SoundPath + 'Shuffle.mp3'); + + Log.BenchmarkEnd(4); Log.LogBenchmark('--> Loading Sounds', 4); +end; + +procedure TMusic.InitializeRecord; +var + S: integer; + device: integer; + descr: string; + input: integer; + input2: integer; + flags: integer; + mic: array[0..15] of integer; + SC: integer; // soundcard + SCI: integer; // soundcard input +begin + if RecordSystem = 1 then 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; + + + // check for recording devices; + {device := 0; + descr := BASS_RecordGetDeviceDescription(device); + + SetLength(SoundCard, 0); + while (descr <> '') do begin + SC := High(SoundCard) + 1; + SetLength(SoundCard, SC+1); + + Log.LogAnalyze('Device #'+IntToStr(device)+': '+ descr); + SoundCard[SC].Description := Descr; + + // check for recording inputs + mic[device] := -1; // default to no change + input := 0; + BASS_RecordInit(device); + Log.LogAnalyze('Input #' + IntToStr(Input) + ': ' + BASS_RecordGetInputName(input)); + flags := BASS_RecordGetInput(input); + + SetLength(SoundCard[SC].Input, 0); + while (flags <> -1) do begin + SCI := High(SoundCard[SC].Input) + 1; + SetLength(SoundCard[SC].Input, SCI+1); + + Log.LogAnalyze('Input #' + IntToStr(Input) + ': ' + BASS_RecordGetInputName(input)); + SoundCard[SC].Input[SCI].Name := BASS_RecordGetInputName(Input); + + if (flags and BASS_INPUT_TYPE_MASK) = BASS_INPUT_TYPE_MIC then begin + mic[device] := input; // auto set microphone + end; + Inc(Input); + flags := BASS_RecordGetInput(input); + end; + + if mic[device] <> -1 then begin + Log.LogAnalyze('Found the mic at input ' + IntToStr(Mic[device])) + end else begin + Log.LogAnalyze('Mic not found'); + mic[device] := 0; // setting to the first one (for kxproject) + end; + SoundCard[SC].InputSeleceted := Mic[Device]; + + + BASS_RecordFree; + + inc(Device); + descr := BASS_RecordGetDeviceDescription(Device); + end; // while} + end; // if +end; + +procedure TMusic.SetVolume(Volume: integer); +begin + //Old Sets Wave Volume + //BASS_SetVolume(Volume); + //New: Sets Volume only for this Application + + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_SetConfig(BASS_CONFIG_GVOL_SAMPLE, Volume); + BASS_SetConfig(BASS_CONFIG_GVOL_STREAM, Volume); + BASS_SetConfig(BASS_CONFIG_GVOL_MUSIC, Volume); + {$ENDIF} +end; + +procedure TMusic.SetMusicVolume(Volume: Integer); +begin + //Max Volume Prevention + if Volume > 100 then + Volume := 100; + + //Set Volume + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_ChannelSetAttributes (Bass, -1, Volume, -101); + {$ENDIF} +end; + +procedure TMusic.SetLoop(Enabled: boolean); +begin + Loop := Enabled; +end; + +function TMusic.Open(Name: string): boolean; +begin + Loaded := false; + if FileExists(Name) then + begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + Bass := Bass_StreamCreateFile(false, pchar(Name), 0, 0, 0); + {$ENDIF} + + Loaded := true; + //Set Max Volume + SetMusicVolume (100); + end; + + Result := Loaded; +end; + +procedure TMusic.Rewind; +begin + if Loaded then begin + end; +end; + +procedure TMusic.MoveTo(Time: real); +var + bytes: integer; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + bytes := BASS_ChannelSeconds2Bytes(Bass, Time); + BASS_ChannelSetPosition(Bass, bytes); + {$ENDIF} +end; + +procedure TMusic.Play; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + if Loaded then + begin + if Loop then + BASS_ChannelPlay(Bass, True); // start from beginning... actually bass itself does not loop, nor does this TMusic Class + + BASS_ChannelPlay(Bass, False); // for setting position before playing + end; + {$ENDIF} +end; + +procedure TMusic.Pause; //Pause Mod +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + if Loaded then begin + BASS_ChannelPause(Bass); // Pauses Song + end; + {$ENDIF} +end; + +procedure TMusic.Stop; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + Bass_ChannelStop(Bass); + {$ENDIF} +end; + +procedure TMusic.Close; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + Bass_StreamFree(Bass); + {$ENDIF} +end; + +function TMusic.Length: real; +var + bytes: integer; +begin + Result := 60; + + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + bytes := BASS_ChannelGetLength(Bass); + Result := BASS_ChannelBytes2Seconds(Bass, bytes); + {$ENDIF} +end; + +function TMusic.Position: real; +var + bytes: integer; +begin + Result := 0; + + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + bytes := BASS_ChannelGetPosition(BASS); + Result := BASS_ChannelBytes2Seconds(BASS, bytes); + {$ENDIF} +end; + +function TMusic.Finished: boolean; +begin + Result := false; + + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + if BASS_ChannelIsActive(BASS) = BASS_ACTIVE_STOPPED then + begin + Result := true; + end; + {$ENDIF} +end; + +procedure TMusic.PlayStart; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_ChannelPlay(BassStart, True); + {$ENDIF} +end; + +procedure TMusic.PlayBack; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_ChannelPlay(BassBack, True);// then + {$ENDIF} +end; + +procedure TMusic.PlaySwoosh; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_ChannelPlay(BassSwoosh, True); + {$ENDIF} +end; + +procedure TMusic.PlayChange; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_ChannelPlay(BassChange, True); + {$ENDIF} +end; + +procedure TMusic.PlayOption; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_ChannelPlay(BassOption, True); + {$ENDIF} +end; + +procedure TMusic.PlayClick; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_ChannelPlay(BassClick, True); + {$ENDIF} +end; + +procedure TMusic.PlayDrum; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_ChannelPlay(BassDrum, True); + {$ENDIF} +end; + +procedure TMusic.PlayHihat; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_ChannelPlay(BassHihat, True); + {$ENDIF} +end; + +procedure TMusic.PlayClap; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_ChannelPlay(BassClap, True); + {$ENDIF} +end; + +procedure TMusic.PlayShuffle; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_ChannelPlay(BassShuffle, True); + {$ENDIF} +end; + +procedure TMusic.StopShuffle; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_ChannelStop(BassShuffle); + {$ENDIF} +end; + +procedure TMusic.CaptureStart; +var + S: integer; + SC: integer; + P1: integer; + P2: integer; +begin + for S := 0 to High(Sound) do + Sound[S].BufferLong[0].Clear; + + for SC := 0 to High(Ini.CardList) do begin + P1 := Ini.CardList[SC].ChannelL; + P2 := Ini.CardList[SC].ChannelR; + if P1 > PlayersPlay then P1 := 0; + if P2 > PlayersPlay then P2 := 0; + if (P1 > 0) or (P2 > 0) then + CaptureCard(SC, P1, P2); + end; +end; + +procedure TMusic.CaptureStop; +var + SC: integer; + P1: integer; + P2: integer; +begin + + for SC := 0 to High(Ini.CardList) do begin + P1 := Ini.CardList[SC].ChannelL; + P2 := Ini.CardList[SC].ChannelR; + if P1 > PlayersPlay then P1 := 0; + if P2 > PlayersPlay then P2 := 0; + if (P1 > 0) or (P2 > 0) then StopCard(SC); + end; + +end; + +//procedure TMusic.CaptureCard(RecordI, SoundNum, PlayerLeft, PlayerRight: byte); +procedure TMusic.CaptureCard(RecordI, PlayerLeft, PlayerRight: byte); +var + Error: integer; + ErrorMsg: string; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + + if not BASS_RecordInit(RecordI) 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.LogAnalyze('Error initializing record [' + IntToStr(RecordI) + ', ' + + IntToStr(PlayerLeft) + ', '+ IntToStr(PlayerRight) + ']: ' + + ErrorMsg);} + Log.LogError('Error initializing record [' + IntToStr(RecordI) + ', ' + + IntToStr(PlayerLeft) + ', '+ IntToStr(PlayerRight) + ']: ' + + ErrorMsg); + Log.LogError('Music -> CaptureCard: Error initializing record: ' + ErrorMsg); + + + end + else + begin + Recording.SoundCard[RecordI].BassRecordStream := BASS_RecordStart(44100, 2, MakeLong(0, 20) , @GetMicrophone, PlayerLeft + PlayerRight*256); + end; + + {$ENDIF} +end; + +procedure TMusic.StopCard(Card: byte); +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_RecordSetDevice(Card); + BASS_RecordFree; + {$ENDIF} +end; + +function TMusic.LoadSoundFromFile(var hStream: hStream; Name: string): boolean; +var + L: Integer; +begin + if FileExists(Name) then begin + Log.LogStatus('Loading Sound: "' + Name + '"', 'LoadSoundFromFile'); + try + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + hStream := BASS_StreamCreateFile(False, pchar(Name), 0, 0, 0); + {$ENDIF} + + //Add CustomSound + L := High(CustomSounds) + 1; + SetLength (CustomSounds, L + 1); + CustomSounds[L].Filename := Name; + CustomSounds[L].Handle := hStream; + except + Log.LogError('Failed to open using BASS', 'LoadSoundFromFile'); + end; + end else begin + Log.LogError('Sound not found: "' + Name + '"', 'LoadSoundFromFile'); + exit; + end; +end; + +//Equalizer +function TMusic.GetFFTData: TFFTData; +var +Data: TFFTData; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + + //Get Channel Data Mono and 256 Values + BASS_ChannelGetData(Bass, @Result, BASS_DATA_FFT512); + //Result := Data; + + {$ENDIF} +end; + +function TMusic.LoadCustomSound(const Filename: String): Cardinal; +var + S: hStream; + I: Integer; + F: String; +begin + //Search for Sound in already loaded Sounds + F := UpperCase(SoundPath + FileName); + For I := 0 to High(CustomSounds) do + begin + if (UpperCase(CustomSounds[I].Filename) = F) then + begin + Result := I; + Exit; + end; + end; + + if LoadSoundFromFile(S, SoundPath + Filename) then + Result := High(CustomSounds) + else + Result := 0; +end; + +procedure TMusic.PlayCustomSound(const Index: Cardinal); +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + + if Index <= High(CustomSounds) then + BASS_ChannelPlay(CustomSounds[Index].Handle, True); + + {$ENDIF} +end; + + +end. -- cgit v1.2.3 From 95662b4cb8252ae665de8222762f9fc320f11ea0 Mon Sep 17 00:00:00 2001 From: jaybinks Date: Sat, 29 Sep 2007 01:47:49 +0000 Subject: small fixes for lazarus build. cleanup on some code. git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@445 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UMusic.pas | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Game/Code/Classes/UMusic.pas') diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas index b9ed47b4..b9f93b29 100644 --- a/Game/Code/Classes/UMusic.pas +++ b/Game/Code/Classes/UMusic.pas @@ -233,7 +233,7 @@ begin if not BASS_Init(1, 44100, 0, fHWND, nil) then begin {$IFNDEF FPC} - // TODO : JB_lazarus find a way to do this nice.. + // TODO : JB_linux find a way to do this nice.. Application.MessageBox ('Could not initialize BASS', 'Error'); {$ENDIF} Exit; -- cgit v1.2.3 From b29759fbfdd8a013e3d0a85b578934ebec028c41 Mon Sep 17 00:00:00 2001 From: jaybinks Date: Tue, 2 Oct 2007 04:39:22 +0000 Subject: Fixed linux compilation. Linux is now running in the main loop fine. * no audio playback or input yet... * Timing hack inplace.. that must be replace * bunch of textures not working.. however the play screen is looking similar to windows builds. I hope this dosnt break windows builds to much. git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@460 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UMusic.pas | 1473 +++++++++++++++++++++--------------------- 1 file changed, 738 insertions(+), 735 deletions(-) (limited to 'Game/Code/Classes/UMusic.pas') diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas index b9f93b29..b3729e69 100644 --- a/Game/Code/Classes/UMusic.pas +++ b/Game/Code/Classes/UMusic.pas @@ -1,735 +1,738 @@ -unit UMusic; - -interface - -{$I switches.inc} - -{$IFDEF FPC} - {$MODE Delphi} -{$ENDIF} - - -uses Classes, - {$IFDEF win32} - windows, - {$ENDIF} - UCommon, - Messages, - SysUtils, - {$IFNDEF FPC} - Forms, - {$ENDIF} - {$IFDEF useBASS} - bass, - {$ENDIF} - ULog, - USongs; - - -procedure InitializeSound; - -type - TSoundCard = record - Name: string; - Source: array of string; - end; - - TFFTData = array [0..256] of Single; - - TCustomSoundEntry = record - Filename : String; - Handle : hStream; - end; - - - TMusic = class - private - BassStart: hStream; // Wait, I've replaced this with BASS - BassBack: hStream; // It has almost all features we need - BassSwoosh: hStream; - BassChange: hStream; // Almost? It aleady has them all :) - BassOption: hStream; - BassClick: hStream; - BassDrum: hStream; - BassHihat: hStream; - BassClap: hStream; - BassShuffle: hStream; - - //Custom Sounds - CustomSounds: array of TCustomSoundEntry; - - - Loaded: boolean; - Loop: boolean; - public - Bass: hStream; - procedure InitializePlayback; - procedure InitializeRecord; - procedure SetVolume(Volume: integer); - procedure SetMusicVolume(Volume: integer); - procedure SetLoop(Enabled: boolean); - function Open(Name: string): boolean; // true if succeed - procedure Rewind; - procedure MoveTo(Time: real); - procedure Play; - procedure Pause; //Pause Mod - procedure Stop; - procedure Close; - function Finished: boolean; - function Length: real; - function Position: real; - procedure PlayStart; - procedure PlayBack; - procedure PlaySwoosh; - procedure PlayChange; - procedure PlayOption; - procedure PlayClick; - procedure PlayDrum; - procedure PlayHihat; - procedure PlayClap; - procedure PlayShuffle; - procedure StopShuffle; - procedure CaptureStart; - procedure CaptureStop; - procedure CaptureCard(RecordI, PlayerLeft, PlayerRight: byte); - procedure StopCard(Card: byte); - function LoadSoundFromFile(var hStream: hStream; Name: string): boolean; - - //Equalizer - function GetFFTData: TFFTData; - - //Custom Sounds - function LoadCustomSound(const Filename: String): Cardinal; - procedure PlayCustomSound(const Index: Cardinal); - -end; - -const - RecordSystem = 1; - -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; - -var - Music: TMusic; - - // muzyka - Muzyka: TMuzyka; - - // czesci z nutami; - Czesci: array of TCzesci; - - // czas - Czas: TCzas; - - fHWND: Thandle; - -type - TMPModes = (mpNotReady, mpStopped, mpPlaying, mpRecording, mpSeeking, - mpPaused, mpOpen); - -const - ModeStr: array[TMPModes] of string = ('Not ready', 'Stopped', 'Playing', 'Recording', 'Seeking', 'Paused', 'Open'); - -implementation - -uses - {$IFDEF FPC} - lclintf, - {$ENDIF} - UGraphic, - URecord, - UFiles, - UIni, - UMain, - UThemes; - -procedure InitializeSound; -begin - Log.LogStatus('Initializing Playback', 'InitializeSound'); Music.InitializePlayback; - Log.LogStatus('Initializing Record', 'InitializeSound'); Music.InitializeRecord; -end; - -procedure TMusic.InitializePlayback; -var - Pet: integer; - S: integer; -begin - Log.BenchmarkStart(4); - Log.LogStatus('Initializing Playback Subsystem', 'Music Initialize'); - - Loaded := false; - Loop := false; - - fHWND := AllocateHWND( nil); // TODO : JB_lazarus - can we do something different here ?? lazarus didnt like this function - - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - if not BASS_Init(1, 44100, 0, fHWND, nil) then - begin - {$IFNDEF FPC} - // TODO : JB_linux find a way to do this nice.. - Application.MessageBox ('Could not initialize BASS', 'Error'); - {$ENDIF} - Exit; - end; - {$ENDIF} - - Log.BenchmarkEnd(4); Log.LogBenchmark('--> Bass Init', 4); - - // config playing buffer -// BASS_SetConfig(BASS_CONFIG_UPDATEPERIOD, 10); -// BASS_SetConfig(BASS_CONFIG_BUFFER, 100); - - Log.LogStatus('Loading Sounds', 'Music Initialize'); - - Log.BenchmarkStart(4); - LoadSoundFromFile(BassStart, SoundPath + 'Common Start.mp3'); - LoadSoundFromFile(BassBack, SoundPath + 'Common Back.mp3'); - LoadSoundFromFile(BassSwoosh, SoundPath + 'menu swoosh.mp3'); - LoadSoundFromFile(BassChange, SoundPath + 'select music change music 50.mp3'); - LoadSoundFromFile(BassOption, SoundPath + 'option change col.mp3'); - LoadSoundFromFile(BassClick, SoundPath + 'rimshot022b.mp3'); - -// LoadSoundFromFile(BassDrum, SoundPath + 'bassdrumhard076b.mp3'); -// LoadSoundFromFile(BassHihat, SoundPath + 'hihatclosed068b.mp3'); -// LoadSoundFromFile(BassClap, SoundPath + 'claps050b.mp3'); - -// LoadSoundFromFile(BassShuffle, SoundPath + 'Shuffle.mp3'); - - Log.BenchmarkEnd(4); Log.LogBenchmark('--> Loading Sounds', 4); -end; - -procedure TMusic.InitializeRecord; -var - S: integer; - device: integer; - descr: string; - input: integer; - input2: integer; - flags: integer; - mic: array[0..15] of integer; - SC: integer; // soundcard - SCI: integer; // soundcard input -begin - if RecordSystem = 1 then 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; - - - // check for recording devices; - {device := 0; - descr := BASS_RecordGetDeviceDescription(device); - - SetLength(SoundCard, 0); - while (descr <> '') do begin - SC := High(SoundCard) + 1; - SetLength(SoundCard, SC+1); - - Log.LogAnalyze('Device #'+IntToStr(device)+': '+ descr); - SoundCard[SC].Description := Descr; - - // check for recording inputs - mic[device] := -1; // default to no change - input := 0; - BASS_RecordInit(device); - Log.LogAnalyze('Input #' + IntToStr(Input) + ': ' + BASS_RecordGetInputName(input)); - flags := BASS_RecordGetInput(input); - - SetLength(SoundCard[SC].Input, 0); - while (flags <> -1) do begin - SCI := High(SoundCard[SC].Input) + 1; - SetLength(SoundCard[SC].Input, SCI+1); - - Log.LogAnalyze('Input #' + IntToStr(Input) + ': ' + BASS_RecordGetInputName(input)); - SoundCard[SC].Input[SCI].Name := BASS_RecordGetInputName(Input); - - if (flags and BASS_INPUT_TYPE_MASK) = BASS_INPUT_TYPE_MIC then begin - mic[device] := input; // auto set microphone - end; - Inc(Input); - flags := BASS_RecordGetInput(input); - end; - - if mic[device] <> -1 then begin - Log.LogAnalyze('Found the mic at input ' + IntToStr(Mic[device])) - end else begin - Log.LogAnalyze('Mic not found'); - mic[device] := 0; // setting to the first one (for kxproject) - end; - SoundCard[SC].InputSeleceted := Mic[Device]; - - - BASS_RecordFree; - - inc(Device); - descr := BASS_RecordGetDeviceDescription(Device); - end; // while} - end; // if -end; - -procedure TMusic.SetVolume(Volume: integer); -begin - //Old Sets Wave Volume - //BASS_SetVolume(Volume); - //New: Sets Volume only for this Application - - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_SetConfig(BASS_CONFIG_GVOL_SAMPLE, Volume); - BASS_SetConfig(BASS_CONFIG_GVOL_STREAM, Volume); - BASS_SetConfig(BASS_CONFIG_GVOL_MUSIC, Volume); - {$ENDIF} -end; - -procedure TMusic.SetMusicVolume(Volume: Integer); -begin - //Max Volume Prevention - if Volume > 100 then - Volume := 100; - - //Set Volume - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_ChannelSetAttributes (Bass, -1, Volume, -101); - {$ENDIF} -end; - -procedure TMusic.SetLoop(Enabled: boolean); -begin - Loop := Enabled; -end; - -function TMusic.Open(Name: string): boolean; -begin - Loaded := false; - if FileExists(Name) then - begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - Bass := Bass_StreamCreateFile(false, pchar(Name), 0, 0, 0); - {$ENDIF} - - Loaded := true; - //Set Max Volume - SetMusicVolume (100); - end; - - Result := Loaded; -end; - -procedure TMusic.Rewind; -begin - if Loaded then begin - end; -end; - -procedure TMusic.MoveTo(Time: real); -var - bytes: integer; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - bytes := BASS_ChannelSeconds2Bytes(Bass, Time); - BASS_ChannelSetPosition(Bass, bytes); - {$ENDIF} -end; - -procedure TMusic.Play; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - if Loaded then - begin - if Loop then - BASS_ChannelPlay(Bass, True); // start from beginning... actually bass itself does not loop, nor does this TMusic Class - - BASS_ChannelPlay(Bass, False); // for setting position before playing - end; - {$ENDIF} -end; - -procedure TMusic.Pause; //Pause Mod -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - if Loaded then begin - BASS_ChannelPause(Bass); // Pauses Song - end; - {$ENDIF} -end; - -procedure TMusic.Stop; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - Bass_ChannelStop(Bass); - {$ENDIF} -end; - -procedure TMusic.Close; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - Bass_StreamFree(Bass); - {$ENDIF} -end; - -function TMusic.Length: real; -var - bytes: integer; -begin - Result := 60; - - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - bytes := BASS_ChannelGetLength(Bass); - Result := BASS_ChannelBytes2Seconds(Bass, bytes); - {$ENDIF} -end; - -function TMusic.Position: real; -var - bytes: integer; -begin - Result := 0; - - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - bytes := BASS_ChannelGetPosition(BASS); - Result := BASS_ChannelBytes2Seconds(BASS, bytes); - {$ENDIF} -end; - -function TMusic.Finished: boolean; -begin - Result := false; - - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - if BASS_ChannelIsActive(BASS) = BASS_ACTIVE_STOPPED then - begin - Result := true; - end; - {$ENDIF} -end; - -procedure TMusic.PlayStart; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_ChannelPlay(BassStart, True); - {$ENDIF} -end; - -procedure TMusic.PlayBack; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_ChannelPlay(BassBack, True);// then - {$ENDIF} -end; - -procedure TMusic.PlaySwoosh; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_ChannelPlay(BassSwoosh, True); - {$ENDIF} -end; - -procedure TMusic.PlayChange; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_ChannelPlay(BassChange, True); - {$ENDIF} -end; - -procedure TMusic.PlayOption; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_ChannelPlay(BassOption, True); - {$ENDIF} -end; - -procedure TMusic.PlayClick; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_ChannelPlay(BassClick, True); - {$ENDIF} -end; - -procedure TMusic.PlayDrum; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_ChannelPlay(BassDrum, True); - {$ENDIF} -end; - -procedure TMusic.PlayHihat; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_ChannelPlay(BassHihat, True); - {$ENDIF} -end; - -procedure TMusic.PlayClap; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_ChannelPlay(BassClap, True); - {$ENDIF} -end; - -procedure TMusic.PlayShuffle; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_ChannelPlay(BassShuffle, True); - {$ENDIF} -end; - -procedure TMusic.StopShuffle; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_ChannelStop(BassShuffle); - {$ENDIF} -end; - -procedure TMusic.CaptureStart; -var - S: integer; - SC: integer; - P1: integer; - P2: integer; -begin - for S := 0 to High(Sound) do - Sound[S].BufferLong[0].Clear; - - for SC := 0 to High(Ini.CardList) do begin - P1 := Ini.CardList[SC].ChannelL; - P2 := Ini.CardList[SC].ChannelR; - if P1 > PlayersPlay then P1 := 0; - if P2 > PlayersPlay then P2 := 0; - if (P1 > 0) or (P2 > 0) then - CaptureCard(SC, P1, P2); - end; -end; - -procedure TMusic.CaptureStop; -var - SC: integer; - P1: integer; - P2: integer; -begin - - for SC := 0 to High(Ini.CardList) do begin - P1 := Ini.CardList[SC].ChannelL; - P2 := Ini.CardList[SC].ChannelR; - if P1 > PlayersPlay then P1 := 0; - if P2 > PlayersPlay then P2 := 0; - if (P1 > 0) or (P2 > 0) then StopCard(SC); - end; - -end; - -//procedure TMusic.CaptureCard(RecordI, SoundNum, PlayerLeft, PlayerRight: byte); -procedure TMusic.CaptureCard(RecordI, PlayerLeft, PlayerRight: byte); -var - Error: integer; - ErrorMsg: string; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - - if not BASS_RecordInit(RecordI) 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.LogAnalyze('Error initializing record [' + IntToStr(RecordI) + ', ' - + IntToStr(PlayerLeft) + ', '+ IntToStr(PlayerRight) + ']: ' - + ErrorMsg);} - Log.LogError('Error initializing record [' + IntToStr(RecordI) + ', ' - + IntToStr(PlayerLeft) + ', '+ IntToStr(PlayerRight) + ']: ' - + ErrorMsg); - Log.LogError('Music -> CaptureCard: Error initializing record: ' + ErrorMsg); - - - end - else - begin - Recording.SoundCard[RecordI].BassRecordStream := BASS_RecordStart(44100, 2, MakeLong(0, 20) , @GetMicrophone, PlayerLeft + PlayerRight*256); - end; - - {$ENDIF} -end; - -procedure TMusic.StopCard(Card: byte); -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_RecordSetDevice(Card); - BASS_RecordFree; - {$ENDIF} -end; - -function TMusic.LoadSoundFromFile(var hStream: hStream; Name: string): boolean; -var - L: Integer; -begin - if FileExists(Name) then begin - Log.LogStatus('Loading Sound: "' + Name + '"', 'LoadSoundFromFile'); - try - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - hStream := BASS_StreamCreateFile(False, pchar(Name), 0, 0, 0); - {$ENDIF} - - //Add CustomSound - L := High(CustomSounds) + 1; - SetLength (CustomSounds, L + 1); - CustomSounds[L].Filename := Name; - CustomSounds[L].Handle := hStream; - except - Log.LogError('Failed to open using BASS', 'LoadSoundFromFile'); - end; - end else begin - Log.LogError('Sound not found: "' + Name + '"', 'LoadSoundFromFile'); - exit; - end; -end; - -//Equalizer -function TMusic.GetFFTData: TFFTData; -var -Data: TFFTData; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - - //Get Channel Data Mono and 256 Values - BASS_ChannelGetData(Bass, @Result, BASS_DATA_FFT512); - //Result := Data; - - {$ENDIF} -end; - -function TMusic.LoadCustomSound(const Filename: String): Cardinal; -var - S: hStream; - I: Integer; - F: String; -begin - //Search for Sound in already loaded Sounds - F := UpperCase(SoundPath + FileName); - For I := 0 to High(CustomSounds) do - begin - if (UpperCase(CustomSounds[I].Filename) = F) then - begin - Result := I; - Exit; - end; - end; - - if LoadSoundFromFile(S, SoundPath + Filename) then - Result := High(CustomSounds) - else - Result := 0; -end; - -procedure TMusic.PlayCustomSound(const Index: Cardinal); -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - - if Index <= High(CustomSounds) then - BASS_ChannelPlay(CustomSounds[Index].Handle, True); - - {$ENDIF} -end; - - -end. +unit UMusic; + +interface + +{$I switches.inc} + +{$IFDEF FPC} + {$MODE Delphi} +{$ENDIF} + + +uses Classes, + {$IFDEF win32} + windows, + {$ENDIF} + UCommon, + Messages, + SysUtils, + {$IFNDEF FPC} + Forms, + {$ENDIF} + {$IFDEF useBASS} + bass, + {$ENDIF} + ULog, + USongs; + + +procedure InitializeSound; + +type + TSoundCard = record + Name: string; + Source: array of string; + end; + + TFFTData = array [0..256] of Single; + + TCustomSoundEntry = record + Filename : String; + Handle : hStream; + end; + + + TMusic = class + private + BassStart: hStream; // Wait, I've replaced this with BASS + BassBack: hStream; // It has almost all features we need + BassSwoosh: hStream; + BassChange: hStream; // Almost? It aleady has them all :) + BassOption: hStream; + BassClick: hStream; + BassDrum: hStream; + BassHihat: hStream; + BassClap: hStream; + BassShuffle: hStream; + + //Custom Sounds + CustomSounds: array of TCustomSoundEntry; + + + Loaded: boolean; + Loop: boolean; + public + Bass: hStream; + procedure InitializePlayback; + procedure InitializeRecord; + procedure SetVolume(Volume: integer); + procedure SetMusicVolume(Volume: integer); + procedure SetLoop(Enabled: boolean); + function Open(Name: string): boolean; // true if succeed + procedure Rewind; + procedure MoveTo(Time: real); + procedure Play; + procedure Pause; //Pause Mod + procedure Stop; + procedure Close; + function Finished: boolean; + function Length: real; + function Position: real; + procedure PlayStart; + procedure PlayBack; + procedure PlaySwoosh; + procedure PlayChange; + procedure PlayOption; + procedure PlayClick; + procedure PlayDrum; + procedure PlayHihat; + procedure PlayClap; + procedure PlayShuffle; + procedure StopShuffle; + procedure CaptureStart; + procedure CaptureStop; + procedure CaptureCard(RecordI, PlayerLeft, PlayerRight: byte); + procedure StopCard(Card: byte); + function LoadSoundFromFile(var hStream: hStream; Name: string): boolean; + + //Equalizer + function GetFFTData: TFFTData; + + //Custom Sounds + function LoadCustomSound(const Filename: String): Cardinal; + procedure PlayCustomSound(const Index: Cardinal); + +end; + +const + RecordSystem = 1; + +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; + +var + Music: TMusic; + + // muzyka + Muzyka: TMuzyka; + + // czesci z nutami; + Czesci: array of TCzesci; + + // czas + Czas: TCzas; + + fHWND: Thandle; + +type + TMPModes = (mpNotReady, mpStopped, mpPlaying, mpRecording, mpSeeking, + mpPaused, mpOpen); + +const + ModeStr: array[TMPModes] of string = ('Not ready', 'Stopped', 'Playing', 'Recording', 'Seeking', 'Paused', 'Open'); + +implementation + +uses + {$IFDEF FPC} + lclintf, + {$ENDIF} + UGraphic, + URecord, + UFiles, + UIni, + UMain, + UThemes; + +procedure InitializeSound; +begin + Log.LogStatus('Initializing Playback', 'InitializeSound'); Music.InitializePlayback; + Log.LogStatus('Initializing Record', 'InitializeSound'); Music.InitializeRecord; +end; + +procedure TMusic.InitializePlayback; +var + Pet: integer; + S: integer; +begin + Log.BenchmarkStart(4); + Log.LogStatus('Initializing Playback Subsystem', 'Music Initialize'); + + Loaded := false; + Loop := false; + + {$ifdef win32} + // TODO : JB_Linux ... is this needed ? :) + fHWND := AllocateHWND( nil); // TODO : JB_lazarus - can we do something different here ?? lazarus didnt like this function + {$ENDIF} + + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + if not BASS_Init(1, 44100, 0, fHWND, nil) then + begin + {$IFNDEF FPC} + // TODO : JB_linux find a way to do this nice.. + Application.MessageBox ('Could not initialize BASS', 'Error'); + {$ENDIF} + Exit; + end; + {$ENDIF} + + Log.BenchmarkEnd(4); Log.LogBenchmark('--> Bass Init', 4); + + // config playing buffer +// BASS_SetConfig(BASS_CONFIG_UPDATEPERIOD, 10); +// BASS_SetConfig(BASS_CONFIG_BUFFER, 100); + + Log.LogStatus('Loading Sounds', 'Music Initialize'); + + Log.BenchmarkStart(4); + LoadSoundFromFile(BassStart, SoundPath + 'Common Start.mp3'); + LoadSoundFromFile(BassBack, SoundPath + 'Common Back.mp3'); + LoadSoundFromFile(BassSwoosh, SoundPath + 'menu swoosh.mp3'); + LoadSoundFromFile(BassChange, SoundPath + 'select music change music 50.mp3'); + LoadSoundFromFile(BassOption, SoundPath + 'option change col.mp3'); + LoadSoundFromFile(BassClick, SoundPath + 'rimshot022b.mp3'); + +// LoadSoundFromFile(BassDrum, SoundPath + 'bassdrumhard076b.mp3'); +// LoadSoundFromFile(BassHihat, SoundPath + 'hihatclosed068b.mp3'); +// LoadSoundFromFile(BassClap, SoundPath + 'claps050b.mp3'); + +// LoadSoundFromFile(BassShuffle, SoundPath + 'Shuffle.mp3'); + + Log.BenchmarkEnd(4); Log.LogBenchmark('--> Loading Sounds', 4); +end; + +procedure TMusic.InitializeRecord; +var + S: integer; + device: integer; + descr: string; + input: integer; + input2: integer; + flags: integer; + mic: array[0..15] of integer; + SC: integer; // soundcard + SCI: integer; // soundcard input +begin + if RecordSystem = 1 then 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; + + + // check for recording devices; + {device := 0; + descr := BASS_RecordGetDeviceDescription(device); + + SetLength(SoundCard, 0); + while (descr <> '') do begin + SC := High(SoundCard) + 1; + SetLength(SoundCard, SC+1); + + Log.LogAnalyze('Device #'+IntToStr(device)+': '+ descr); + SoundCard[SC].Description := Descr; + + // check for recording inputs + mic[device] := -1; // default to no change + input := 0; + BASS_RecordInit(device); + Log.LogAnalyze('Input #' + IntToStr(Input) + ': ' + BASS_RecordGetInputName(input)); + flags := BASS_RecordGetInput(input); + + SetLength(SoundCard[SC].Input, 0); + while (flags <> -1) do begin + SCI := High(SoundCard[SC].Input) + 1; + SetLength(SoundCard[SC].Input, SCI+1); + + Log.LogAnalyze('Input #' + IntToStr(Input) + ': ' + BASS_RecordGetInputName(input)); + SoundCard[SC].Input[SCI].Name := BASS_RecordGetInputName(Input); + + if (flags and BASS_INPUT_TYPE_MASK) = BASS_INPUT_TYPE_MIC then begin + mic[device] := input; // auto set microphone + end; + Inc(Input); + flags := BASS_RecordGetInput(input); + end; + + if mic[device] <> -1 then begin + Log.LogAnalyze('Found the mic at input ' + IntToStr(Mic[device])) + end else begin + Log.LogAnalyze('Mic not found'); + mic[device] := 0; // setting to the first one (for kxproject) + end; + SoundCard[SC].InputSeleceted := Mic[Device]; + + + BASS_RecordFree; + + inc(Device); + descr := BASS_RecordGetDeviceDescription(Device); + end; // while} + end; // if +end; + +procedure TMusic.SetVolume(Volume: integer); +begin + //Old Sets Wave Volume + //BASS_SetVolume(Volume); + //New: Sets Volume only for this Application + + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_SetConfig(BASS_CONFIG_GVOL_SAMPLE, Volume); + BASS_SetConfig(BASS_CONFIG_GVOL_STREAM, Volume); + BASS_SetConfig(BASS_CONFIG_GVOL_MUSIC, Volume); + {$ENDIF} +end; + +procedure TMusic.SetMusicVolume(Volume: Integer); +begin + //Max Volume Prevention + if Volume > 100 then + Volume := 100; + + //Set Volume + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_ChannelSetAttributes (Bass, -1, Volume, -101); + {$ENDIF} +end; + +procedure TMusic.SetLoop(Enabled: boolean); +begin + Loop := Enabled; +end; + +function TMusic.Open(Name: string): boolean; +begin + Loaded := false; + if FileExists(Name) then + begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + Bass := Bass_StreamCreateFile(false, pchar(Name), 0, 0, 0); + {$ENDIF} + + Loaded := true; + //Set Max Volume + SetMusicVolume (100); + end; + + Result := Loaded; +end; + +procedure TMusic.Rewind; +begin + if Loaded then begin + end; +end; + +procedure TMusic.MoveTo(Time: real); +var + bytes: integer; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + bytes := BASS_ChannelSeconds2Bytes(Bass, Time); + BASS_ChannelSetPosition(Bass, bytes); + {$ENDIF} +end; + +procedure TMusic.Play; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + if Loaded then + begin + if Loop then + BASS_ChannelPlay(Bass, True); // start from beginning... actually bass itself does not loop, nor does this TMusic Class + + BASS_ChannelPlay(Bass, False); // for setting position before playing + end; + {$ENDIF} +end; + +procedure TMusic.Pause; //Pause Mod +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + if Loaded then begin + BASS_ChannelPause(Bass); // Pauses Song + end; + {$ENDIF} +end; + +procedure TMusic.Stop; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + Bass_ChannelStop(Bass); + {$ENDIF} +end; + +procedure TMusic.Close; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + Bass_StreamFree(Bass); + {$ENDIF} +end; + +function TMusic.Length: real; +var + bytes: integer; +begin + Result := 60; + + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + bytes := BASS_ChannelGetLength(Bass); + Result := BASS_ChannelBytes2Seconds(Bass, bytes); + {$ENDIF} +end; + +function TMusic.Position: real; +var + bytes: integer; +begin + Result := 0; + + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + bytes := BASS_ChannelGetPosition(BASS); + Result := BASS_ChannelBytes2Seconds(BASS, bytes); + {$ENDIF} +end; + +function TMusic.Finished: boolean; +begin + Result := false; + + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + if BASS_ChannelIsActive(BASS) = BASS_ACTIVE_STOPPED then + begin + Result := true; + end; + {$ENDIF} +end; + +procedure TMusic.PlayStart; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_ChannelPlay(BassStart, True); + {$ENDIF} +end; + +procedure TMusic.PlayBack; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_ChannelPlay(BassBack, True);// then + {$ENDIF} +end; + +procedure TMusic.PlaySwoosh; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_ChannelPlay(BassSwoosh, True); + {$ENDIF} +end; + +procedure TMusic.PlayChange; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_ChannelPlay(BassChange, True); + {$ENDIF} +end; + +procedure TMusic.PlayOption; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_ChannelPlay(BassOption, True); + {$ENDIF} +end; + +procedure TMusic.PlayClick; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_ChannelPlay(BassClick, True); + {$ENDIF} +end; + +procedure TMusic.PlayDrum; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_ChannelPlay(BassDrum, True); + {$ENDIF} +end; + +procedure TMusic.PlayHihat; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_ChannelPlay(BassHihat, True); + {$ENDIF} +end; + +procedure TMusic.PlayClap; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_ChannelPlay(BassClap, True); + {$ENDIF} +end; + +procedure TMusic.PlayShuffle; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_ChannelPlay(BassShuffle, True); + {$ENDIF} +end; + +procedure TMusic.StopShuffle; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_ChannelStop(BassShuffle); + {$ENDIF} +end; + +procedure TMusic.CaptureStart; +var + S: integer; + SC: integer; + P1: integer; + P2: integer; +begin + for S := 0 to High(Sound) do + Sound[S].BufferLong[0].Clear; + + for SC := 0 to High(Ini.CardList) do begin + P1 := Ini.CardList[SC].ChannelL; + P2 := Ini.CardList[SC].ChannelR; + if P1 > PlayersPlay then P1 := 0; + if P2 > PlayersPlay then P2 := 0; + if (P1 > 0) or (P2 > 0) then + CaptureCard(SC, P1, P2); + end; +end; + +procedure TMusic.CaptureStop; +var + SC: integer; + P1: integer; + P2: integer; +begin + + for SC := 0 to High(Ini.CardList) do begin + P1 := Ini.CardList[SC].ChannelL; + P2 := Ini.CardList[SC].ChannelR; + if P1 > PlayersPlay then P1 := 0; + if P2 > PlayersPlay then P2 := 0; + if (P1 > 0) or (P2 > 0) then StopCard(SC); + end; + +end; + +//procedure TMusic.CaptureCard(RecordI, SoundNum, PlayerLeft, PlayerRight: byte); +procedure TMusic.CaptureCard(RecordI, PlayerLeft, PlayerRight: byte); +var + Error: integer; + ErrorMsg: string; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + + if not BASS_RecordInit(RecordI) 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.LogAnalyze('Error initializing record [' + IntToStr(RecordI) + ', ' + + IntToStr(PlayerLeft) + ', '+ IntToStr(PlayerRight) + ']: ' + + ErrorMsg);} + Log.LogError('Error initializing record [' + IntToStr(RecordI) + ', ' + + IntToStr(PlayerLeft) + ', '+ IntToStr(PlayerRight) + ']: ' + + ErrorMsg); + Log.LogError('Music -> CaptureCard: Error initializing record: ' + ErrorMsg); + + + end + else + begin + Recording.SoundCard[RecordI].BassRecordStream := BASS_RecordStart(44100, 2, MakeLong(0, 20) , @GetMicrophone, PlayerLeft + PlayerRight*256); + end; + + {$ENDIF} +end; + +procedure TMusic.StopCard(Card: byte); +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + BASS_RecordSetDevice(Card); + BASS_RecordFree; + {$ENDIF} +end; + +function TMusic.LoadSoundFromFile(var hStream: hStream; Name: string): boolean; +var + L: Integer; +begin + if FileExists(Name) then begin + Log.LogStatus('Loading Sound: "' + Name + '"', 'LoadSoundFromFile'); + try + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + hStream := BASS_StreamCreateFile(False, pchar(Name), 0, 0, 0); + {$ENDIF} + + //Add CustomSound + L := High(CustomSounds) + 1; + SetLength (CustomSounds, L + 1); + CustomSounds[L].Filename := Name; + CustomSounds[L].Handle := hStream; + except + Log.LogError('Failed to open using BASS', 'LoadSoundFromFile'); + end; + end else begin + Log.LogError('Sound not found: "' + Name + '"', 'LoadSoundFromFile'); + exit; + end; +end; + +//Equalizer +function TMusic.GetFFTData: TFFTData; +var +Data: TFFTData; +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + + //Get Channel Data Mono and 256 Values + BASS_ChannelGetData(Bass, @Result, BASS_DATA_FFT512); + //Result := Data; + + {$ENDIF} +end; + +function TMusic.LoadCustomSound(const Filename: String): Cardinal; +var + S: hStream; + I: Integer; + F: String; +begin + //Search for Sound in already loaded Sounds + F := UpperCase(SoundPath + FileName); + For I := 0 to High(CustomSounds) do + begin + if (UpperCase(CustomSounds[I].Filename) = F) then + begin + Result := I; + Exit; + end; + end; + + if LoadSoundFromFile(S, SoundPath + Filename) then + Result := High(CustomSounds) + else + Result := 0; +end; + +procedure TMusic.PlayCustomSound(const Index: Cardinal); +begin + {$IFDEF useBASS} + // TODO : jb_linux replace with something other than bass + + if Index <= High(CustomSounds) then + BASS_ChannelPlay(CustomSounds[Index].Handle, True); + + {$ENDIF} +end; + + +end. -- cgit v1.2.3 From ef07574805b0fb247cfa91f0e6bbb234c0dbd22a Mon Sep 17 00:00:00 2001 From: jaybinks Date: Mon, 8 Oct 2007 06:45:19 +0000 Subject: minor changes to faciliate ffmpeg audio playback jira#USDX-123 git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@470 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UMusic.pas | 107 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 102 insertions(+), 5 deletions(-) (limited to 'Game/Code/Classes/UMusic.pas') diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas index b3729e69..bdd0be83 100644 --- a/Game/Code/Classes/UMusic.pas +++ b/Game/Code/Classes/UMusic.pas @@ -41,8 +41,48 @@ type Handle : hStream; end; + IAudioPlayback = Interface + procedure InitializePlayback; + + procedure SetVolume(Volume: integer); + procedure SetMusicVolume(Volume: integer); + procedure SetLoop(Enabled: boolean); + + function Open(Name: string): boolean; // true if succeed + + procedure Play; + procedure Pause; //Pause Mod + procedure Stop; - TMusic = class + procedure Rewind; + procedure MoveTo(Time: real); + procedure Close; + + function Finished: boolean; + function Length: real; + function Position: real; + + procedure PlayStart; + procedure PlayBack; + procedure PlaySwoosh; + procedure PlayChange; + procedure PlayOption; + procedure PlayClick; + procedure PlayDrum; + procedure PlayHihat; + procedure PlayClap; + procedure PlayShuffle; + procedure StopShuffle; + + function LoadSoundFromFile(var hStream: hStream; Name: string): boolean; + + //Custom Sounds + function LoadCustomSound(const Filename: String): Cardinal; + procedure PlayCustomSound(const Index: Cardinal); + end; + + + TMusic = class( TInterfacedObject, IAudioPlayback ) private BassStart: hStream; // Wait, I've replaced this with BASS BassBack: hStream; // It has almost all features we need @@ -59,6 +99,8 @@ type CustomSounds: array of TCustomSoundEntry; + function FFMPeg_StreamCreateFile(abool : boolean; aFileName : pchar ): THandle; + Loaded: boolean; Loop: boolean; public @@ -101,7 +143,6 @@ type //Custom Sounds function LoadCustomSound(const Filename: String): Cardinal; procedure PlayCustomSound(const Index: Cardinal); - end; const @@ -202,6 +243,11 @@ uses {$IFDEF FPC} lclintf, {$ENDIF} + + avcodec, + avformat, + avutil, + UGraphic, URecord, UFiles, @@ -265,7 +311,8 @@ begin // LoadSoundFromFile(BassShuffle, SoundPath + 'Shuffle.mp3'); - Log.BenchmarkEnd(4); Log.LogBenchmark('--> Loading Sounds', 4); + Log.BenchmarkEnd(4); + Log.LogBenchmark('--> Loading Sounds', 4); end; procedure TMusic.InitializeRecord; @@ -663,14 +710,19 @@ function TMusic.LoadSoundFromFile(var hStream: hStream; Name: string): boolean; var L: Integer; begin - if FileExists(Name) then begin + if FileExists(Name) then + begin Log.LogStatus('Loading Sound: "' + Name + '"', 'LoadSoundFromFile'); try {$IFDEF useBASS} // TODO : jb_linux replace with something other than bass hStream := BASS_StreamCreateFile(False, pchar(Name), 0, 0, 0); + {$ELSE} + hStream := FFMPeg_StreamCreateFile(False, pchar(Name) ); {$ENDIF} + + //Add CustomSound L := High(CustomSounds) + 1; SetLength (CustomSounds, L + 1); @@ -679,7 +731,9 @@ begin except Log.LogError('Failed to open using BASS', 'LoadSoundFromFile'); end; - end else begin + end + else + begin Log.LogError('Sound not found: "' + Name + '"', 'LoadSoundFromFile'); exit; end; @@ -735,4 +789,47 @@ begin end; +{* + +Sorry guys... this is my mess :( +Im going to try and get ffmpeg to handle audio playback ( at least for linux ) +and Im going to implement it nicly along side BASS, in TMusic ( where I can ) + +http://www.dranger.com/ffmpeg/ffmpeg.html +http://www.dranger.com/ffmpeg/ffmpegtutorial_all.html + +http://www.inb.uni-luebeck.de/~boehme/using_libavcodec.html + +*} +function TMusic.FFMPeg_StreamCreateFile(abool : boolean; aFileName : pchar ): THandle; +var + lFormatCtx : PAVFormatContext; +begin + +(* + if(SDL_OpenAudio(&wanted_spec, &spec) < 0) + begin + fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError()); + writeln( 'SDL_OpenAudio' ); + exit; + end; +*) + +(* + if ( av_open_input_file( lFormatCtx, aFileName, NULL, 0, NULL ) <> 0 ) + begin + writeln( 'Unable to open file '+ aFileName ); + exit; + end; + + // Retrieve stream information + if ( av_find_stream_info(pFormatCtx) < 0 ) + begin + writeln( 'Unable to Retrieve stream information' ); + exit; + end; +*) + +end; + end. -- cgit v1.2.3 From 174244a5ddf10da145779f6fe0ad1c5bc398fa6a Mon Sep 17 00:00:00 2001 From: jaybinks Date: Mon, 8 Oct 2007 09:08:17 +0000 Subject: fixed bad build build#USDX-DELPHI-31 oops... git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@473 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UMusic.pas | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'Game/Code/Classes/UMusic.pas') diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas index bdd0be83..3c43615b 100644 --- a/Game/Code/Classes/UMusic.pas +++ b/Game/Code/Classes/UMusic.pas @@ -97,12 +97,12 @@ type //Custom Sounds CustomSounds: array of TCustomSoundEntry; + Loaded: boolean; + Loop: boolean; function FFMPeg_StreamCreateFile(abool : boolean; aFileName : pchar ): THandle; - Loaded: boolean; - Loop: boolean; public Bass: hStream; procedure InitializePlayback; @@ -670,7 +670,8 @@ begin {$IFDEF useBASS} // TODO : jb_linux replace with something other than bass - if not BASS_RecordInit(RecordI) then begin + if not BASS_RecordInit(RecordI) then + begin Error := BASS_ErrorGetCode; ErrorMsg := IntToStr(Error); -- cgit v1.2.3 From 44554c7908f7e2405a249331f00a35703f5939c2 Mon Sep 17 00:00:00 2001 From: jaybinks Date: Thu, 11 Oct 2007 12:02:20 +0000 Subject: Added IAudioPlayback Interface and implementation for BASS. Created "AudioPlayback" Global Singleton, which removed the need for the "Music" Global variable. This was done because global singleton objects are a recognized better "design pattern" achieving the same thing as global variables, but in a nicer way. I will be working to a) separate IAudioPlayback in to separate "Playback" and "Input" Interfaces b) build a FFMpeg class that implements IAudioPlayback git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@504 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UMusic.pas | 802 ++++--------------------------------------- 1 file changed, 74 insertions(+), 728 deletions(-) (limited to 'Game/Code/Classes/UMusic.pas') diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas index 3c43615b..934e14e3 100644 --- a/Game/Code/Classes/UMusic.pas +++ b/Game/Code/Classes/UMusic.pas @@ -8,145 +8,8 @@ interface {$MODE Delphi} {$ENDIF} - -uses Classes, - {$IFDEF win32} - windows, - {$ENDIF} - UCommon, - Messages, - SysUtils, - {$IFNDEF FPC} - Forms, - {$ENDIF} - {$IFDEF useBASS} - bass, - {$ENDIF} - ULog, - USongs; - - -procedure InitializeSound; - -type - TSoundCard = record - Name: string; - Source: array of string; - end; - - TFFTData = array [0..256] of Single; - - TCustomSoundEntry = record - Filename : String; - Handle : hStream; - end; - - IAudioPlayback = Interface - procedure InitializePlayback; - - procedure SetVolume(Volume: integer); - procedure SetMusicVolume(Volume: integer); - procedure SetLoop(Enabled: boolean); - - function Open(Name: string): boolean; // true if succeed - - procedure Play; - procedure Pause; //Pause Mod - procedure Stop; - - procedure Rewind; - procedure MoveTo(Time: real); - procedure Close; - - function Finished: boolean; - function Length: real; - function Position: real; - - procedure PlayStart; - procedure PlayBack; - procedure PlaySwoosh; - procedure PlayChange; - procedure PlayOption; - procedure PlayClick; - procedure PlayDrum; - procedure PlayHihat; - procedure PlayClap; - procedure PlayShuffle; - procedure StopShuffle; - - function LoadSoundFromFile(var hStream: hStream; Name: string): boolean; - - //Custom Sounds - function LoadCustomSound(const Filename: String): Cardinal; - procedure PlayCustomSound(const Index: Cardinal); - end; - - - TMusic = class( TInterfacedObject, IAudioPlayback ) - private - BassStart: hStream; // Wait, I've replaced this with BASS - BassBack: hStream; // It has almost all features we need - BassSwoosh: hStream; - BassChange: hStream; // Almost? It aleady has them all :) - BassOption: hStream; - BassClick: hStream; - BassDrum: hStream; - BassHihat: hStream; - BassClap: hStream; - BassShuffle: hStream; - - //Custom Sounds - CustomSounds: array of TCustomSoundEntry; - Loaded: boolean; - Loop: boolean; - - - function FFMPeg_StreamCreateFile(abool : boolean; aFileName : pchar ): THandle; - - public - Bass: hStream; - procedure InitializePlayback; - procedure InitializeRecord; - procedure SetVolume(Volume: integer); - procedure SetMusicVolume(Volume: integer); - procedure SetLoop(Enabled: boolean); - function Open(Name: string): boolean; // true if succeed - procedure Rewind; - procedure MoveTo(Time: real); - procedure Play; - procedure Pause; //Pause Mod - procedure Stop; - procedure Close; - function Finished: boolean; - function Length: real; - function Position: real; - procedure PlayStart; - procedure PlayBack; - procedure PlaySwoosh; - procedure PlayChange; - procedure PlayOption; - procedure PlayClick; - procedure PlayDrum; - procedure PlayHihat; - procedure PlayClap; - procedure PlayShuffle; - procedure StopShuffle; - procedure CaptureStart; - procedure CaptureStop; - procedure CaptureCard(RecordI, PlayerLeft, PlayerRight: byte); - procedure StopCard(Card: byte); - function LoadSoundFromFile(var hStream: hStream; Name: string): boolean; - - //Equalizer - function GetFFTData: TFFTData; - - //Custom Sounds - function LoadCustomSound(const Filename: String): Cardinal; - procedure PlayCustomSound(const Index: Cardinal); -end; - -const - RecordSystem = 1; +uses Classes // UCommon + ; type TMuzyka = record @@ -216,621 +79,104 @@ type Razem: real; // caly czas utworu end; -var - Music: TMusic; - - // muzyka - Muzyka: TMuzyka; - - // czesci z nutami; - Czesci: array of TCzesci; - - // czas - Czas: TCzas; - - fHWND: Thandle; - -type - TMPModes = (mpNotReady, mpStopped, mpPlaying, mpRecording, mpSeeking, - mpPaused, mpOpen); - -const - ModeStr: array[TMPModes] of string = ('Not ready', 'Stopped', 'Playing', 'Recording', 'Seeking', 'Paused', 'Open'); - -implementation - -uses - {$IFDEF FPC} - lclintf, - {$ENDIF} - - avcodec, - avformat, - avutil, - - UGraphic, - URecord, - UFiles, - UIni, - UMain, - UThemes; - -procedure InitializeSound; -begin - Log.LogStatus('Initializing Playback', 'InitializeSound'); Music.InitializePlayback; - Log.LogStatus('Initializing Record', 'InitializeSound'); Music.InitializeRecord; -end; - -procedure TMusic.InitializePlayback; -var - Pet: integer; - S: integer; -begin - Log.BenchmarkStart(4); - Log.LogStatus('Initializing Playback Subsystem', 'Music Initialize'); - - Loaded := false; - Loop := false; - - {$ifdef win32} - // TODO : JB_Linux ... is this needed ? :) - fHWND := AllocateHWND( nil); // TODO : JB_lazarus - can we do something different here ?? lazarus didnt like this function - {$ENDIF} - - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - if not BASS_Init(1, 44100, 0, fHWND, nil) then - begin - {$IFNDEF FPC} - // TODO : JB_linux find a way to do this nice.. - Application.MessageBox ('Could not initialize BASS', 'Error'); - {$ENDIF} - Exit; - end; - {$ENDIF} - - Log.BenchmarkEnd(4); Log.LogBenchmark('--> Bass Init', 4); - - // config playing buffer -// BASS_SetConfig(BASS_CONFIG_UPDATEPERIOD, 10); -// BASS_SetConfig(BASS_CONFIG_BUFFER, 100); - - Log.LogStatus('Loading Sounds', 'Music Initialize'); - - Log.BenchmarkStart(4); - LoadSoundFromFile(BassStart, SoundPath + 'Common Start.mp3'); - LoadSoundFromFile(BassBack, SoundPath + 'Common Back.mp3'); - LoadSoundFromFile(BassSwoosh, SoundPath + 'menu swoosh.mp3'); - LoadSoundFromFile(BassChange, SoundPath + 'select music change music 50.mp3'); - LoadSoundFromFile(BassOption, SoundPath + 'option change col.mp3'); - LoadSoundFromFile(BassClick, SoundPath + 'rimshot022b.mp3'); - -// LoadSoundFromFile(BassDrum, SoundPath + 'bassdrumhard076b.mp3'); -// LoadSoundFromFile(BassHihat, SoundPath + 'hihatclosed068b.mp3'); -// LoadSoundFromFile(BassClap, SoundPath + 'claps050b.mp3'); - -// LoadSoundFromFile(BassShuffle, SoundPath + 'Shuffle.mp3'); - - Log.BenchmarkEnd(4); - Log.LogBenchmark('--> Loading Sounds', 4); -end; - -procedure TMusic.InitializeRecord; -var - S: integer; - device: integer; - descr: string; - input: integer; - input2: integer; - flags: integer; - mic: array[0..15] of integer; - SC: integer; // soundcard - SCI: integer; // soundcard input -begin - if RecordSystem = 1 then 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; - - - // check for recording devices; - {device := 0; - descr := BASS_RecordGetDeviceDescription(device); - - SetLength(SoundCard, 0); - while (descr <> '') do begin - SC := High(SoundCard) + 1; - SetLength(SoundCard, SC+1); - - Log.LogAnalyze('Device #'+IntToStr(device)+': '+ descr); - SoundCard[SC].Description := Descr; - - // check for recording inputs - mic[device] := -1; // default to no change - input := 0; - BASS_RecordInit(device); - Log.LogAnalyze('Input #' + IntToStr(Input) + ': ' + BASS_RecordGetInputName(input)); - flags := BASS_RecordGetInput(input); - - SetLength(SoundCard[SC].Input, 0); - while (flags <> -1) do begin - SCI := High(SoundCard[SC].Input) + 1; - SetLength(SoundCard[SC].Input, SCI+1); - - Log.LogAnalyze('Input #' + IntToStr(Input) + ': ' + BASS_RecordGetInputName(input)); - SoundCard[SC].Input[SCI].Name := BASS_RecordGetInputName(Input); - - if (flags and BASS_INPUT_TYPE_MASK) = BASS_INPUT_TYPE_MIC then begin - mic[device] := input; // auto set microphone - end; - Inc(Input); - flags := BASS_RecordGetInput(input); - end; - - if mic[device] <> -1 then begin - Log.LogAnalyze('Found the mic at input ' + IntToStr(Mic[device])) - end else begin - Log.LogAnalyze('Mic not found'); - mic[device] := 0; // setting to the first one (for kxproject) - end; - SoundCard[SC].InputSeleceted := Mic[Device]; - - - BASS_RecordFree; - - inc(Device); - descr := BASS_RecordGetDeviceDescription(Device); - end; // while} - end; // if -end; - -procedure TMusic.SetVolume(Volume: integer); -begin - //Old Sets Wave Volume - //BASS_SetVolume(Volume); - //New: Sets Volume only for this Application - - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_SetConfig(BASS_CONFIG_GVOL_SAMPLE, Volume); - BASS_SetConfig(BASS_CONFIG_GVOL_STREAM, Volume); - BASS_SetConfig(BASS_CONFIG_GVOL_MUSIC, Volume); - {$ENDIF} -end; - -procedure TMusic.SetMusicVolume(Volume: Integer); -begin - //Max Volume Prevention - if Volume > 100 then - Volume := 100; - - //Set Volume - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_ChannelSetAttributes (Bass, -1, Volume, -101); - {$ENDIF} -end; - -procedure TMusic.SetLoop(Enabled: boolean); -begin - Loop := Enabled; -end; - -function TMusic.Open(Name: string): boolean; -begin - Loaded := false; - if FileExists(Name) then - begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - Bass := Bass_StreamCreateFile(false, pchar(Name), 0, 0, 0); - {$ENDIF} - - Loaded := true; - //Set Max Volume - SetMusicVolume (100); - end; - - Result := Loaded; -end; - -procedure TMusic.Rewind; -begin - if Loaded then begin - end; -end; - -procedure TMusic.MoveTo(Time: real); -var - bytes: integer; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - bytes := BASS_ChannelSeconds2Bytes(Bass, Time); - BASS_ChannelSetPosition(Bass, bytes); - {$ENDIF} -end; - -procedure TMusic.Play; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - if Loaded then - begin - if Loop then - BASS_ChannelPlay(Bass, True); // start from beginning... actually bass itself does not loop, nor does this TMusic Class - - BASS_ChannelPlay(Bass, False); // for setting position before playing + TSoundCard = record + Name: string; + Source: array of string; end; - {$ENDIF} -end; -procedure TMusic.Pause; //Pause Mod -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - if Loaded then begin - BASS_ChannelPause(Bass); // Pauses Song - end; - {$ENDIF} -end; - -procedure TMusic.Stop; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - Bass_ChannelStop(Bass); - {$ENDIF} -end; - -procedure TMusic.Close; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - Bass_StreamFree(Bass); - {$ENDIF} -end; - -function TMusic.Length: real; -var - bytes: integer; -begin - Result := 60; - - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - bytes := BASS_ChannelGetLength(Bass); - Result := BASS_ChannelBytes2Seconds(Bass, bytes); - {$ENDIF} -end; - -function TMusic.Position: real; -var - bytes: integer; -begin - Result := 0; - - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - bytes := BASS_ChannelGetPosition(BASS); - Result := BASS_ChannelBytes2Seconds(BASS, bytes); - {$ENDIF} -end; + TFFTData = array [0..256] of Single; -function TMusic.Finished: boolean; -begin - Result := false; + hStream = Cardinal; - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - if BASS_ChannelIsActive(BASS) = BASS_ACTIVE_STOPPED then - begin - Result := true; + TCustomSoundEntry = record + Filename : String; + Handle : hStream; end; - {$ENDIF} -end; - -procedure TMusic.PlayStart; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_ChannelPlay(BassStart, True); - {$ENDIF} -end; - -procedure TMusic.PlayBack; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_ChannelPlay(BassBack, True);// then - {$ENDIF} -end; - -procedure TMusic.PlaySwoosh; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_ChannelPlay(BassSwoosh, True); - {$ENDIF} -end; - -procedure TMusic.PlayChange; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_ChannelPlay(BassChange, True); - {$ENDIF} -end; - -procedure TMusic.PlayOption; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_ChannelPlay(BassOption, True); - {$ENDIF} -end; - -procedure TMusic.PlayClick; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_ChannelPlay(BassClick, True); - {$ENDIF} -end; -procedure TMusic.PlayDrum; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_ChannelPlay(BassDrum, True); - {$ENDIF} -end; - -procedure TMusic.PlayHihat; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_ChannelPlay(BassHihat, True); - {$ENDIF} -end; - -procedure TMusic.PlayClap; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_ChannelPlay(BassClap, True); - {$ENDIF} -end; - -procedure TMusic.PlayShuffle; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_ChannelPlay(BassShuffle, True); - {$ENDIF} -end; +type + IAudioPlayback = Interface + procedure InitializePlayback; + procedure InitializeRecord; + procedure SetVolume(Volume: integer); + procedure SetMusicVolume(Volume: integer); + procedure SetLoop(Enabled: boolean); + function Open(Name: string): boolean; // true if succeed + procedure Rewind; + procedure MoveTo(Time: real); + procedure Play; + procedure Pause; //Pause Mod + procedure Stop; + procedure Close; + function Finished: boolean; + function Length: real; + function Position: real; + procedure PlayStart; + procedure PlayBack; + procedure PlaySwoosh; + procedure PlayChange; + procedure PlayOption; + procedure PlayClick; + procedure PlayDrum; + procedure PlayHihat; + procedure PlayClap; + procedure PlayShuffle; + procedure StopShuffle; + procedure CaptureStart; + procedure CaptureStop; + procedure CaptureCard(RecordI, PlayerLeft, PlayerRight: byte); + procedure StopCard(Card: byte); + function LoadSoundFromFile(var hStream: hStream; Name: string): boolean; -procedure TMusic.StopShuffle; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_ChannelStop(BassShuffle); - {$ENDIF} -end; + //Equalizer + function GetFFTData: TFFTData; -procedure TMusic.CaptureStart; -var - S: integer; - SC: integer; - P1: integer; - P2: integer; -begin - for S := 0 to High(Sound) do - Sound[S].BufferLong[0].Clear; - - for SC := 0 to High(Ini.CardList) do begin - P1 := Ini.CardList[SC].ChannelL; - P2 := Ini.CardList[SC].ChannelR; - if P1 > PlayersPlay then P1 := 0; - if P2 > PlayersPlay then P2 := 0; - if (P1 > 0) or (P2 > 0) then - CaptureCard(SC, P1, P2); + //Custom Sounds + function LoadCustomSound(const Filename: String): Cardinal; + procedure PlayCustomSound(const Index: Cardinal ); end; -end; -procedure TMusic.CaptureStop; -var - SC: integer; - P1: integer; - P2: integer; -begin - for SC := 0 to High(Ini.CardList) do begin - P1 := Ini.CardList[SC].ChannelL; - P2 := Ini.CardList[SC].ChannelR; - if P1 > PlayersPlay then P1 := 0; - if P2 > PlayersPlay then P2 := 0; - if (P1 > 0) or (P2 > 0) then StopCard(SC); - end; +var // TODO : JB --- THESE SHOULD NOT BE GLOBAL + // muzyka + Muzyka: TMuzyka; -end; + // czesci z nutami; + Czesci: array of TCzesci; -//procedure TMusic.CaptureCard(RecordI, SoundNum, PlayerLeft, PlayerRight: byte); -procedure TMusic.CaptureCard(RecordI, PlayerLeft, PlayerRight: byte); -var - Error: integer; - ErrorMsg: string; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - - if not BASS_RecordInit(RecordI) 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.LogAnalyze('Error initializing record [' + IntToStr(RecordI) + ', ' - + IntToStr(PlayerLeft) + ', '+ IntToStr(PlayerRight) + ']: ' - + ErrorMsg);} - Log.LogError('Error initializing record [' + IntToStr(RecordI) + ', ' - + IntToStr(PlayerLeft) + ', '+ IntToStr(PlayerRight) + ']: ' - + ErrorMsg); - Log.LogError('Music -> CaptureCard: Error initializing record: ' + ErrorMsg); - - - end - else - begin - Recording.SoundCard[RecordI].BassRecordStream := BASS_RecordStart(44100, 2, MakeLong(0, 20) , @GetMicrophone, PlayerLeft + PlayerRight*256); - end; + // czas + Czas: TCzas; - {$ENDIF} -end; - -procedure TMusic.StopCard(Card: byte); -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - BASS_RecordSetDevice(Card); - BASS_RecordFree; - {$ENDIF} -end; -function TMusic.LoadSoundFromFile(var hStream: hStream; Name: string): boolean; -var - L: Integer; -begin - if FileExists(Name) then - begin - Log.LogStatus('Loading Sound: "' + Name + '"', 'LoadSoundFromFile'); - try - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass - hStream := BASS_StreamCreateFile(False, pchar(Name), 0, 0, 0); - {$ELSE} - hStream := FFMPeg_StreamCreateFile(False, pchar(Name) ); - {$ENDIF} - - - - //Add CustomSound - L := High(CustomSounds) + 1; - SetLength (CustomSounds, L + 1); - CustomSounds[L].Filename := Name; - CustomSounds[L].Handle := hStream; - except - Log.LogError('Failed to open using BASS', 'LoadSoundFromFile'); - end; - end - else - begin - Log.LogError('Sound not found: "' + Name + '"', 'LoadSoundFromFile'); - exit; - end; -end; +procedure InitializeSound; +function AudioPlayback(): IAudioPlayback; -//Equalizer -function TMusic.GetFFTData: TFFTData; -var -Data: TFFTData; -begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass +implementation - //Get Channel Data Mono and 256 Values - BASS_ChannelGetData(Bass, @Result, BASS_DATA_FFT512); - //Result := Data; - - {$ENDIF} -end; +uses + uLog, + UMusic_BASS; -function TMusic.LoadCustomSound(const Filename: String): Cardinal; var - S: hStream; - I: Integer; - F: String; -begin - //Search for Sound in already loaded Sounds - F := UpperCase(SoundPath + FileName); - For I := 0 to High(CustomSounds) do - begin - if (UpperCase(CustomSounds[I].Filename) = F) then - begin - Result := I; - Exit; - end; - end; - - if LoadSoundFromFile(S, SoundPath + Filename) then - Result := High(CustomSounds) - else - Result := 0; -end; + singleton_AudioPlayback : IAudioPlayback; -procedure TMusic.PlayCustomSound(const Index: Cardinal); +function AudioPlayback(): IAudioPlayback; begin - {$IFDEF useBASS} - // TODO : jb_linux replace with something other than bass + if singleton_AudioPlayback = nil then + begin + writeln( 'Created AudioPlayback' ); + singleton_AudioPlayback := TMusic_bass.create(); + end; - if Index <= High(CustomSounds) then - BASS_ChannelPlay(CustomSounds[Index].Handle, True); - - {$ENDIF} + result := singleton_AudioPlayback; end; - -{* - -Sorry guys... this is my mess :( -Im going to try and get ffmpeg to handle audio playback ( at least for linux ) -and Im going to implement it nicly along side BASS, in TMusic ( where I can ) - -http://www.dranger.com/ffmpeg/ffmpeg.html -http://www.dranger.com/ffmpeg/ffmpegtutorial_all.html - -http://www.inb.uni-luebeck.de/~boehme/using_libavcodec.html - -*} -function TMusic.FFMPeg_StreamCreateFile(abool : boolean; aFileName : pchar ): THandle; -var - lFormatCtx : PAVFormatContext; +procedure InitializeSound; begin + Log.LogStatus('Initializing Playback', 'InitializeSound'); + AudioPlayback.InitializePlayback; -(* - if(SDL_OpenAudio(&wanted_spec, &spec) < 0) - begin - fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError()); - writeln( 'SDL_OpenAudio' ); - exit; - end; -*) - -(* - if ( av_open_input_file( lFormatCtx, aFileName, NULL, 0, NULL ) <> 0 ) - begin - writeln( 'Unable to open file '+ aFileName ); - exit; - end; - - // Retrieve stream information - if ( av_find_stream_info(pFormatCtx) < 0 ) - begin - writeln( 'Unable to Retrieve stream information' ); - exit; - end; -*) - + Log.LogStatus('Initializing Record', 'InitializeSound'); + AudioPlayback.InitializeRecord; end; end. -- cgit v1.2.3 From 6292440f6da3c11e85bb9fc3a741a26540e429be Mon Sep 17 00:00:00 2001 From: jaybinks Date: Thu, 11 Oct 2007 12:12:37 +0000 Subject: separated IAudioPlayback in to separate "Playback" and "Input" Interfaces ( both interfaces provided by same TMusic_Bass class... git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@505 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UMusic.pas | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) (limited to 'Game/Code/Classes/UMusic.pas') diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas index 934e14e3..a2620607 100644 --- a/Game/Code/Classes/UMusic.pas +++ b/Game/Code/Classes/UMusic.pas @@ -96,7 +96,6 @@ type type IAudioPlayback = Interface procedure InitializePlayback; - procedure InitializeRecord; procedure SetVolume(Volume: integer); procedure SetMusicVolume(Volume: integer); procedure SetLoop(Enabled: boolean); @@ -121,18 +120,25 @@ type procedure PlayClap; procedure PlayShuffle; procedure StopShuffle; + + function LoadSoundFromFile(var hStream: hStream; Name: string): boolean; + + //Custom Sounds + function LoadCustomSound(const Filename: String): Cardinal; + procedure PlayCustomSound(const Index: Cardinal ); + end; + + IAudioInput = Interface + procedure InitializeRecord; + procedure CaptureStart; procedure CaptureStop; + procedure CaptureCard(RecordI, PlayerLeft, PlayerRight: byte); procedure StopCard(Card: byte); - function LoadSoundFromFile(var hStream: hStream; Name: string): boolean; //Equalizer function GetFFTData: TFFTData; - - //Custom Sounds - function LoadCustomSound(const Filename: String): Cardinal; - procedure PlayCustomSound(const Index: Cardinal ); end; @@ -147,8 +153,11 @@ var // TODO : JB --- THESE SHOULD NOT BE GLOBAL Czas: TCzas; -procedure InitializeSound; +procedure InitializeSound; + function AudioPlayback(): IAudioPlayback; +function AudioInput(): IAudioInput; + implementation @@ -158,25 +167,37 @@ uses var singleton_AudioPlayback : IAudioPlayback; + singleton_AudioInput : IAudioInput; function AudioPlayback(): IAudioPlayback; begin if singleton_AudioPlayback = nil then begin writeln( 'Created AudioPlayback' ); - singleton_AudioPlayback := TMusic_bass.create(); + singleton_AudioPlayback := TMusic_bass.create(); // Yes we could do this with one instance of TMusic_Bass... but I cant be bothered at this point:P end; result := singleton_AudioPlayback; end; +function AudioInput(): IAudioInput; +begin + if singleton_AudioInput = nil then + begin + writeln( 'Created AudioInput' ); + singleton_AudioInput := TMusic_bass.create(); // Yes we could do this with one instance of TMusic_Bass... but I cant be bothered at this point:P + end; + + result := singleton_AudioInput; +end; + procedure InitializeSound; begin Log.LogStatus('Initializing Playback', 'InitializeSound'); AudioPlayback.InitializePlayback; Log.LogStatus('Initializing Record', 'InitializeSound'); - AudioPlayback.InitializeRecord; + AudioInput.InitializeRecord; end; end. -- cgit v1.2.3 From df37a6a52ea5b1856e9e0e4d924a859f3fa472e1 Mon Sep 17 00:00:00 2001 From: jaybinks Date: Thu, 11 Oct 2007 13:32:43 +0000 Subject: added UAudio_FFMpeg.pas as placeholder... ( Still has bass code in it.. needs to be replaced with ffmpeg code ) UMusic ( And UAudio* ) files, now have proper IAudioPlayback and IAudioInput Interface enumeration. simply having the unit in the uses clause will make it available. git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@506 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UMusic.pas | 87 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 67 insertions(+), 20 deletions(-) (limited to 'Game/Code/Classes/UMusic.pas') diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas index a2620607..8aa59d41 100644 --- a/Game/Code/Classes/UMusic.pas +++ b/Game/Code/Classes/UMusic.pas @@ -95,6 +95,8 @@ type type IAudioPlayback = Interface + ['{E4AE0B40-3C21-4DC5-847C-20A87E0DFB96}'] + function GetName: String; procedure InitializePlayback; procedure SetVolume(Volume: integer); procedure SetMusicVolume(Volume: integer); @@ -129,6 +131,8 @@ type end; IAudioInput = Interface + ['{A5C8DA92-2A0C-4AB2-849B-2F7448C6003A}'] + function GetName: String; procedure InitializeRecord; procedure CaptureStart; @@ -158,46 +162,89 @@ procedure InitializeSound; function AudioPlayback(): IAudioPlayback; function AudioInput(): IAudioInput; +function AudioManager: TInterfaceList; + implementation uses - uLog, - UMusic_BASS; + sysutils, + uLog; var singleton_AudioPlayback : IAudioPlayback; singleton_AudioInput : IAudioInput; + singleton_AudioManager : TInterfaceList; + + +function AudioManager: TInterfaceList; +begin + Result := singleton_AudioManager; +end; //CompressionPluginManager + function AudioPlayback(): IAudioPlayback; begin - if singleton_AudioPlayback = nil then - begin - writeln( 'Created AudioPlayback' ); - singleton_AudioPlayback := TMusic_bass.create(); // Yes we could do this with one instance of TMusic_Bass... but I cant be bothered at this point:P - end; - - result := singleton_AudioPlayback; + result := singleton_AudioPlayback; end; function AudioInput(): IAudioInput; begin - if singleton_AudioInput = nil then - begin - writeln( 'Created AudioInput' ); - singleton_AudioInput := TMusic_bass.create(); // Yes we could do this with one instance of TMusic_Bass... but I cant be bothered at this point:P - end; - result := singleton_AudioInput; end; procedure InitializeSound; +var + lTmpPlayBack : IAudioPlayback; + lTmpInput : IAudioInput; + iCount : Integer; begin - Log.LogStatus('Initializing Playback', 'InitializeSound'); - AudioPlayback.InitializePlayback; - - Log.LogStatus('Initializing Record', 'InitializeSound'); - AudioInput.InitializeRecord; + lTmpPlayBack := nil; + lTmpInput := nil; + + writeln( 'InitializeSound , Enumerate Registered Audio Interfaces' ); + for iCount := 0 to singleton_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, lTmpPlayBack ) = 0 ) AND + ( not assigned( singleton_AudioPlayback ) ) then + begin + singleton_AudioPlayback := lTmpPlayBack; + end; + + // if this interface is a Input, then set it as the default used + if ( AudioManager[iCount].QueryInterface( IAudioInput, lTmpInput ) = 0 ) AND + ( not assigned( singleton_AudioInput ) ) then + begin + singleton_AudioInput := lTmpInput; + end; + end; + end; + + + writeln( 'Registered Audio Playback Interface : ' + AudioPlayback.GetName ); + writeln( 'Registered Audio Input Interface : ' + AudioInput.GetName ); + + // Initialize Playback + Log.LogStatus('Initializing Playback ('+AudioPlayback.GetName+')', 'InitializeSound'); + AudioPlayback.InitializePlayback; + + // Initialize Input + Log.LogStatus('Initializing Record ('+AudioPlayback.GetName+')', 'InitializeSound'); + AudioInput.InitializeRecord; end; +initialization +begin + writeln('Init AudioManager'); + singleton_AudioManager := TInterfaceList.Create(); +end; + +finalization + writeln('Finalize AudioManager'); + singleton_AudioManager.clear; + FreeAndNil( singleton_AudioManager ); + end. -- cgit v1.2.3 From 8c923b5b76bb17e00132a0b2b2b96de34265fc63 Mon Sep 17 00:00:00 2001 From: jaybinks Date: Tue, 16 Oct 2007 11:27:23 +0000 Subject: modified ffmpeg usage, to use interface same as bass... still needs some tidy up, but its working. :) git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@515 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UMusic.pas | 142 ++++++++++++++++++++++++++++++++----------- 1 file changed, 106 insertions(+), 36 deletions(-) (limited to 'Game/Code/Classes/UMusic.pas') diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas index 8aa59d41..88d845f7 100644 --- a/Game/Code/Classes/UMusic.pas +++ b/Game/Code/Classes/UMusic.pas @@ -8,8 +8,7 @@ interface {$MODE Delphi} {$ENDIF} -uses Classes // UCommon - ; +uses Classes ; type TMuzyka = record @@ -94,23 +93,58 @@ type end; type - IAudioPlayback = Interface + IGenericPlayback = Interface + ['{63A5EBC3-3F4D-4F23-8DFB-B5165FCE33DD}'] + function GetName: String; + + function Open(Name: string): boolean; // true if succeed + procedure Close; + + procedure Play; + procedure Pause; + procedure Stop; + + procedure MoveTo(Time: real); + function getPosition: real; + + property position : real READ getPosition WRITE MoveTo; + end; + + IVideoPlayback = Interface( IGenericPlayback ) + ['{3574C40C-28AE-4201-B3D1-3D1F0759B131}'] +(* + procedure FFmpegOpenFile(FileName: pAnsiChar); + procedure FFmpegClose; + + procedure FFmpegGetFrame(Time: Extended); + procedure FFmpegDrawGL(Screen: integer); + procedure FFmpegTogglePause; + procedure FFmpegSkip(Time: Single); +*) + procedure init(); + + procedure FFmpegGetFrame(Time: Extended); // WANT TO RENAME THESE TO BE MORE GENERIC + procedure FFmpegDrawGL(Screen: integer); // WANT TO RENAME THESE TO BE MORE GENERIC + + end; + + IAudioPlayback = Interface( IGenericPlayback ) ['{E4AE0B40-3C21-4DC5-847C-20A87E0DFB96}'] - function GetName: String; procedure InitializePlayback; procedure SetVolume(Volume: integer); procedure SetMusicVolume(Volume: integer); procedure SetLoop(Enabled: boolean); - function Open(Name: string): boolean; // true if succeed +// function Open(Name: string): boolean; // true if succeed procedure Rewind; - procedure MoveTo(Time: real); - procedure Play; - procedure Pause; //Pause Mod - procedure Stop; - procedure Close; +// procedure MoveTo(Time: real); +// procedure Play; +// procedure Pause; +// procedure Stop; +// procedure Close; function Finished: boolean; function Length: real; - function Position: real; +// function getPosition: real; + procedure PlayStart; procedure PlayBack; procedure PlaySwoosh; @@ -159,6 +193,7 @@ var // TODO : JB --- THESE SHOULD NOT BE GLOBAL procedure InitializeSound; +function VideoPlayback(): IVideoPlayback; function AudioPlayback(): IAudioPlayback; function AudioInput(): IAudioInput; @@ -168,21 +203,30 @@ function AudioManager: TInterfaceList; implementation uses - sysutils, - uLog; + sysutils; +// uLog; var - singleton_AudioPlayback : IAudioPlayback; - singleton_AudioInput : IAudioInput; - singleton_AudioManager : TInterfaceList; + singleton_VideoPlayback : IVideoPlayback = nil; + singleton_AudioPlayback : IAudioPlayback = nil; + singleton_AudioInput : IAudioInput = 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 AudioPlayback(): IAudioPlayback; begin result := singleton_AudioPlayback; @@ -195,45 +239,71 @@ end; procedure InitializeSound; var - lTmpPlayBack : IAudioPlayback; - lTmpInput : IAudioInput; - iCount : Integer; + lTmpInterface : IInterface; + iCount : Integer; begin - lTmpPlayBack := nil; - lTmpInput := nil; + lTmpInterface := nil; + + singleton_AudioPlayback := nil; + singleton_AudioInput := nil; + singleton_VideoPlayback := nil; writeln( 'InitializeSound , Enumerate Registered Audio Interfaces' ); - for iCount := 0 to singleton_AudioManager.Count - 1 do + 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, lTmpPlayBack ) = 0 ) AND - ( not assigned( singleton_AudioPlayback ) ) then + + if ( AudioManager[iCount].QueryInterface( IAudioPlayback, lTmpInterface ) = 0 ) AND + ( true ) then +// ( not assigned( singleton_AudioPlayback ) ) then begin - singleton_AudioPlayback := lTmpPlayBack; + singleton_AudioPlayback := IAudioPlayback( lTmpInterface ); end; // if this interface is a Input, then set it as the default used - if ( AudioManager[iCount].QueryInterface( IAudioInput, lTmpInput ) = 0 ) AND - ( not assigned( singleton_AudioInput ) ) then + if ( AudioManager[iCount].QueryInterface( IAudioInput, lTmpInterface ) = 0 ) AND + ( true ) then +// ( not assigned( singleton_AudioInput ) ) then begin - singleton_AudioInput := lTmpInput; + singleton_AudioInput := IAudioInput( 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 +// ( not assigned( singleton_VideoPlayback ) ) then + begin + singleton_VideoPlayback := IVideoPlayback( lTmpInterface ); + end; + end; end; - writeln( 'Registered Audio Playback Interface : ' + AudioPlayback.GetName ); - writeln( 'Registered Audio Input Interface : ' + AudioInput.GetName ); + if VideoPlayback <> nil then + begin + writeln( 'Registered Video Playback Interface : ' + VideoPlayback.GetName ); + end; + + if AudioPlayback <> nil then + begin + writeln( 'Registered Audio Playback Interface : ' + AudioPlayback.GetName ); + // Log.LogStatus('Initializing Playback ('+AudioPlayback.GetName+')', 'InitializeSound'); + AudioPlayback.InitializePlayback; + end; + + if AudioInput <> nil then + begin + writeln( 'Registered Audio Input Interface : ' + AudioInput.GetName ); + +// Log.LogStatus('Initializing Record ('+AudioPlayback.GetName+')', 'InitializeSound'); + AudioInput.InitializeRecord; + end; - // Initialize Playback - Log.LogStatus('Initializing Playback ('+AudioPlayback.GetName+')', 'InitializeSound'); - AudioPlayback.InitializePlayback; + writeln( 'InitializeSound DONE' ); - // Initialize Input - Log.LogStatus('Initializing Record ('+AudioPlayback.GetName+')', 'InitializeSound'); - AudioInput.InitializeRecord; end; initialization -- cgit v1.2.3 From cdf2eb843e60cb4712080430a9f43f8e68e26069 Mon Sep 17 00:00:00 2001 From: jaybinks Date: Wed, 24 Oct 2007 12:14:03 +0000 Subject: modifed bitmap fonts to have alpha channel, after conversation with blindy. modified ultrastar.lpr to get linux version running as it should be ( after mods I did in windows ) git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@525 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UMusic.pas | 110 +++++++++++++++++++++---------------------- 1 file changed, 55 insertions(+), 55 deletions(-) (limited to 'Game/Code/Classes/UMusic.pas') diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas index 88d845f7..f3342625 100644 --- a/Game/Code/Classes/UMusic.pas +++ b/Game/Code/Classes/UMusic.pas @@ -94,13 +94,13 @@ type type IGenericPlayback = Interface - ['{63A5EBC3-3F4D-4F23-8DFB-B5165FCE33DD}'] - function GetName: String; - - function Open(Name: string): boolean; // true if succeed - procedure Close; - - procedure Play; + ['{63A5EBC3-3F4D-4F23-8DFB-B5165FCE33DD}'] + function GetName: String; + + function Open(Name: string): boolean; // true if succeed + procedure Close; + + procedure Play; procedure Pause; procedure Stop; @@ -108,24 +108,24 @@ type function getPosition: real; property position : real READ getPosition WRITE MoveTo; - end; + end; IVideoPlayback = Interface( IGenericPlayback ) - ['{3574C40C-28AE-4201-B3D1-3D1F0759B131}'] -(* - procedure FFmpegOpenFile(FileName: pAnsiChar); + ['{3574C40C-28AE-4201-B3D1-3D1F0759B131}'] +(* + procedure FFmpegOpenFile(FileName: pAnsiChar); procedure FFmpegClose; procedure FFmpegGetFrame(Time: Extended); procedure FFmpegDrawGL(Screen: integer); procedure FFmpegTogglePause; procedure FFmpegSkip(Time: Single); -*) - procedure init(); - - procedure FFmpegGetFrame(Time: Extended); // WANT TO RENAME THESE TO BE MORE GENERIC +*) + procedure init(); + + procedure FFmpegGetFrame(Time: Extended); // WANT TO RENAME THESE TO BE MORE GENERIC procedure FFmpegDrawGL(Screen: integer); // WANT TO RENAME THESE TO BE MORE GENERIC - + end; IAudioPlayback = Interface( IGenericPlayback ) @@ -212,13 +212,13 @@ var singleton_AudioInput : IAudioInput = nil; singleton_AudioManager : TInterfaceList = nil; - -function AudioManager: TInterfaceList; -begin - if singleton_AudioManager = nil then - singleton_AudioManager := TInterfaceList.Create(); - - Result := singleton_AudioManager; + +function AudioManager: TInterfaceList; +begin + if singleton_AudioManager = nil then + singleton_AudioManager := TInterfaceList.Create(); + + Result := singleton_AudioManager; end; //CompressionPluginManager @@ -234,7 +234,7 @@ end; function AudioInput(): IAudioInput; begin - result := singleton_AudioInput; + result := singleton_AudioInput; end; procedure InitializeSound; @@ -253,33 +253,33 @@ begin 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 + // if this interface is a Playback, then set it as the default used + + if ( AudioManager[iCount].QueryInterface( IAudioPlayback, lTmpInterface ) = 0 ) AND + ( true ) then // ( not assigned( singleton_AudioPlayback ) ) 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 -// ( not assigned( singleton_AudioInput ) ) then + 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 +// ( not assigned( singleton_AudioInput ) ) then begin - singleton_AudioInput := IAudioInput( 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 -// ( not assigned( singleton_VideoPlayback ) ) then + singleton_AudioInput := IAudioInput( 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 +// ( not assigned( singleton_VideoPlayback ) ) then begin - singleton_VideoPlayback := IVideoPlayback( lTmpInterface ); - end; - - end; - end; + singleton_VideoPlayback := IVideoPlayback( lTmpInterface ); + end; + + end; + end; if VideoPlayback <> nil then @@ -307,14 +307,14 @@ begin end; initialization -begin - writeln('Init AudioManager'); - singleton_AudioManager := TInterfaceList.Create(); -end; - -finalization - writeln('Finalize AudioManager'); - singleton_AudioManager.clear; +begin + writeln('Init AudioManager'); + singleton_AudioManager := TInterfaceList.Create(); +end; + +finalization + writeln('Finalize AudioManager'); + singleton_AudioManager.clear; FreeAndNil( singleton_AudioManager ); end. -- cgit v1.2.3 From 391d30716d48dc709f6444b19c008e82311623b9 Mon Sep 17 00:00:00 2001 From: eddie-0815 Date: Thu, 1 Nov 2007 19:34:40 +0000 Subject: Mac OS X version compiles and links. I hope I didn't break too many files on windows/linux. Added switches.inc to all files. Changed many IFDEFs. For Windows-only code please use MSWINDOWS instead of WIN32 now. WIN32 is also used by the Mac port. git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@546 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UMusic.pas | 4 ---- 1 file changed, 4 deletions(-) (limited to 'Game/Code/Classes/UMusic.pas') diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas index f3342625..e2d2cc60 100644 --- a/Game/Code/Classes/UMusic.pas +++ b/Game/Code/Classes/UMusic.pas @@ -4,10 +4,6 @@ interface {$I switches.inc} -{$IFDEF FPC} - {$MODE Delphi} -{$ENDIF} - uses Classes ; type -- cgit v1.2.3 From 99955c78f63d1cb0d8bec666bc33953590a74c8a Mon Sep 17 00:00:00 2001 From: jaybinks Date: Thu, 1 Nov 2007 23:22:01 +0000 Subject: fixed failed builds build:USDX-LAZLIN-75 build:USDX-LAZLIN-76 for some reason we can not use {$MODE Delphi} in an included file. ( Probably because of the way the compier scopes this switch to each pas file ) ive had to revert this part of eddies changes. git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@548 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UMusic.pas | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'Game/Code/Classes/UMusic.pas') diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas index e2d2cc60..3fc1136b 100644 --- a/Game/Code/Classes/UMusic.pas +++ b/Game/Code/Classes/UMusic.pas @@ -2,6 +2,10 @@ unit UMusic; interface +{$IFDEF FPC} + {$MODE Delphi} +{$ENDIF} + {$I switches.inc} uses Classes ; -- cgit v1.2.3 From 80c11b3e86ee826e66640711f11f927472f6ce47 Mon Sep 17 00:00:00 2001 From: tobigun Date: Wed, 5 Dec 2007 21:41:56 +0000 Subject: - Moved GetFFTData from IAudioInput -> IAudioOutput (it is used for the song-selection equalizer not for mic-input) - CaptureCard/StopCard is not visible to public anymore git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@668 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UMusic.pas | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'Game/Code/Classes/UMusic.pas') diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas index 3fc1136b..feba3f61 100644 --- a/Game/Code/Classes/UMusic.pas +++ b/Game/Code/Classes/UMusic.pas @@ -162,6 +162,9 @@ type //Custom Sounds function LoadCustomSound(const Filename: String): Cardinal; procedure PlayCustomSound(const Index: Cardinal ); + + //Equalizer + function GetFFTData: TFFTData; end; IAudioInput = Interface @@ -171,12 +174,6 @@ type procedure CaptureStart; procedure CaptureStop; - - procedure CaptureCard(RecordI, PlayerLeft, PlayerRight: byte); - procedure StopCard(Card: byte); - - //Equalizer - function GetFFTData: TFFTData; end; -- cgit v1.2.3 From 486ad8796acc5883ef83f3a78cd615f6711d77f0 Mon Sep 17 00:00:00 2001 From: jaybinks Date: Thu, 6 Dec 2007 09:39:49 +0000 Subject: conformed projectM to IVideoPlayback still needs a little work. git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@678 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UMusic.pas | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'Game/Code/Classes/UMusic.pas') diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas index feba3f61..18ec2944 100644 --- a/Game/Code/Classes/UMusic.pas +++ b/Game/Code/Classes/UMusic.pas @@ -123,8 +123,8 @@ type *) procedure init(); - procedure FFmpegGetFrame(Time: Extended); // WANT TO RENAME THESE TO BE MORE GENERIC - procedure FFmpegDrawGL(Screen: integer); // WANT TO RENAME THESE TO BE MORE GENERIC + 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; @@ -265,6 +265,7 @@ begin // ( not assigned( singleton_AudioInput ) ) then begin singleton_AudioInput := IAudioInput( lTmpInterface ); + Writeln(singleton_AudioInput.GetName); end; // if this interface is a Input, then set it as the default used -- cgit v1.2.3 From 27ca028ea19879bb3b109c58bae86b61e60b3370 Mon Sep 17 00:00:00 2001 From: tobigun Date: Thu, 6 Dec 2007 10:40:15 +0000 Subject: Visualizer changes (audio connection, some opengl fixes) git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@679 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UMusic.pas | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'Game/Code/Classes/UMusic.pas') diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas index 18ec2944..4acbb55a 100644 --- a/Game/Code/Classes/UMusic.pas +++ b/Game/Code/Classes/UMusic.pas @@ -83,7 +83,10 @@ type Source: array of string; end; - TFFTData = array [0..256] of Single; + TFFTData = array[0..256] of Single; + + TPCMStereoSample = array[0..1] of Smallint; + TPCMData = array[0..511] of TPCMStereoSample; hStream = Cardinal; @@ -165,6 +168,9 @@ type //Equalizer function GetFFTData: TFFTData; + + // Interface for Visualizer + function GetPCMData(var data: TPCMData): Cardinal; end; IAudioInput = Interface -- cgit v1.2.3 From be68ff31e2d10d5f29894c6ec4ed877c70c142a3 Mon Sep 17 00:00:00 2001 From: jaybinks Date: Thu, 6 Dec 2007 12:26:05 +0000 Subject: gave priority to videos over Visualization... so now video plays back... and "V" will switch between Video ( or jpg ) background and visualization. this needs to be pressed on every song, as the state should be forgotten. git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@687 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UMusic.pas | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'Game/Code/Classes/UMusic.pas') diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas index 4acbb55a..2cdcc707 100644 --- a/Game/Code/Classes/UMusic.pas +++ b/Game/Code/Classes/UMusic.pas @@ -131,6 +131,10 @@ type end; + IVideoVisualization = Interface( IVideoPlayback ) + ['{5AC17D60-B34D-478D-B632-EB00D4078017}'] + end; + IAudioPlayback = Interface( IGenericPlayback ) ['{E4AE0B40-3C21-4DC5-847C-20A87E0DFB96}'] procedure InitializePlayback; @@ -195,7 +199,8 @@ var // TODO : JB --- THESE SHOULD NOT BE GLOBAL procedure InitializeSound; - + +function Visualization(): IVideoPlayback; function VideoPlayback(): IVideoPlayback; function AudioPlayback(): IAudioPlayback; function AudioInput(): IAudioInput; @@ -210,9 +215,11 @@ uses // uLog; var - singleton_VideoPlayback : IVideoPlayback = nil; + singleton_VideoPlayback : IVideoPlayback = nil; + singleton_Visualization : IVideoPlayback = nil; singleton_AudioPlayback : IAudioPlayback = nil; singleton_AudioInput : IAudioInput = nil; + singleton_AudioManager : TInterfaceList = nil; @@ -230,6 +237,11 @@ begin result := singleton_VideoPlayback; end; +function Visualization(): IVideoPlayback; +begin + result := singleton_Visualization; +end; + function AudioPlayback(): IAudioPlayback; begin result := singleton_AudioPlayback; @@ -250,6 +262,7 @@ begin singleton_AudioPlayback := nil; singleton_AudioInput := nil; singleton_VideoPlayback := nil; + singleton_Visualization := nil; writeln( 'InitializeSound , Enumerate Registered Audio Interfaces' ); for iCount := 0 to AudioManager.Count - 1 do @@ -276,12 +289,19 @@ begin // if this interface is a Input, then set it as the default used if ( AudioManager[iCount].QueryInterface( IVideoPlayback, lTmpInterface ) = 0 ) AND + //( AudioManager[iCount].QueryInterface( IVideoVisualization, lTmpInterface ) <> 0 ) AND ( true ) then // ( not assigned( singleton_VideoPlayback ) ) then begin singleton_VideoPlayback := IVideoPlayback( lTmpInterface ); end; + if ( AudioManager[iCount].QueryInterface( IVideoVisualization, lTmpInterface ) = 0 ) AND + ( true ) then + begin + singleton_Visualization := IVideoPlayback( lTmpInterface ); + end; + end; end; -- cgit v1.2.3 From 425ff834dbc3933475ee8f783eea6167e92ec174 Mon Sep 17 00:00:00 2001 From: jaybinks Date: Fri, 7 Dec 2007 04:32:38 +0000 Subject: little bit of tidy up.. added command line switch, to see what media interfaces are being used. moved RandomPCM Data generation to Visualizer class. added Visualization preset change, on new line ( may be a little to much... maybe we should do ever 4 or 16 bars or something ?) git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@697 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UMusic.pas | 58 +++++++++++++++++--------------------------- 1 file changed, 22 insertions(+), 36 deletions(-) (limited to 'Game/Code/Classes/UMusic.pas') diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas index 2cdcc707..7e1aa839 100644 --- a/Game/Code/Classes/UMusic.pas +++ b/Game/Code/Classes/UMusic.pas @@ -109,21 +109,12 @@ type procedure MoveTo(Time: real); function getPosition: real; - - property position : real READ getPosition WRITE MoveTo; + + property position : real READ getPosition WRITE MoveTo; end; IVideoPlayback = Interface( IGenericPlayback ) ['{3574C40C-28AE-4201-B3D1-3D1F0759B131}'] -(* - procedure FFmpegOpenFile(FileName: pAnsiChar); - procedure FFmpegClose; - - procedure FFmpegGetFrame(Time: Extended); - procedure FFmpegDrawGL(Screen: integer); - procedure FFmpegTogglePause; - procedure FFmpegSkip(Time: Single); -*) procedure init(); procedure GetFrame(Time: Extended); // WANT TO RENAME THESE TO BE MORE GENERIC @@ -141,16 +132,10 @@ type procedure SetVolume(Volume: integer); procedure SetMusicVolume(Volume: integer); procedure SetLoop(Enabled: boolean); -// function Open(Name: string): boolean; // true if succeed + procedure Rewind; -// procedure MoveTo(Time: real); -// procedure Play; -// procedure Pause; -// procedure Stop; -// procedure Close; - function Finished: boolean; - function Length: real; -// function getPosition: real; + function Finished: boolean; + function Length: real; procedure PlayStart; procedure PlayBack; @@ -211,7 +196,8 @@ function AudioManager: TInterfaceList; implementation uses - sysutils; + sysutils, + UCommandLine; // uLog; var @@ -264,7 +250,6 @@ begin singleton_VideoPlayback := nil; singleton_Visualization := nil; - writeln( 'InitializeSound , Enumerate Registered Audio Interfaces' ); for iCount := 0 to AudioManager.Count - 1 do begin if assigned( AudioManager[iCount] ) then @@ -273,7 +258,6 @@ begin if ( AudioManager[iCount].QueryInterface( IAudioPlayback, lTmpInterface ) = 0 ) AND ( true ) then -// ( not assigned( singleton_AudioPlayback ) ) then begin singleton_AudioPlayback := IAudioPlayback( lTmpInterface ); end; @@ -281,17 +265,13 @@ begin // if this interface is a Input, then set it as the default used if ( AudioManager[iCount].QueryInterface( IAudioInput, lTmpInterface ) = 0 ) AND ( true ) then -// ( not assigned( singleton_AudioInput ) ) then begin singleton_AudioInput := IAudioInput( lTmpInterface ); - Writeln(singleton_AudioInput.GetName); end; // if this interface is a Input, then set it as the default used if ( AudioManager[iCount].QueryInterface( IVideoPlayback, lTmpInterface ) = 0 ) AND - //( AudioManager[iCount].QueryInterface( IVideoVisualization, lTmpInterface ) <> 0 ) AND ( true ) then -// ( not assigned( singleton_VideoPlayback ) ) then begin singleton_VideoPlayback := IVideoPlayback( lTmpInterface ); end; @@ -306,38 +286,44 @@ begin end; + if VideoPlayback <> nil then begin - writeln( 'Registered Video Playback Interface : ' + VideoPlayback.GetName ); end; if AudioPlayback <> nil then begin - writeln( 'Registered Audio Playback Interface : ' + AudioPlayback.GetName ); - // Log.LogStatus('Initializing Playback ('+AudioPlayback.GetName+')', 'InitializeSound'); AudioPlayback.InitializePlayback; end; if AudioInput <> nil then begin - writeln( 'Registered Audio Input Interface : ' + AudioInput.GetName ); - -// Log.LogStatus('Initializing Record ('+AudioPlayback.GetName+')', 'InitializeSound'); AudioInput.InitializeRecord; end; - writeln( 'InitializeSound DONE' ); + if FindCmdLineSwitch( cMediaInterfaces ) then + begin + writeln( '' ); + writeln( '--------------------------------------------------------------' ); + writeln( ' In-use Media Interfaces ' ); + writeln( '--------------------------------------------------------------' ); + writeln( 'Registered Audio Playback Interface : ' + AudioPlayback.GetName ); + writeln( 'Registered Audio Input Interface : ' + AudioInput.GetName ); + writeln( 'Registered Video Playback Interface : ' + VideoPlayback.GetName ); + writeln( 'Registered Visualization Interface : ' + Visualization.GetName ); + writeln( '--------------------------------------------------------------' ); + writeln( '' ); + halt; + end; end; initialization begin - writeln('Init AudioManager'); singleton_AudioManager := TInterfaceList.Create(); end; finalization - writeln('Finalize AudioManager'); singleton_AudioManager.clear; FreeAndNil( singleton_AudioManager ); -- cgit v1.2.3 From 58ffcecef49caacf566150ea266453fbf61930e9 Mon Sep 17 00:00:00 2001 From: tobigun Date: Mon, 17 Dec 2007 11:20:56 +0000 Subject: - removed hStream in favour of TAudioOutputStream - removed all this BASS-specific sound-names git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@708 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UMusic.pas | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'Game/Code/Classes/UMusic.pas') diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas index 7e1aa839..c2d616ec 100644 --- a/Game/Code/Classes/UMusic.pas +++ b/Game/Code/Classes/UMusic.pas @@ -88,11 +88,12 @@ type TPCMStereoSample = array[0..1] of Smallint; TPCMData = array[0..511] of TPCMStereoSample; - hStream = Cardinal; + TAudioOutputStream = class + end; TCustomSoundEntry = record Filename : String; - Handle : hStream; + Stream : TAudioOutputStream; end; type @@ -149,7 +150,8 @@ type procedure PlayShuffle; procedure StopShuffle; - function LoadSoundFromFile(var hStream: hStream; Name: string): boolean; + // TODO + //function LoadSoundFromFile(var stream: TAudioOutputStream; Name: string): boolean; //Custom Sounds function LoadCustomSound(const Filename: String): Cardinal; -- cgit v1.2.3 From ff1dc556936cef441e105a19aa9d1d3b9e0cc833 Mon Sep 17 00:00:00 2001 From: tobigun Date: Fri, 11 Jan 2008 13:52:44 +0000 Subject: changed from ffmpeg-free (audio) to ffmpeg-enabled (if turned on in switches.inc) version. BASS is used by default. git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@786 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UMusic.pas | 112 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 101 insertions(+), 11 deletions(-) (limited to 'Game/Code/Classes/UMusic.pas') diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas index c2d616ec..bf366130 100644 --- a/Game/Code/Classes/UMusic.pas +++ b/Game/Code/Classes/UMusic.pas @@ -83,17 +83,72 @@ type Source: array of string; end; +type TFFTData = array[0..256] of Single; TPCMStereoSample = array[0..1] of Smallint; TPCMData = array[0..511] of TPCMStereoSample; - TAudioOutputStream = class +type + TStreamStatus = (sStopped, sPlaying, sPaused); +const + StreamStatusStr: array[TStreamStatus] of string = ('Stopped', 'Playing', 'Paused'); + +type + TAudioProcessingStream = class + public + procedure Close(); virtual; abstract; + end; + + TAudioPlaybackStream = class(TAudioProcessingStream) + protected + function GetLoop(): boolean; virtual; abstract; + procedure SetLoop(Enabled: boolean); virtual; abstract; + function GetLength(): real; virtual; abstract; + function GetStatus(): TStreamStatus; virtual; abstract; + public + procedure Play(); virtual; abstract; + procedure Pause(); virtual; abstract; + procedure Stop(); virtual; abstract; + + property Loop: boolean READ GetLoop WRITE SetLoop; + property Length: real READ GetLength; + property Status: TStreamStatus READ GetStatus; end; + (* + TAudioMixerStream = class(TAudioProcessingStream) + procedure AddStream(stream: TAudioProcessingStream); + procedure RemoveStream(stream: TAudioProcessingStream); + procedure SetMasterVolume(volume: cardinal); + function GetMasterVolume(): cardinal; + procedure SetStreamVolume(stream: TAudioProcessingStream; volume: cardinal); + function GetStreamVolume(stream: TAudioProcessingStream): cardinal; + end; + *) + + TAudioDecodeStream = class(TAudioProcessingStream) + protected + function GetLength(): real; virtual; abstract; + function GetChannelCount(): cardinal; virtual; abstract; + function GetSampleRate(): cardinal; virtual; abstract; + function GetPosition(): real; virtual; abstract; + procedure SetPosition(Time: real); virtual; abstract; + function IsEOF(): boolean; virtual; abstract; + public + function ReadData(Buffer: PChar; BufSize: integer): integer; virtual; abstract; + + property Length: real READ GetLength; + property ChannelCount: cardinal READ GetChannelCount; + property SampleRate: cardinal READ GetSampleRate; + property Position: real READ GetPosition WRITE SetPosition; + property EOF: boolean READ IsEOF; + end; + +type TCustomSoundEntry = record Filename : String; - Stream : TAudioOutputStream; + Stream : TAudioPlaybackStream; end; type @@ -101,23 +156,23 @@ type ['{63A5EBC3-3F4D-4F23-8DFB-B5165FCE33DD}'] function GetName: String; - function Open(Name: string): boolean; // true if succeed + function Open(Filename: string): boolean; // true if succeed procedure Close; procedure Play; procedure Pause; procedure Stop; - procedure MoveTo(Time: real); - function getPosition: real; - - property position : real READ getPosition WRITE MoveTo; + procedure SetPosition(Time: real); + function GetPosition: real; + + property Position : real READ GetPosition WRITE SetPosition; end; IVideoPlayback = Interface( IGenericPlayback ) ['{3574C40C-28AE-4201-B3D1-3D1F0759B131}'] procedure init(); - + procedure GetFrame(Time: Extended); // WANT TO RENAME THESE TO BE MORE GENERIC procedure DrawGL(Screen: integer); // WANT TO RENAME THESE TO BE MORE GENERIC @@ -150,9 +205,6 @@ type procedure PlayShuffle; procedure StopShuffle; - // TODO - //function LoadSoundFromFile(var stream: TAudioOutputStream; Name: string): boolean; - //Custom Sounds function LoadCustomSound(const Filename: String): Cardinal; procedure PlayCustomSound(const Index: Cardinal ); @@ -164,6 +216,24 @@ type function GetPCMData(var data: TPCMData): Cardinal; end; + IGenericDecoder = Interface + ['{557B0E9A-604D-47E4-B826-13769F3E10B7}'] + function InitializeDecoder(): boolean; + //function IsSupported(const Filename: string): boolean; + end; + + (* + IVideoDecoder = Interface( IGenericDecoder ) + ['{2F184B2B-FE69-44D5-9031-0A2462391DCA}'] + function Open(const Filename: string): TVideoDecodeStream; + end; + *) + + IAudioDecoder = Interface( IGenericDecoder ) + ['{AB47B1B6-2AA9-4410-BF8C-EC79561B5478}'] + function Open(const Filename: string): TAudioDecodeStream; + end; + IAudioInput = Interface ['{A5C8DA92-2A0C-4AB2-849B-2F7448C6003A}'] function GetName: String; @@ -191,6 +261,7 @@ function Visualization(): IVideoPlayback; function VideoPlayback(): IVideoPlayback; function AudioPlayback(): IAudioPlayback; function AudioInput(): IAudioInput; +function AudioDecoder(): IAudioDecoder; function AudioManager: TInterfaceList; @@ -207,6 +278,7 @@ var singleton_Visualization : IVideoPlayback = nil; singleton_AudioPlayback : IAudioPlayback = nil; singleton_AudioInput : IAudioInput = nil; + singleton_AudioDecoder : IAudioDecoder = nil; singleton_AudioManager : TInterfaceList = nil; @@ -240,6 +312,11 @@ begin result := singleton_AudioInput; end; +function AudioDecoder(): IAudioDecoder; +begin + result := singleton_AudioDecoder; +end; + procedure InitializeSound; var lTmpInterface : IInterface; @@ -249,6 +326,7 @@ begin singleton_AudioPlayback := nil; singleton_AudioInput := nil; + singleton_AudioDecoder := nil; singleton_VideoPlayback := nil; singleton_Visualization := nil; @@ -271,6 +349,13 @@ begin singleton_AudioInput := IAudioInput( lTmpInterface ); end; + // if this interface is a Decoder, then set it as the default used + if ( AudioManager[iCount].QueryInterface( IAudioDecoder, lTmpInterface ) = 0 ) AND + ( true ) then + begin + singleton_AudioDecoder := IAudioDecoder( lTmpInterface ); + end; + // if this interface is a Input, then set it as the default used if ( AudioManager[iCount].QueryInterface( IVideoPlayback, lTmpInterface ) = 0 ) AND ( true ) then @@ -293,6 +378,11 @@ begin begin end; + if AudioDecoder <> nil then + begin + AudioDecoder.InitializeDecoder; + end; + if AudioPlayback <> nil then begin AudioPlayback.InitializePlayback; -- cgit v1.2.3 From e74bd57c12f470257111c1c0530fb38f0fd34414 Mon Sep 17 00:00:00 2001 From: jaybinks Date: Sat, 12 Jan 2008 12:31:43 +0000 Subject: bunch of smaller changes... some changes to song loading... Record global changed to singleton object started implementing mic volume display in Settings-Record hope this dosnt break anything.. :P git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@789 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UMusic.pas | 1 + 1 file changed, 1 insertion(+) (limited to 'Game/Code/Classes/UMusic.pas') diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas index bf366130..a7f1918f 100644 --- a/Game/Code/Classes/UMusic.pas +++ b/Game/Code/Classes/UMusic.pas @@ -413,6 +413,7 @@ end; initialization begin singleton_AudioManager := TInterfaceList.Create(); + end; finalization -- cgit v1.2.3 From dee94f5dae9e6b5ae6c7b54a12a567745abc8dc3 Mon Sep 17 00:00:00 2001 From: tobigun Date: Tue, 5 Feb 2008 20:36:19 +0000 Subject: 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 --- Game/Code/Classes/UMusic.pas | 915 +++++++++++++++++++++++-------------------- 1 file changed, 492 insertions(+), 423 deletions(-) (limited to 'Game/Code/Classes/UMusic.pas') 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. -- cgit v1.2.3 From 51a8b92b1696c8ff27523de753a7c6a743a817de Mon Sep 17 00:00:00 2001 From: tobigun Date: Thu, 7 Feb 2008 18:38:51 +0000 Subject: Audio output working again git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@838 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UMusic.pas | 2 -- 1 file changed, 2 deletions(-) (limited to 'Game/Code/Classes/UMusic.pas') diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas index 27ab86e1..b06e226d 100644 --- a/Game/Code/Classes/UMusic.pas +++ b/Game/Code/Classes/UMusic.pas @@ -444,13 +444,11 @@ begin //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'); -- cgit v1.2.3 From 00b2331d0b1a08651374c56cce898f501a2d5104 Mon Sep 17 00:00:00 2001 From: jaybinks Date: Tue, 12 Feb 2008 12:18:57 +0000 Subject: changed InitializeSound to be responsive to failed module initializations, and to remove the module and try again. EG... in my case, sound card driver problems. ALSA is installed but wouldnt open the audio device. now it fails, and the output module goes to the next available ( if there is any ) then gracefully fails to dummy. git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@845 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UMusic.pas | 53 ++++++++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 14 deletions(-) (limited to 'Game/Code/Classes/UMusic.pas') diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas index b06e226d..8bbd297a 100644 --- a/Game/Code/Classes/UMusic.pas +++ b/Game/Code/Classes/UMusic.pas @@ -341,18 +341,14 @@ begin result := singleton_AudioDecoder; end; -procedure InitializeSound; +procedure AssignSingletonObjects(); 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 @@ -361,34 +357,34 @@ begin // if this interface is a Playback, then set it as the default used if ( AudioManager[iCount].QueryInterface( IAudioPlayback, lTmpInterface ) = 0 ) AND - ( true ) then + ( true ) then //not assigned( singleton_AudioPlayback ) ) 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 + ( true ) then //not assigned( singleton_AudioInput ) ) 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 + ( true ) then //not assigned( singleton_AudioDecoder ) ) 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 + ( true ) then //not assigned( singleton_VideoPlayback ) ) then begin singleton_VideoPlayback := IVideoPlayback( lTmpInterface ); end; if ( AudioManager[iCount].QueryInterface( IVideoVisualization, lTmpInterface ) = 0 ) AND - ( true ) then + ( true ) then //not assigned( singleton_Visualization ) ) then begin singleton_Visualization := IVideoPlayback( lTmpInterface ); end; @@ -396,6 +392,17 @@ begin end; end; +end; + +procedure InitializeSound; +begin + singleton_AudioPlayback := nil; + singleton_AudioInput := nil; + singleton_AudioDecoder := nil; + singleton_VideoPlayback := nil; + singleton_Visualization := nil; + + AssignSingletonObjects(); if VideoPlayback <> nil then @@ -404,17 +411,35 @@ begin if AudioDecoder <> nil then begin - AudioDecoder.InitializeDecoder; + while not AudioDecoder.InitializeDecoder do + begin + //writeln('Initialize failed, Removing - '+ AudioDecoder.GetName ); + AudioManager.remove( AudioDecoder ); + singleton_AudioDecoder := nil; + AssignSingletonObjects(); + end; end; if AudioPlayback <> nil then begin - AudioPlayback.InitializePlayback; + while not AudioPlayback.InitializePlayback do + begin + writeln('Initialize failed, Removing - '+ AudioPlayback.GetName ); + AudioManager.remove( AudioPlayback ); + singleton_AudioPlayback := nil; + AssignSingletonObjects(); + end; end; if AudioInput <> nil then begin - AudioInput.InitializeRecord; + while not AudioInput.InitializeRecord do + begin + writeln('Initialize failed, Removing - '+ AudioInput.GetName ); + AudioManager.remove( AudioInput ); + singleton_AudioInput := nil; + AssignSingletonObjects(); + end; end; // Load in-game sounds -- cgit v1.2.3