unit U_BassPlayer;
interface
uses
bass, Windows, dialogs, Classes, StdCtrls, SysUtils;
type
WAVHDR =
packed record
riff:
array[0..3]
of Char;
len: DWord;
cWavFmt:
array[0..7]
of Char;
dwHdrLen: DWord;
wFormat: Word;
wNumChannels: Word;
dwSampleRate: DWord;
dwBytesPerSec: DWord;
wBlockAlign: Word;
wBitsPerSample: Word;
cData:
array[0..3]
of Char;
dwDataLen: DWord;
end;
TFFTData =
array[0..256]
of Single;
TBassPlayer =
class
private
{ Private declarations }
channel: HSTREAM;
WaveHdr: WAVHDR;
// WAV header
recordchannel: HRECORD;
// recording channel
isrecording: boolean;
FFilename:
string;
procedure setvolume(volume: byte);
{0 bis 100}
function getvolume: byte;
function getposition: integer;
function getlength: integer;
{in sekunden}
function getRightPeak: dword;
function getLeftPeak: dword;
function getstatus: integer;
public
constructor create(mainwindowhandle: HWND);
destructor destroy;
override;
function play(filename:
string): boolean;
function getfftdata: TFFTData;
procedure stop;
procedure pause;
procedure resume;
procedure startrecording(input: integer;filename:
string);
procedure stoprecording;
function getDatasize: int64;
procedure setrecordvolume(input: integer;volume: integer);
procedure initCombobox(Combobox: TCombobox);
procedure ComboBoxChange(Sender: TObject);
property volume: byte
read getvolume
write setvolume;
procedure setposition(position: integer);
property position: integer
read getposition
write setposition;
{in sekunden}
property length: integer
read getlength;
property RightPeak: dword
read getRightPeak;
{von 0 bis 128}
property LeftPeak: dword
read getLeftPeak;
{von 0 bis 128}
property filename:
string read FFilename;
property status: integer
read getstatus;
//STOPPED = 0 PLAYING = 1 STALLED = 2 PAUSED = 3
{ Public declarations }
end;
implementation
var
WaveStream: TFileStream;
//muss leider global deklariert werden wegen callback Funktion
function TBassPlayer.getfftdata: TFFTData;
begin
if (BASS_ChannelGetData(Channel, @Result, BASS_DATA_FFT512) = 2048) = false
then
begin
ZeroMemory(@Result, SizeOf(Result));
end;
end;
function TBassPlayer.getstatus: integer;
begin //STOPPED = 0 PLAYING = 1 STALLED = 2 PAUSED = 3
result := BASS_ChannelIsActive(channel);
end;
function TBassPlayer.getRightPeak: dword;
begin
result := HIWORD(BASS_ChannelGetLevel(channel));
end;
function TBassPlayer.getLeftPeak: dword;
begin
result := LOWORD(BASS_ChannelGetLevel(channel));
end;
function TBassPlayer.getvolume: byte;
begin
result := BASS_GetConfig(BASS_CONFIG_GVOL_STREAM);
end;
procedure TBassPlayer.setvolume(volume: byte);
begin
BASS_SetConfig(BASS_CONFIG_GVOL_STREAM,volume)
end;
function TBassPlayer.getposition: integer;
begin
result := round(BASS_ChannelBytes2Seconds(channel,BASS_ChannelGetPosition(channel)));
end;
procedure TBassPlayer.setposition(position: integer);
begin
BASS_ChannelSetPosition(Channel,BASS_ChannelSeconds2Bytes(Channel, position));
end;
function TBassPlayer.getlength: integer;
begin
result := round(BASS_ChannelBytes2Seconds(channel,BASS_StreamGetLength(channel)));
end;
function TBassPlayer.play(filename:
string): boolean;
begin
If BASS_ChannelIsActive(channel)=1
then
begin
BASS_StreamFree(channel);
end;
FFilename := filename;
channel:=BASS_StreamCreateFile(False,PChar(filename),0,0,BASS_STREAM_AUTOFREE
or BASS_SAMPLE_FX);
result := BASS_StreamPlay(channel,false,0);
end;
procedure TBassPlayer.stop;
begin
BASS_ChannelPause(channel);
position := 0;
end;
procedure TBassPlayer.pause;
begin
BASS_ChannelPause(channel);
end;
procedure TBassPlayer.resume;
begin
BASS_ChannelResume(channel);
end;
constructor TBassPlayer.create(mainwindowhandle: HWND);
begin
inherited create;;
if BASS_GetVersion() <> MAKELONG(2,0)
then
begin
showmessage('
Falsche Version der bass.dll(benötigt wird 2.0)');
Halt;
end;
BASS_Init(1, 44100, 0, mainwindowhandle,
nil);
if not BASS_RecordInit(0)
then
begin
BASS_RecordFree;
BASS_Free();
MessageDlg('
Cannot start default recording device!', mtError, [mbOk], 0);
halt;
end;
isrecording := false;
end;
destructor TBassPlayer.destroy;
begin
BASS_RecordFree;
Bass_streamFree(channel);
BASS_Stop;
BASS_Free;
inherited destroy;
end;
// This is called while recording audio
function RecordingCallback(
Handle: HRECORD; buffer: Pointer; length, user: DWord): boolean;
stdcall;
begin
// Copy new buffer contents to the memory buffer
WaveStream.
Write(buffer^, length);
//Allow recording to continue
Result := True;
end;
procedure TBassPlayer.startrecording(input: integer;filename:
string);
var
i: Integer;
begin
//File Stream
WaveStream := TFileStream.Create(filename,fmCreate);
if WaveStream.Size > 0
then
begin // free old recording
BASS_StreamFree(channel);
end;
// generate header for WAV file
WaveHdr.riff := '
RIFF';
WaveHdr.len := 36;
WaveHdr.cWavFmt := '
WAVEfmt ';
WaveHdr.dwHdrLen := 16;
WaveHdr.wFormat := 1;
WaveHdr.wNumChannels := 2;
WaveHdr.dwSampleRate := 44100;
WaveHdr.wBlockAlign := 4;
WaveHdr.dwBytesPerSec := 176400;
WaveHdr.wBitsPerSample := 16;
WaveHdr.cData := '
data';
WaveHdr.dwDataLen := 0;
WaveStream.
Write(WaveHdr, SizeOf(WAVHDR));
i := 0;
while BASS_RecordSetInput(i, BASS_INPUT_OFF)
do
begin
i := i + 1;
end;
BASS_RecordSetInput(input, BASS_INPUT_ON);
// start recording @ 44100hz 16-bit stereo
recordchannel := BASS_RecordStart(44100, 0, @RecordingCallback, 0);
if recordchannel = 0
then
begin
MessageDlg('
Couldn''
t start recording!', mtError, [mbOk], 0);
WaveStream.Free;
end;
isrecording:= true;
end;
procedure TBassPlayer.stoprecording;
var
i: integer;
begin
BASS_ChannelStop(recordchannel);
// complete the WAV header
WaveStream.Position := 4;
i := WaveStream.Size - 8;
WaveStream.
Write(i, 4);
i := i - $24;
WaveStream.Position := 40;
WaveStream.
Write(i, 4);
WaveStream.Position := 0;
// create a stream from the recorded data
//channel := BASS_StreamCreateFile(false, pchar(FRecordfilename), 0, WaveStream.Size, 0);
{if channel = 0 then
begin
MessageDlg('Error creating stream from recorded data!', mtError, [mbOk], 0);
end;}
WaveStream.Free;
end;
function TBassPlayer.getDatasize: int64;
begin
IF isrecording
then
begin
result:= WaveStream.Size
end
else
begin
result:=0;
end;
end;
procedure TBassPlayer.setrecordvolume(input: integer;volume: integer);
begin
BASS_RecordSetInput(input, BASS_INPUT_LEVEL
or volume);
end;
end.