298 lines
7.2 KiB
ObjectPascal
298 lines
7.2 KiB
ObjectPascal
|
(*
|
||
|
* BASS Recording example for Delphi
|
||
|
*)
|
||
|
|
||
|
unit Unit1;
|
||
|
|
||
|
interface
|
||
|
|
||
|
uses
|
||
|
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
|
||
|
StdCtrls, Bass, ExtCtrls, ComCtrls;
|
||
|
|
||
|
type
|
||
|
WAVHDR = packed record
|
||
|
riff: array[0..3] of AnsiChar;
|
||
|
len: DWord;
|
||
|
cWavFmt: array[0..7] of AnsiChar;
|
||
|
dwHdrLen: DWord;
|
||
|
wFormat: Word;
|
||
|
wNumChannels: Word;
|
||
|
dwSampleRate: DWord;
|
||
|
dwBytesPerSec: DWord;
|
||
|
wBlockAlign: Word;
|
||
|
wBitsPerSample: Word;
|
||
|
cData: array[0..3] of AnsiChar;
|
||
|
dwDataLen: DWord;
|
||
|
end;
|
||
|
|
||
|
type
|
||
|
TForm1 = class(TForm)
|
||
|
ComboBox1: TComboBox;
|
||
|
bRecord: TButton;
|
||
|
bPlay: TButton;
|
||
|
Label1: TLabel;
|
||
|
TrackBar1: TTrackBar;
|
||
|
Bevel1: TBevel;
|
||
|
bSave: TButton;
|
||
|
lPos: TLabel;
|
||
|
PosTimer: TTimer;
|
||
|
SaveDialog: TSaveDialog;
|
||
|
Label2 : TLabel;
|
||
|
procedure FormCreate(Sender: TObject);
|
||
|
procedure FormClose(Sender: TObject; var Action: TCloseAction);
|
||
|
procedure FormDestroy(Sender: TObject);
|
||
|
procedure bRecordClick(Sender: TObject);
|
||
|
procedure bPlayClick(Sender: TObject);
|
||
|
procedure ComboBox1Change(Sender: TObject);
|
||
|
procedure StartRecording;
|
||
|
procedure StopRecording;
|
||
|
procedure PosTimerTimer(Sender: TObject);
|
||
|
procedure UpdateInputInfo;
|
||
|
procedure TrackBar1Change(Sender: TObject);
|
||
|
procedure bSaveClick(Sender: TObject);
|
||
|
private
|
||
|
{ Private declarations }
|
||
|
WaveStream: TMemoryStream;
|
||
|
public
|
||
|
{ Public declarations }
|
||
|
end;
|
||
|
|
||
|
|
||
|
var
|
||
|
Form1: TForm1;
|
||
|
WaveHdr: WAVHDR; // WAV header
|
||
|
rchan: HRECORD; // recording channel
|
||
|
chan: HSTREAM; // playback channel
|
||
|
|
||
|
|
||
|
implementation
|
||
|
|
||
|
{$R *.dfm}
|
||
|
|
||
|
|
||
|
(* This is called while recording audio *)
|
||
|
function RecordingCallback(Handle: HRECORD; buffer: Pointer; length: DWORD; user: Pointer): boolean; stdcall;
|
||
|
begin
|
||
|
// Copy new buffer contents to the memory buffer
|
||
|
Form1.WaveStream.Write(buffer^, length);
|
||
|
// Allow recording to continue
|
||
|
Result := True;
|
||
|
end;
|
||
|
|
||
|
|
||
|
(* Initialize BASS, form controls, memory stream *)
|
||
|
procedure TForm1.FormCreate(Sender: TObject);
|
||
|
var
|
||
|
i: Integer;
|
||
|
dName: PAnsiChar;
|
||
|
level: Single;
|
||
|
begin
|
||
|
// check the correct BASS was loaded
|
||
|
if (HIWORD(BASS_GetVersion) <> BASSVERSION) then
|
||
|
begin
|
||
|
MessageBox(0,'An incorrect version of BASS.DLL was loaded', nil,MB_ICONERROR);
|
||
|
Halt;
|
||
|
end;
|
||
|
if (not BASS_RecordInit(-1)) or (not BASS_Init(-1, 44100, 0, Handle, nil)) then
|
||
|
begin
|
||
|
BASS_RecordFree;
|
||
|
BASS_Free();
|
||
|
MessageDlg('Cannot start default recording device!', mtError, [mbOk], 0);
|
||
|
Halt;
|
||
|
end;
|
||
|
WaveStream := TMemoryStream.Create;
|
||
|
i := 0;
|
||
|
dName := BASS_RecordGetInputName(i);
|
||
|
while dName <> nil do
|
||
|
begin
|
||
|
ComboBox1.Items.Add(StrPas(dName));
|
||
|
// is this one currently "on"?
|
||
|
if (BASS_RecordGetInput(i, level) and BASS_INPUT_OFF) = 0 then
|
||
|
ComboBox1.ItemIndex := i;
|
||
|
Inc(i);
|
||
|
dName := BASS_RecordGetInputName(i);
|
||
|
end;
|
||
|
ComboBox1Change(Self); // display info
|
||
|
end;
|
||
|
|
||
|
|
||
|
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
|
||
|
begin
|
||
|
Action := caFree;
|
||
|
end;
|
||
|
|
||
|
|
||
|
(* Application closing, release stuff *)
|
||
|
procedure TForm1.FormDestroy(Sender: TObject);
|
||
|
begin
|
||
|
WaveStream.Free;
|
||
|
BASS_RecordFree;
|
||
|
BASS_Free;
|
||
|
BASS_Stop;
|
||
|
end;
|
||
|
|
||
|
|
||
|
(* Start recording to memory *)
|
||
|
procedure TForm1.StartRecording;
|
||
|
begin
|
||
|
if ComboBox1.ItemIndex < 0 then Exit;
|
||
|
if WaveStream.Size > 0 then
|
||
|
begin // free old recording
|
||
|
BASS_StreamFree(chan);
|
||
|
WaveStream.Clear;
|
||
|
end;
|
||
|
// generate header for WAV file
|
||
|
with WaveHdr do
|
||
|
begin
|
||
|
riff := 'RIFF';
|
||
|
len := 36;
|
||
|
cWavFmt := 'WAVEfmt ';
|
||
|
dwHdrLen := 16;
|
||
|
wFormat := 1;
|
||
|
wNumChannels := 2;
|
||
|
dwSampleRate := 44100;
|
||
|
wBlockAlign := 4;
|
||
|
dwBytesPerSec := 176400;
|
||
|
wBitsPerSample := 16;
|
||
|
cData := 'data';
|
||
|
dwDataLen := 0;
|
||
|
end;
|
||
|
WaveStream.Write(WaveHdr, SizeOf(WAVHDR));
|
||
|
// start recording @ 44100hz 16-bit stereo
|
||
|
rchan := BASS_RecordStart(44100, 2, 0, @RecordingCallback, nil);
|
||
|
if rchan = 0 then
|
||
|
begin
|
||
|
MessageDlg('Couldn''t start recording!', mtError, [mbOk], 0);
|
||
|
WaveStream.Clear;
|
||
|
end
|
||
|
else
|
||
|
begin
|
||
|
bRecord.Caption := 'Stop';
|
||
|
bPlay.Enabled := False;
|
||
|
bSave.Enabled := False;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
|
||
|
(* Stop recording *)
|
||
|
procedure TForm1.StopRecording;
|
||
|
var
|
||
|
i: integer;
|
||
|
begin
|
||
|
BASS_ChannelStop(rchan);
|
||
|
bRecord.Caption := 'Record';
|
||
|
// 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
|
||
|
chan := BASS_StreamCreateFile(True, WaveStream.Memory, 0, WaveStream.Size, 0);
|
||
|
if chan <> 0 then
|
||
|
begin
|
||
|
// enable "Play" & "Save" buttons
|
||
|
bPlay.Enabled := True;
|
||
|
bSave.Enabled := True;
|
||
|
end
|
||
|
else
|
||
|
MessageDlg('Error creating stream from recorded data!', mtError, [mbOk], 0);
|
||
|
end;
|
||
|
|
||
|
|
||
|
(* Start/stop recording *)
|
||
|
procedure TForm1.bRecordClick(Sender: TObject);
|
||
|
begin
|
||
|
if BASS_ChannelIsActive(rchan) <> 0
|
||
|
then StopRecording
|
||
|
else StartRecording;
|
||
|
end;
|
||
|
|
||
|
|
||
|
(* Play the recorded data *)
|
||
|
procedure TForm1.bPlayClick(Sender: TObject);
|
||
|
begin
|
||
|
BASS_ChannelPlay(chan, True);
|
||
|
end;
|
||
|
|
||
|
|
||
|
(* Change recording input *)
|
||
|
procedure TForm1.ComboBox1Change(Sender: TObject);
|
||
|
var
|
||
|
i: Integer;
|
||
|
r: Boolean;
|
||
|
begin
|
||
|
// enable the selected input
|
||
|
r := True;
|
||
|
i := 0;
|
||
|
// first disable all inputs, then...
|
||
|
while r do
|
||
|
begin
|
||
|
r := BASS_RecordSetInput(i, BASS_INPUT_OFF, -1);
|
||
|
Inc(i);
|
||
|
end;
|
||
|
// ...enable the selected.
|
||
|
BASS_RecordSetInput(ComboBox1.ItemIndex, BASS_INPUT_ON, -1);
|
||
|
UpdateInputInfo; // update info
|
||
|
end;
|
||
|
|
||
|
|
||
|
procedure TForm1.UpdateInputInfo;
|
||
|
var
|
||
|
i: DWord;
|
||
|
level: Single;
|
||
|
begin
|
||
|
I := BASS_RecordGetInput(ComboBox1.ItemIndex, level);
|
||
|
TrackBar1.Position := Round(level * 100); // set the level slider
|
||
|
Label2.Caption := IntToStr(TrackBar1.Position);
|
||
|
|
||
|
case (i and BASS_INPUT_TYPE_MASK) of
|
||
|
BASS_INPUT_TYPE_DIGITAL: Label1.Caption := 'digital';
|
||
|
BASS_INPUT_TYPE_LINE: Label1.Caption := 'line-in';
|
||
|
BASS_INPUT_TYPE_MIC: Label1.Caption := 'microphone';
|
||
|
BASS_INPUT_TYPE_SYNTH: Label1.Caption := 'midi synth';
|
||
|
BASS_INPUT_TYPE_CD: Label1.Caption := 'analog cd';
|
||
|
BASS_INPUT_TYPE_PHONE: Label1.Caption := 'telephone';
|
||
|
BASS_INPUT_TYPE_SPEAKER: Label1.Caption := 'pc speaker';
|
||
|
BASS_INPUT_TYPE_WAVE: Label1.Caption := 'wave/pcm';
|
||
|
BASS_INPUT_TYPE_AUX: Label1.Caption := 'aux';
|
||
|
BASS_INPUT_TYPE_ANALOG: Label1.Caption := 'analog';
|
||
|
else
|
||
|
Label1.Caption := 'undefined';
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
|
||
|
(* Update rec/playback position display *)
|
||
|
procedure TForm1.PosTimerTimer(Sender: TObject);
|
||
|
begin
|
||
|
if WaveStream.Size < 1 then Exit;
|
||
|
if BASS_ChannelIsActive(chan) = BASS_ACTIVE_STOPPED then
|
||
|
lPos.Caption := IntToStr(WaveStream.Size) else
|
||
|
lPos.Caption := IntToStr(BASS_ChannelGetPosition(chan, BASS_POS_BYTE)) + ' / ' + IntToStr(WaveStream.Size);
|
||
|
end;
|
||
|
|
||
|
|
||
|
(* Set recording volume *)
|
||
|
procedure TForm1.TrackBar1Change(Sender: TObject);
|
||
|
begin
|
||
|
BASS_RecordSetInput(ComboBox1.ItemIndex, 0, TrackBar1.Position / 100);
|
||
|
Label2.Caption := IntToStr(TrackBar1.Position);
|
||
|
|
||
|
end;
|
||
|
|
||
|
|
||
|
(* Save recorded audio to WAV file *)
|
||
|
procedure TForm1.bSaveClick(Sender: TObject);
|
||
|
begin
|
||
|
if SaveDialog.Execute then
|
||
|
WaveStream.SaveToFile(SaveDialog.FileName);
|
||
|
end;
|
||
|
|
||
|
|
||
|
end.
|
||
|
|