aboutsummaryrefslogtreecommitdiffstats
path: root/Game/Code/Classes/UAudio_bass.pas
diff options
context:
space:
mode:
authortobigun <tobigun@b956fd51-792f-4845-bead-9b4dfca2ff2c>2007-12-05 21:48:59 +0000
committertobigun <tobigun@b956fd51-792f-4845-bead-9b4dfca2ff2c>2007-12-05 21:48:59 +0000
commit21e5e8cec6f253ec24b5116b4020dc62bb2a80b1 (patch)
treea5ec230fa9aded26e14a899fe21c8f2ae804c17e /Game/Code/Classes/UAudio_bass.pas
parent80c11b3e86ee826e66640711f11f927472f6ce47 (diff)
downloadusdx-21e5e8cec6f253ec24b5116b4020dc62bb2a80b1.tar.gz
usdx-21e5e8cec6f253ec24b5116b4020dc62bb2a80b1.tar.xz
usdx-21e5e8cec6f253ec24b5116b4020dc62bb2a80b1.zip
- Moved initialization from URecord to UAudio_bass.
- Removed duplicate registration at AudioManager - separated input an output functions so input-functionality can be switched on and off with the UseBASSInput define - Removed HWND Windows stuff git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@669 b956fd51-792f-4845-bead-9b4dfca2ff2c
Diffstat (limited to '')
-rw-r--r--Game/Code/Classes/UAudio_bass.pas1297
1 files changed, 648 insertions, 649 deletions
diff --git a/Game/Code/Classes/UAudio_bass.pas b/Game/Code/Classes/UAudio_bass.pas
index 9ef3b789..bcf01f92 100644
--- a/Game/Code/Classes/UAudio_bass.pas
+++ b/Game/Code/Classes/UAudio_bass.pas
@@ -1,649 +1,648 @@
-unit UAudio_bass;
-
-interface
-
-{$IFDEF FPC}
- {$MODE Delphi}
-{$ENDIF}
-
-{$I switches.inc}
-
-
-uses Classes,
- {$IFDEF win32}
- windows,
- {$ENDIF}
- Messages,
- SysUtils,
- {$IFNDEF FPC}
- Forms,
- {$ENDIF}
-
- bass,
- ULog,
- UMusic;
-
-implementation
-
-uses
- {$IFDEF LAZARUS}
- lclintf,
- {$ENDIF}
- URecord,
- UIni,
- UMain,
- UCommon,
- UThemes;
-
-const
- RecordSystem = 1;
-
-type
- TMPModes = (mpNotReady, mpStopped, mpPlaying, mpRecording, mpSeeking,
- mpPaused, mpOpen);
-
-const
- ModeStr: array[TMPModes] of string = ('Not ready', 'Stopped', 'Playing', 'Recording', 'Seeking', 'Paused', 'Open');
-
-type
- TAudio_bass = class( TInterfacedObject, IAudioPlayback, IAudioInput )
- 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;
- fHWND: THandle;
-
- public
- Bass: hStream;
- function GetName: String;
- 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 getPosition: 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;
-
-var
- singleton_MusicBass : IAudioPlayback;
-
-function TAudio_bass.GetName: String;
-begin
- result := 'BASS';
-end;
-
-procedure TAudio_bass.InitializePlayback;
-var
- Pet: integer;
- S: integer;
-begin
- writeln( 'TAudio_bass.InitializePlayback' );
-// Log.BenchmarkStart(4);
-// Log.LogStatus('Initializing Playback Subsystem', 'Music Initialize');
-
- Loaded := false;
- Loop := false;
-
-
- writeln( 'TAudio_bass AllocateHWND' );
- {$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}
-
-
- writeln( 'TAudio_bass BASS_Init' );
- // 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;
-
-// Log.BenchmarkEnd(4); Log.LogBenchmark('--> Bass Init', 4);
-
- // config playing buffer
-// BASS_SetConfig(BASS_CONFIG_UPDATEPERIOD, 10);
-// BASS_SetConfig(BASS_CONFIG_BUFFER, 100);
-
-// Log.LogStatus('Loading Sounds', 'Music Initialize');
-
- writeln( 'TAudio_bass LoadSoundFromFile' );
-// Log.BenchmarkStart(4);
- LoadSoundFromFile(BassStart, SoundPath + 'Common Start.mp3');
- LoadSoundFromFile(BassBack, SoundPath + 'Common Back.mp3');
- LoadSoundFromFile(BassSwoosh, SoundPath + 'menu swoosh.mp3');
- LoadSoundFromFile(BassChange, SoundPath + 'select music change music 50.mp3');
- LoadSoundFromFile(BassOption, SoundPath + 'option change col.mp3');
- LoadSoundFromFile(BassClick, SoundPath + 'rimshot022b.mp3');
-
-// LoadSoundFromFile(BassDrum, SoundPath + 'bassdrumhard076b.mp3');
-// LoadSoundFromFile(BassHihat, SoundPath + 'hihatclosed068b.mp3');
-// LoadSoundFromFile(BassClap, SoundPath + 'claps050b.mp3');
-
-// LoadSoundFromFile(BassShuffle, SoundPath + 'Shuffle.mp3');
-
-// Log.BenchmarkEnd(4);
-// Log.LogBenchmark('--> Loading Sounds', 4);
-end;
-
-procedure TAudio_bass.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 TAudio_bass.SetVolume(Volume: integer);
-begin
- //Old Sets Wave Volume
- //BASS_SetVolume(Volume);
- //New: Sets Volume only for this Application
-
-
- // 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);
-end;
-
-procedure TAudio_bass.SetMusicVolume(Volume: Integer);
-begin
- //Max Volume Prevention
- if Volume > 100 then
- Volume := 100;
-
- if Volume < 0 then
- Volume := 0;
-
-
- //Set Volume
- // TODO : jb_linux replace with something other than bass
- BASS_ChannelSetAttributes (Bass, -1, Volume, -101);
-end;
-
-procedure TAudio_bass.SetLoop(Enabled: boolean);
-begin
- Loop := Enabled;
-end;
-
-function TAudio_bass.Open(Name: string): boolean;
-begin
- Loaded := false;
- if FileExists(Name) then
- begin
- // TODO : jb_linux replace with something other than bass
- Bass := Bass_StreamCreateFile(false, pchar(Name), 0, 0, 0);
-
- Loaded := true;
- //Set Max Volume
- SetMusicVolume (100);
- end;
-
- Result := Loaded;
-end;
-
-procedure TAudio_bass.Rewind;
-begin
- if Loaded then begin
- end;
-end;
-
-procedure TAudio_bass.MoveTo(Time: real);
-var
- bytes: integer;
-begin
- // TODO : jb_linux replace with something other than bass
- bytes := BASS_ChannelSeconds2Bytes(Bass, Time);
- BASS_ChannelSetPosition(Bass, bytes);
-end;
-
-procedure TAudio_bass.Play;
-begin
- // 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 TAudio_bass Class
-
- BASS_ChannelPlay(Bass, False); // for setting position before playing
- end;
-end;
-
-procedure TAudio_bass.Pause; //Pause Mod
-begin
- // TODO : jb_linux replace with something other than bass
- if Loaded then begin
- BASS_ChannelPause(Bass); // Pauses Song
- end;
-end;
-
-procedure TAudio_bass.Stop;
-begin
- // TODO : jb_linux replace with something other than bass
- Bass_ChannelStop(Bass);
-end;
-
-procedure TAudio_bass.Close;
-begin
- // TODO : jb_linux replace with something other than bass
- Bass_StreamFree(Bass);
-end;
-
-function TAudio_bass.Length: real;
-var
- bytes: integer;
-begin
- Result := 60;
-
- // TODO : jb_linux replace with something other than bass
- bytes := BASS_ChannelGetLength(Bass);
- Result := BASS_ChannelBytes2Seconds(Bass, bytes);
-end;
-
-function TAudio_bass.getPosition: real;
-var
- bytes: integer;
-begin
- Result := 0;
-
- // TODO : jb_linux replace with something other than bass
- bytes := BASS_ChannelGetPosition(BASS);
- Result := BASS_ChannelBytes2Seconds(BASS, bytes);
-end;
-
-function TAudio_bass.Finished: boolean;
-begin
- Result := false;
-
- // TODO : jb_linux replace with something other than bass
- if BASS_ChannelIsActive(BASS) = BASS_ACTIVE_STOPPED then
- begin
- Result := true;
- end;
-end;
-
-procedure TAudio_bass.PlayStart;
-begin
- // TODO : jb_linux replace with something other than bass
- BASS_ChannelPlay(BassStart, True);
-end;
-
-procedure TAudio_bass.PlayBack;
-begin
- // TODO : jb_linux replace with something other than bass
- BASS_ChannelPlay(BassBack, True);// then
-end;
-
-procedure TAudio_bass.PlaySwoosh;
-begin
- // TODO : jb_linux replace with something other than bass
- BASS_ChannelPlay(BassSwoosh, True);
-end;
-
-procedure TAudio_bass.PlayChange;
-begin
- // TODO : jb_linux replace with something other than bass
- BASS_ChannelPlay(BassChange, True);
-end;
-
-procedure TAudio_bass.PlayOption;
-begin
- // TODO : jb_linux replace with something other than bass
- BASS_ChannelPlay(BassOption, True);
-end;
-
-procedure TAudio_bass.PlayClick;
-begin
- // TODO : jb_linux replace with something other than bass
- BASS_ChannelPlay(BassClick, True);
-end;
-
-procedure TAudio_bass.PlayDrum;
-begin
- // TODO : jb_linux replace with something other than bass
- BASS_ChannelPlay(BassDrum, True);
-end;
-
-procedure TAudio_bass.PlayHihat;
-begin
- // TODO : jb_linux replace with something other than bass
- BASS_ChannelPlay(BassHihat, True);
-end;
-
-procedure TAudio_bass.PlayClap;
-begin
- // TODO : jb_linux replace with something other than bass
- BASS_ChannelPlay(BassClap, True);
-end;
-
-procedure TAudio_bass.PlayShuffle;
-begin
- // TODO : jb_linux replace with something other than bass
- BASS_ChannelPlay(BassShuffle, True);
-end;
-
-procedure TAudio_bass.StopShuffle;
-begin
- // TODO : jb_linux replace with something other than bass
- BASS_ChannelStop(BassShuffle);
-end;
-
-procedure TAudio_bass.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 TAudio_bass.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 TAudio_bass.CaptureCard(RecordI, SoundNum, PlayerLeft, PlayerRight: byte);
-procedure TAudio_bass.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 TAudio_bass.StopCard(Card: byte);
-begin
- // TODO : jb_linux replace with something other than bass
- BASS_RecordSetDevice(Card);
- BASS_RecordFree;
-end;
-
-function TAudio_bass.LoadSoundFromFile(var hStream: hStream; Name: string): boolean;
-var
- L: Integer;
-begin
- if FileExists(Name) then
- begin
- Log.LogStatus('Loading Sound: "' + Name + '"', 'LoadSoundFromFile');
- try
- // TODO : jb_linux replace with something other than bass
- hStream := BASS_StreamCreateFile(False, pchar(Name), 0, 0, 0);
-
- //Add CustomSound
- L := High(CustomSounds) + 1;
- SetLength (CustomSounds, L + 1);
- CustomSounds[L].Filename := Name;
- CustomSounds[L].Handle := hStream;
- except
- Log.LogError('Failed to open using BASS', 'LoadSoundFromFile');
- end;
- end
- else
- begin
- Log.LogError('Sound not found: "' + Name + '"', 'LoadSoundFromFile');
- exit;
- end;
-end;
-
-//Equalizer
-function TAudio_bass.GetFFTData: TFFTData;
-var
- Data: TFFTData;
-begin
- //Get Channel Data Mono and 256 Values
- BASS_ChannelGetData(Bass, @Result, BASS_DATA_FFT512);
-end;
-
-function TAudio_bass.LoadCustomSound(const Filename: String): Cardinal;
-var
- S: hStream;
- I: Integer;
- F: String;
-begin
- //Search for Sound in already loaded Sounds
- F := UpperCase(SoundPath + FileName);
- For I := 0 to High(CustomSounds) do
- begin
- if (UpperCase(CustomSounds[I].Filename) = F) then
- begin
- Result := I;
- Exit;
- end;
- end;
-
- if LoadSoundFromFile(S, SoundPath + Filename) then
- Result := High(CustomSounds)
- else
- Result := 0;
-end;
-
-procedure TAudio_bass.PlayCustomSound(const Index: Cardinal );
-begin
- if Index <= High(CustomSounds) then
- BASS_ChannelPlay(CustomSounds[Index].Handle, True);
-end;
-
-
-{*
-
-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 TAudio_bass ( 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 TAudio_bass.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; *}
-
-initialization
- singleton_MusicBass := TAudio_bass.create();
-
- writeln( 'UAudio_Bass - Register Playback' );
- AudioManager.add( IAudioPlayback( singleton_MusicBass ) );
-
- writeln( 'UAudio_Bass - Register Input' );
- AudioManager.add( IAudioInput( singleton_MusicBass ) );
-
-finalization
- writeln( 'UAudio_Bass - UnRegister Playback' );
- AudioManager.Remove( IAudioPlayback( singleton_MusicBass ) );
-
- writeln( 'UAudio_Bass - UnRegister Input' );
- AudioManager.Remove( IAudioInput( singleton_MusicBass ) );
-
-end.
+unit UAudio_bass;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+
+uses Classes,
+ {$IFDEF win32}
+ windows,
+ {$ENDIF}
+ Messages,
+ SysUtils,
+ {$IFNDEF FPC}
+ Forms,
+ {$ENDIF}
+ bass,
+ ULog,
+ UMusic;
+
+implementation
+
+uses
+ {$IFDEF LAZARUS}
+ lclintf,
+ {$ENDIF}
+ URecord,
+ UIni,
+ UMain,
+ UCommon,
+ UThemes;
+
+type
+ TMPModes = (mpNotReady, mpStopped, mpPlaying, mpRecording, mpSeeking,
+ mpPaused, mpOpen);
+
+const
+ ModeStr: array[TMPModes] of string = ('Not ready', 'Stopped', 'Playing', 'Recording', 'Seeking', 'Paused', 'Open');
+
+type
+{$IFDEF UseBASSInput}
+ TAudio_bass = class( TInterfacedObject, IAudioPlayback, IAudioInput)
+{$ELSE}
+ TAudio_bass = class( TInterfacedObject, IAudioPlayback)
+{$ENDIF}
+ private
+ BassStart: hStream; // Wait, I've replaced this with BASS
+ BassBack: hStream; // It has almost all features we need
+ BassSwoosh: hStream;
+ BassChange: hStream; // Almost? It aleady has them all :)
+ BassOption: hStream;
+ BassClick: hStream;
+ BassDrum: hStream;
+ BassHihat: hStream;
+ BassClap: hStream;
+ BassShuffle: hStream;
+
+ //Custom Sounds
+ CustomSounds: array of TCustomSoundEntry;
+ Loaded: boolean;
+ Loop: boolean;
+
+ public
+ Bass: hStream;
+ function GetName: String;
+
+ {IAudioOutput interface}
+
+ procedure InitializePlayback;
+ procedure SetVolume(Volume: integer);
+ procedure SetMusicVolume(Volume: integer);
+ procedure SetLoop(Enabled: boolean);
+ function Open(Name: string): boolean; // true if succeed
+ procedure Rewind;
+ procedure MoveTo(Time: real);
+ procedure Play;
+ procedure Pause; //Pause Mod
+ procedure Stop;
+ procedure Close;
+ function Finished: boolean;
+ function Length: real;
+ function getPosition: real;
+ procedure PlayStart;
+ procedure PlayBack;
+ procedure PlaySwoosh;
+ procedure PlayChange;
+ procedure PlayOption;
+ procedure PlayClick;
+ procedure PlayDrum;
+ procedure PlayHihat;
+ procedure PlayClap;
+ procedure PlayShuffle;
+ procedure StopShuffle;
+ function LoadSoundFromFile(var hStream: hStream; Name: string): boolean;
+
+ //Equalizer
+ function GetFFTData: TFFTData;
+
+ //Custom Sounds
+ function LoadCustomSound(const Filename: String): Cardinal;
+ procedure PlayCustomSound(const Index: Cardinal );
+
+ {IAudioInput interface}
+ {$IFDEF UseBASSInput}
+ procedure InitializeRecord;
+
+ procedure CaptureStart;
+ procedure CaptureStop;
+ procedure CaptureCard(Card: byte; CaptureSoundLeft, CaptureSoundRight: TSound);
+ procedure StopCard(Card: byte);
+ {$ENDIF}
+ end;
+
+{$IFDEF UseBASSInput}
+ TBassSoundCard = class(TGenericSoundCard)
+ RecordStream: HSTREAM;
+ end;
+{$ENDIF}
+
+
+var
+ singleton_MusicBass : IAudioPlayback;
+
+function TAudio_bass.GetName: String;
+begin
+ result := 'BASS';
+end;
+
+procedure TAudio_bass.InitializePlayback;
+var
+ Pet: integer;
+ S: integer;
+begin
+ writeln( 'TAudio_bass.InitializePlayback' );
+// Log.BenchmarkStart(4);
+// Log.LogStatus('Initializing Playback Subsystem', 'Music Initialize');
+
+ Loaded := false;
+ Loop := false;
+
+ writeln( 'TAudio_bass BASS_Init' );
+ if not BASS_Init(1, 44100, 0, 0, nil) then
+ begin
+ Log.LogError('Could not initialize BASS', 'Error');
+ Exit;
+ end;
+
+// Log.BenchmarkEnd(4); Log.LogBenchmark('--> Bass Init', 4);
+
+ // config playing buffer
+// BASS_SetConfig(BASS_CONFIG_UPDATEPERIOD, 10);
+// BASS_SetConfig(BASS_CONFIG_BUFFER, 100);
+
+// Log.LogStatus('Loading Sounds', 'Music Initialize');
+
+ writeln( 'TAudio_bass LoadSoundFromFile' );
+// Log.BenchmarkStart(4);
+ LoadSoundFromFile(BassStart, SoundPath + 'Common Start.mp3');
+ LoadSoundFromFile(BassBack, SoundPath + 'Common Back.mp3');
+ LoadSoundFromFile(BassSwoosh, SoundPath + 'menu swoosh.mp3');
+ LoadSoundFromFile(BassChange, SoundPath + 'select music change music 50.mp3');
+ LoadSoundFromFile(BassOption, SoundPath + 'option change col.mp3');
+ LoadSoundFromFile(BassClick, SoundPath + 'rimshot022b.mp3');
+
+// LoadSoundFromFile(BassDrum, SoundPath + 'bassdrumhard076b.mp3');
+// LoadSoundFromFile(BassHihat, SoundPath + 'hihatclosed068b.mp3');
+// LoadSoundFromFile(BassClap, SoundPath + 'claps050b.mp3');
+
+// LoadSoundFromFile(BassShuffle, SoundPath + 'Shuffle.mp3');
+
+// Log.BenchmarkEnd(4);
+// Log.LogBenchmark('--> Loading Sounds', 4);
+end;
+
+procedure TAudio_bass.SetVolume(Volume: integer);
+begin
+ //Old Sets Wave Volume
+ //BASS_SetVolume(Volume);
+ //New: Sets Volume only for this Application
+
+ BASS_SetConfig(BASS_CONFIG_GVOL_SAMPLE, Volume);
+ BASS_SetConfig(BASS_CONFIG_GVOL_STREAM, Volume);
+ BASS_SetConfig(BASS_CONFIG_GVOL_MUSIC, Volume);
+end;
+
+procedure TAudio_bass.SetMusicVolume(Volume: Integer);
+begin
+ //Max Volume Prevention
+ if Volume > 100 then
+ Volume := 100;
+
+ if Volume < 0 then
+ Volume := 0;
+
+
+ //Set Volume
+ // TODO : jb_linux replace with something other than bass
+ BASS_ChannelSetAttributes (Bass, -1, Volume, -101);
+end;
+
+procedure TAudio_bass.SetLoop(Enabled: boolean);
+begin
+ Loop := Enabled;
+end;
+
+function TAudio_bass.Open(Name: string): boolean;
+begin
+ Loaded := false;
+ if FileExists(Name) then
+ begin
+ Bass := Bass_StreamCreateFile(false, pchar(Name), 0, 0, 0);
+
+ Loaded := true;
+ //Set Max Volume
+ SetMusicVolume (100);
+ end;
+
+ Result := Loaded;
+end;
+
+procedure TAudio_bass.Rewind;
+begin
+ if Loaded then begin
+ end;
+end;
+
+procedure TAudio_bass.MoveTo(Time: real);
+var
+ bytes: integer;
+begin
+ bytes := BASS_ChannelSeconds2Bytes(Bass, Time);
+ BASS_ChannelSetPosition(Bass, bytes);
+end;
+
+procedure TAudio_bass.Play;
+begin
+ if Loaded then
+ begin
+ if Loop then
+ BASS_ChannelPlay(Bass, True); // start from beginning... actually bass itself does not loop, nor does this TAudio_bass Class
+
+ BASS_ChannelPlay(Bass, False); // for setting position before playing
+ end;
+end;
+
+procedure TAudio_bass.Pause; //Pause Mod
+begin
+ if Loaded then begin
+ BASS_ChannelPause(Bass); // Pauses Song
+ end;
+end;
+
+procedure TAudio_bass.Stop;
+begin
+ Bass_ChannelStop(Bass);
+end;
+
+procedure TAudio_bass.Close;
+begin
+ Bass_StreamFree(Bass);
+end;
+
+function TAudio_bass.Length: real;
+var
+ bytes: integer;
+begin
+ Result := 60;
+
+ bytes := BASS_ChannelGetLength(Bass);
+ Result := BASS_ChannelBytes2Seconds(Bass, bytes);
+end;
+
+function TAudio_bass.getPosition: real;
+var
+ bytes: integer;
+begin
+ Result := 0;
+
+ bytes := BASS_ChannelGetPosition(BASS);
+ Result := BASS_ChannelBytes2Seconds(BASS, bytes);
+end;
+
+function TAudio_bass.Finished: boolean;
+begin
+ Result := false;
+
+ if BASS_ChannelIsActive(BASS) = BASS_ACTIVE_STOPPED then
+ begin
+ Result := true;
+ end;
+end;
+
+procedure TAudio_bass.PlayStart;
+begin
+ BASS_ChannelPlay(BassStart, True);
+end;
+
+procedure TAudio_bass.PlayBack;
+begin
+ BASS_ChannelPlay(BassBack, True);// then
+end;
+
+procedure TAudio_bass.PlaySwoosh;
+begin
+ BASS_ChannelPlay(BassSwoosh, True);
+end;
+
+procedure TAudio_bass.PlayChange;
+begin
+ BASS_ChannelPlay(BassChange, True);
+end;
+
+procedure TAudio_bass.PlayOption;
+begin
+ BASS_ChannelPlay(BassOption, True);
+end;
+
+procedure TAudio_bass.PlayClick;
+begin
+ BASS_ChannelPlay(BassClick, True);
+end;
+
+procedure TAudio_bass.PlayDrum;
+begin
+ BASS_ChannelPlay(BassDrum, True);
+end;
+
+procedure TAudio_bass.PlayHihat;
+begin
+ BASS_ChannelPlay(BassHihat, True);
+end;
+
+procedure TAudio_bass.PlayClap;
+begin
+ BASS_ChannelPlay(BassClap, True);
+end;
+
+procedure TAudio_bass.PlayShuffle;
+begin
+ BASS_ChannelPlay(BassShuffle, True);
+end;
+
+procedure TAudio_bass.StopShuffle;
+begin
+ BASS_ChannelStop(BassShuffle);
+end;
+
+function TAudio_bass.LoadSoundFromFile(var hStream: hStream; Name: string): boolean;
+var
+ L: Integer;
+begin
+ if FileExists(Name) then
+ begin
+ Log.LogStatus('Loading Sound: "' + Name + '"', 'LoadSoundFromFile');
+ try
+ hStream := BASS_StreamCreateFile(False, pchar(Name), 0, 0, 0);
+
+ //Add CustomSound
+ L := High(CustomSounds) + 1;
+ SetLength (CustomSounds, L + 1);
+ CustomSounds[L].Filename := Name;
+ CustomSounds[L].Handle := hStream;
+ except
+ Log.LogError('Failed to open using BASS', 'LoadSoundFromFile');
+ end;
+ end
+ else
+ begin
+ Log.LogError('Sound not found: "' + Name + '"', 'LoadSoundFromFile');
+ exit;
+ end;
+end;
+
+//Equalizer
+function TAudio_bass.GetFFTData: TFFTData;
+var
+ Data: TFFTData;
+begin
+ //Get Channel Data Mono and 256 Values
+ BASS_ChannelGetData(Bass, @Result, BASS_DATA_FFT512);
+end;
+
+function TAudio_bass.LoadCustomSound(const Filename: String): Cardinal;
+var
+ S: hStream;
+ I: Integer;
+ F: String;
+begin
+ //Search for Sound in already loaded Sounds
+ F := UpperCase(SoundPath + FileName);
+ For I := 0 to High(CustomSounds) do
+ begin
+ if (UpperCase(CustomSounds[I].Filename) = F) then
+ begin
+ Result := I;
+ Exit;
+ end;
+ end;
+
+ if LoadSoundFromFile(S, SoundPath + Filename) then
+ Result := High(CustomSounds)
+ else
+ Result := 0;
+end;
+
+procedure TAudio_bass.PlayCustomSound(const Index: Cardinal );
+begin
+ if Index <= High(CustomSounds) then
+ BASS_ChannelPlay(CustomSounds[Index].Handle, True);
+end;
+
+{$IFDEF UseBASSInput}
+
+procedure TAudio_bass.InitializeRecord;
+var
+ device: integer;
+ Descr: string;
+ input: integer;
+ input2: integer;
+ InputName: PChar;
+ Flags: integer;
+ mic: array[0..15] of integer;
+ SC: integer; // soundcard
+ SCI: integer; // soundcard input
+ No: integer;
+
+function isDuplicate(Desc: String): Boolean;
+var
+ I: Integer;
+begin
+ Result := False;
+ //Check for Soundcard with same Description
+ For I := 0 to SC-1 do
+ begin
+ if (Recording.SoundCard[I].Description = Desc) then
+ begin
+ Result := True;
+ Break;
+ end;
+ end;
+end;
+
+begin
+ with Recording do
+ begin
+ // checks for recording devices and puts them into an array
+ SetLength(SoundCard, 0);
+
+ SC := 0;
+ Descr := BASS_RecordGetDeviceDescription(SC);
+
+ while (Descr <> '') do
+ begin
+ //If there is another SoundCard with the Same ID, Search an available Name
+ if (IsDuplicate(Descr)) then
+ begin
+ No:= 1; //Count of SoundCards with same Name
+ Repeat
+ Inc(No)
+ Until not IsDuplicate(Descr + ' (' + InttoStr(No) + ')');
+
+ //Set Description
+ Descr := Descr + ' (' + InttoStr(No) + ')';
+ end;
+
+ SetLength(SoundCard, SC+1);
+
+ // TODO: free object on termination
+ SoundCard[SC] := TBassSoundCard.Create();
+ SoundCard[SC].Description := Descr;
+
+ //Get Recording Inputs
+ SCI := 0;
+ BASS_RecordInit(SC);
+
+ InputName := BASS_RecordGetInputName(SCI);
+
+ {$IFDEF DARWIN}
+ // Under MacOSX the SingStar Mics have an empty
+ // InputName. So, we have to add a hard coded
+ // Workaround for this problem
+ if (InputName = nil) and (Pos( 'USBMIC Serial#', Descr) > 0) then
+ begin
+ InputName := 'Microphone';
+ end;
+ {$ENDIF}
+
+ SetLength(SoundCard[SC].Input, 1);
+ SoundCard[SC].Input[SCI].Name := InputName;
+
+ // process each input
+ while (InputName <> nil) do
+ begin
+ Flags := BASS_RecordGetInput(SCI);
+ if (SCI >= 1) {AND (Flags AND BASS_INPUT_OFF = 0)} then
+ begin
+ SetLength(SoundCard[SC].Input, SCI+1);
+ SoundCard[SC].Input[SCI].Name := InputName;
+ end;
+
+ //Set Mic Index
+ if ((Flags and BASS_INPUT_TYPE_MIC) = 1) then
+ SoundCard[SC].MicInput := SCI;
+
+ Inc(SCI);
+ InputName := BASS_RecordGetInputName(SCI);
+ end;
+
+ BASS_RecordFree;
+
+ Inc(SC);
+ Descr := BASS_RecordGetDeviceDescription(SC);
+ end; // while
+ end; // with Recording
+end;
+
+// TODO: code is used by all IAudioInput implementors
+// -> move to a common superclass (TAudioInput_Generic?)
+procedure TAudio_bass.CaptureStart;
+var
+ S: integer;
+ SC: integer;
+ PlayerLeft, PlayerRight: integer;
+ CaptureSoundLeft, CaptureSoundRight: TSound;
+begin
+ for S := 0 to High(Recording.Sound) do
+ Recording.Sound[S].BufferLong[0].Clear;
+
+ for SC := 0 to High(Ini.CardList) do begin
+ PlayerLeft := Ini.CardList[SC].ChannelL-1;
+ PlayerRight := Ini.CardList[SC].ChannelR-1;
+ if PlayerLeft >= PlayersPlay then PlayerLeft := -1;
+ if PlayerRight >= PlayersPlay then PlayerRight := -1;
+ if (PlayerLeft > -1) or (PlayerRight > -1) then begin
+ if (PlayerLeft > -1) then
+ CaptureSoundLeft := Recording.Sound[PlayerLeft]
+ else
+ CaptureSoundLeft := nil;
+ if (PlayerRight > -1) then
+ CaptureSoundRight := Recording.Sound[PlayerRight]
+ else
+ CaptureSoundRight := nil;
+
+ CaptureCard(SC, CaptureSoundLeft, CaptureSoundRight);
+ end;
+ end;
+end;
+
+// TODO: code is used by all IAudioInput implementors
+// -> move to a common superclass (TAudioInput_Generic?)
+procedure TAudio_bass.CaptureStop;
+var
+ SC: integer;
+ PlayerLeft: integer;
+ PlayerRight: integer;
+begin
+
+ for SC := 0 to High(Ini.CardList) do begin
+ PlayerLeft := Ini.CardList[SC].ChannelL-1;
+ PlayerRight := Ini.CardList[SC].ChannelR-1;
+ if PlayerLeft >= PlayersPlay then PlayerLeft := -1;
+ if PlayerRight >= PlayersPlay then PlayerRight := -1;
+ if (PlayerLeft > -1) or (PlayerRight > -1) then
+ StopCard(SC);
+ end;
+
+end;
+
+{*
+ * Bass input capture callback.
+ * Params:
+ * stream - BASS input stream
+ * buffer - buffer of captured samples
+ * len - size of buffer in bytes
+ * user - players associated with left/right channels
+ *}
+function MicrophoneCallback(stream: HSTREAM; buffer: Pointer;
+ len: Cardinal; Card: Cardinal): boolean; stdcall;
+begin
+ Recording.HandleMicrophoneData(buffer, len, Recording.SoundCard[Card]);
+ Result := true;
+end;
+
+{*
+ * Start input-capturing on Soundcard specified by Card.
+ * Params:
+ * Card - soundcard index in Recording.SoundCard array
+ * CaptureSoundLeft - sound(-buffer) used for left channel capture data
+ * CaptureSoundRight - sound(-buffer) used for right channel capture data
+ *}
+procedure TAudio_bass.CaptureCard(Card: byte; CaptureSoundLeft, CaptureSoundRight: TSound);
+var
+ Error: integer;
+ ErrorMsg: string;
+ bassSoundCard: TBassSoundCard;
+begin
+ if not BASS_RecordInit(Card) then
+ begin
+ Error := BASS_ErrorGetCode;
+ ErrorMsg := IntToStr(Error);
+ if Error = BASS_ERROR_DX then ErrorMsg := 'No DX5';
+ if Error = BASS_ERROR_ALREADY then ErrorMsg := 'The device has already been initialized';
+ if Error = BASS_ERROR_DEVICE then ErrorMsg := 'The device number specified is invalid';
+ if Error = BASS_ERROR_DRIVER then ErrorMsg := 'There is no available device driver';
+ Log.LogError('Error initializing record [' + IntToStr(Card) + ']');
+ Log.LogError('TAudio_bass.CaptureCard: Error initializing record: ' + ErrorMsg);
+ end
+ else
+ begin
+ bassSoundCard := TBassSoundCard(Recording.SoundCard[Card]);
+ bassSoundCard.CaptureSoundLeft := CaptureSoundLeft;
+ bassSoundCard.CaptureSoundRight := CaptureSoundRight;
+
+ // capture in 44.1kHz/stereo/16bit and a 20ms callback period
+ bassSoundCard.RecordStream :=
+ BASS_RecordStart(44100, 2, MakeLong(0, 20) , @MicrophoneCallback, Card);
+ end;
+end;
+
+{*
+ * Stop input-capturing on Soundcard specified by Card.
+ * Params:
+ * Card - soundcard index in Recording.SoundCard array
+ *}
+procedure TAudio_bass.StopCard(Card: byte);
+begin
+ BASS_RecordSetDevice(Card);
+ BASS_RecordFree;
+end;
+
+{$ENDIF}
+
+
+initialization
+ singleton_MusicBass := TAudio_bass.create();
+
+ writeln( 'UAudio_Bass - Register' );
+ AudioManager.add( singleton_MusicBass );
+
+finalization
+ writeln( 'UAudio_Bass - UnRegister' );
+ AudioManager.Remove( singleton_MusicBass );
+
+end.