aboutsummaryrefslogtreecommitdiffstats
path: root/Game/Code/Classes/UAudioInput_Bass.pas
diff options
context:
space:
mode:
Diffstat (limited to 'Game/Code/Classes/UAudioInput_Bass.pas')
-rw-r--r--Game/Code/Classes/UAudioInput_Bass.pas203
1 files changed, 203 insertions, 0 deletions
diff --git a/Game/Code/Classes/UAudioInput_Bass.pas b/Game/Code/Classes/UAudioInput_Bass.pas
new file mode 100644
index 00000000..6d661258
--- /dev/null
+++ b/Game/Code/Classes/UAudioInput_Bass.pas
@@ -0,0 +1,203 @@
+unit UAudioInput_Bass;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+
+uses
+ Classes,
+ SysUtils,
+ URecord,
+ UMusic;
+
+implementation
+
+uses
+ UMain,
+ UIni,
+ ULog,
+ UAudioCore_Bass,
+ Windows,
+ bass;
+
+type
+ TAudioInput_Bass = class(TAudioInputBase)
+ public
+ function GetName: String; override;
+ function InitializeRecord: boolean; override;
+ destructor Destroy; override;
+ end;
+
+ TBassInputDevice = class(TAudioInputDevice)
+ public
+ DeviceIndex: integer; // index in TAudioInputProcessor.Device[]
+ BassDeviceID: integer; // DeviceID used by BASS
+ RecordStream: HSTREAM;
+
+ procedure Start(); override;
+ procedure Stop(); override;
+ end;
+
+var
+ singleton_AudioInputBass : IAudioInput;
+
+
+{ Global }
+
+{*
+ * Bass input capture callback.
+ * Params:
+ * stream - BASS input stream
+ * buffer - buffer of captured samples
+ * len - size of buffer in bytes
+ * user - players associated with left/right channels
+ *}
+function MicrophoneCallback(stream: HSTREAM; buffer: Pointer;
+ len: Cardinal; Card: Cardinal): boolean; stdcall;
+begin
+ AudioInputProcessor.HandleMicrophoneData(buffer, len,
+ AudioInputProcessor.Device[Card]);
+ Result := true;
+end;
+
+
+{ TBassInputDevice }
+
+{*
+ * Start input-capturing on this device.
+ * TODO: call BASS_RecordInit only once
+ *}
+procedure TBassInputDevice.Start();
+const
+ captureFreq = 44100;
+begin
+ // recording already started -> stop first
+ if (RecordStream <> 0) then
+ Stop();
+
+ // TODO: Call once. Otherwise it's to slow
+ if not BASS_RecordInit(BassDeviceID) then
+ begin
+ Log.LogError('TBassInputDevice.Start: Error initializing device['+IntToStr(DeviceIndex)+']: ' +
+ TAudioCore_Bass.ErrorGetString());
+ Exit;
+ end;
+
+ SampleRate := captureFreq;
+
+ // capture in 44.1kHz/stereo/16bit and a 20ms callback period
+ RecordStream := BASS_RecordStart(captureFreq, 2, MakeLong(0, 20),
+ @MicrophoneCallback, DeviceIndex);
+ if (RecordStream = 0) then
+ begin
+ BASS_RecordFree;
+ Exit;
+ end;
+end;
+
+{*
+ * Stop input-capturing on this device.
+ *}
+procedure TBassInputDevice.Stop();
+begin
+ if (RecordStream = 0) then
+ Exit;
+ // TODO: Don't free the device. Do this on close
+ if (BASS_RecordSetDevice(BassDeviceID)) then
+ BASS_RecordFree;
+ RecordStream := 0;
+end;
+
+
+{ TAudioInput_Bass }
+
+function TAudioInput_Bass.GetName: String;
+begin
+ result := 'BASS_Input';
+end;
+
+function TAudioInput_Bass.InitializeRecord(): boolean;
+var
+ Descr: PChar;
+ SourceName: PChar;
+ Flags: integer;
+ BassDeviceID: integer;
+ BassDevice: TBassInputDevice;
+ DeviceIndex: integer;
+ SourceIndex: integer;
+begin
+ result := false;
+
+ DeviceIndex := 0;
+ BassDeviceID := 0;
+ SetLength(AudioInputProcessor.Device, 0);
+
+ // checks for recording devices and puts them into an array
+ while true do
+ begin
+ Descr := BASS_RecordGetDeviceDescription(BassDeviceID);
+ if (Descr = nil) then
+ break;
+
+ SetLength(AudioInputProcessor.Device, DeviceIndex+1);
+
+ // TODO: free object on termination
+ BassDevice := TBassInputDevice.Create();
+ AudioInputProcessor.Device[DeviceIndex] := BassDevice;
+
+ BassDevice.DeviceIndex := DeviceIndex;
+ BassDevice.BassDeviceID := BassDeviceID;
+ BassDevice.Description := UnifyDeviceName(Descr, DeviceIndex);
+
+ // get input sources
+ SourceIndex := 0;
+ BASS_RecordInit(BassDeviceID);
+ BassDevice.MicInput := 0;
+
+ // process each input
+ while true do
+ begin
+ SourceName := BASS_RecordGetInputName(SourceIndex);
+ if (SourceName = nil) then
+ break;
+
+ SetLength(BassDevice.Source, SourceIndex+1);
+ BassDevice.Source[SourceIndex].Name :=
+ UnifyDeviceSourceName(SourceName, BassDevice.Description);
+
+ // set mic index
+ Flags := BASS_RecordGetInput(SourceIndex);
+ if ((Flags and BASS_INPUT_TYPE_MIC) <> 0) then
+ BassDevice.MicInput := SourceIndex;
+
+ Inc(SourceIndex);
+ end;
+
+ BASS_RecordFree;
+
+ Inc(DeviceIndex);
+ Inc(BassDeviceID);
+ end;
+
+ result := true;
+end;
+
+destructor TAudioInput_Bass.Destroy;
+begin
+ inherited;
+end;
+
+
+initialization
+ singleton_AudioInputBass := TAudioInput_Bass.create();
+ AudioManager.add( singleton_AudioInputBass );
+
+finalization
+ AudioManager.Remove( singleton_AudioInputBass );
+
+end.