hi
I had some problems with the wasapi.dll to!
in my case i did not realize, I have two Radeon 7970 graphics card in my system.
which support "high definition audio" so in my case there are 12 devices and which are all disconnect.
so i have 17 devices listed under Control Panel\Sound
and yet my webcam's Device ID = 45 and my speakers Device ID = 13!
It is very confusing!!!
anyway I've put something together. maybe this will help you further
unit Bass_Recorder;
interface
uses
Windows, Classes, SysUtils, Messages,
Dynamic_Bass,
Dynamic_WASAPI,
Dynamic_BassASIO,
Dynamic_DSHOW,
Dynamic_Basscd,
Dynamic_Bassenc,
Dynamic_BassFX,
Dynamic_Bassmix,
Dynamic_Basswma,
Dynamic_Tags,
LibFlac,
LibLame,
LibMac,
LibMpc,
LibOgg,
LibTTA,
LibVorbis,
LibVorbisEnc,
LibVorbisFile,
LibWV,
Bass_Common;
type
TRecorder = class
private
Saved8087CW : WORD; // FPU exceptions
WndHandle : HWND;
EncoderType : TEncoderType;
Cur_DestName : TUnicodeString; (* Already opend fileName *)
New_DestName : TUnicodeString; (* New Fielname *)
WASAPI_IsInit : Boolean;
Channel_Stream : DWORD;
Channel_Mixer : DWORD;
Channel_WASAPI : DWORD;
Channel_Encoder : DWORD;
procedure Set_DestinationFilename(Destination : TUnicodeString);
protected
{ Protected declarations }
procedure WndProc(var Msg: TMessage); virtual;
public
constructor Create();
destructor Destroy; override;
procedure Set_Encoder(Encoder : Integer);
function WASAPI_Init_Device(Device : Integer; Freq : DWORD; Chann : DWORD) : Boolean;
function WASAPI_Start() : Boolean;
function WASAPI_Stop(Flush : Boolean) : Boolean;
function Recorder_Start() : Boolean;
function Recorder_Stop() : Boolean;
end;
implementation
uses
Bass_Tools,
jbWinUtils,
jbMathUtils,
jbStrUtils,
jbFileUtils;
const
WM_RECORDER_UPDATE = WM_USER + 101;
WM_RECORDER_START = 1;
WM_RECORDER_PAUSE = 2;
WM_RECORDER_STOP = 3;
procedure TRecorder.WndProc(var Msg: TMessage); // Todo
begin
inherited;
if Msg.Msg = WM_RECORDER_UPDATE then
case Msg.WParam of
WM_RECORDER_START :;
WM_RECORDER_PAUSE :;
WM_RECORDER_STOP :;
end;
end;
constructor TRecorder.Create();
begin
inherited Create;
(* Thread-safe AllocateHwnd *)
WndHandle:= WMAllocateHWnd(WndProc);
EncoderType:= enWAV;
end;
destructor TRecorder.Destroy;
begin
WMDeallocateHWnd(WndHandle);
inherited Destroy;
end;
(************************** Set Destination Filename **************************)
procedure TRecorder.Set_DestinationFilename(Destination : TUnicodeString);
begin
Cur_DestName:= Destination;
end;
procedure TRecorder.Set_Encoder(Encoder : Integer);
begin
EncoderType:= TEncoderType(Byte(Encoder));
end;
(******************************************************************************)
(* Wasapi Stuf. *)
(******************************************************************************)
function Input_Wasapi_Proc(buffer:Pointer; length:DWORD; user:Pointer): DWORD; stdcall;
var Buff : array [0..50000] of Byte;
Data : DWORD;
begin
with TRecorder(user) do
begin
BASS_StreamPutData(Channel_Stream, buffer, length);
Data:= BASS_ChannelGetData(Channel_Mixer, @Buff, SizeOf(Buff));
if Data = DW_ERROR then
Data:= 0;
Result:= data
end;
end;
function TRecorder.WASAPI_Init_Device(Device : Integer; Freq : DWORD; Chann : DWORD) : Boolean; // ToDo (Freq, Chann)
var
WasapiDevInfo : BASS_WASAPI_DEVICEINFO;
WasapiInfo : BASS_WASAPI_INFO;
DevFlag : DWORD;
StrFlag : DWORD;
begin
Result:= false;
if not Bass_dll_Loaded[BASS_WASAPI_DLL] then
exit;
try
(* Free Device *)
if BASS_WASAPI_SetDevice(DWORD(Device)) then
begin
if BASS_WASAPI_Free() then
WASAPI_IsInit:= false;
end;
DevFlag:= 0;
DevFlag:= DevFlag or
BASS_WASAPI_AUTOFORMAT or (* Automatically choose another sample format if the specified format is not supported.*)
BASS_WASAPI_BUFFER; (* Enable double buffering This requires the BASS "no sound" device to have been initilized, via BASS_Init. *)
(* Initialize the device in shared mode else exclusive *)
if not BASS_WASAPI_Init(Device, 0, 0, DevFlag, 1, 0.1, @Input_Wasapi_Proc, Pointer(Self)) then
begin
// error
exit;
end;
(* Get Wasapi Info *)
BASS_WASAPI_GetInfo(WasapiInfo);
(* Get Wasapi Device Info *)
BASS_WASAPI_GetDeviceInfo(Device, WasapiDevInfo);
StrFlag:= 0;
StrFlag:= StrFlag or
BASS_SAMPLE_FLOAT or
BASS_STREAM_DECODE;
Channel_Stream:= BASS_StreamCreate(WasapiInfo.freq, WasapiInfo.chans, StrFlag, STREAMPROC_PUSH, nil);
if Channel_Stream = 0 then
begin
//Error
exit;
end;
WASAPI_IsInit:= true;
Result:= true;
except
end;
end;
(******************************** Start Device ********************************)
function TRecorder.WASAPI_Start() : Boolean;
begin
Result:= false;
if BASS_WASAPI_IsStarted() then
exit;
Result:= BASS_WASAPI_Start();
if not Result then
begin
//Error
end;
end;
(******************************** Stop Device *********************************)
function TRecorder.WASAPI_Stop(Flush : Boolean) : Boolean;
begin
Result:= BASS_WASAPI_Stop(Flush);
if not Result then
begin
//Error
end;
end;
function TRecorder.Recorder_Start() : Boolean;
var encFlag : DWORD;
begin
case EncoderType of
enWAV:
begin
WASAPI_Stop(true);
Channel_Mixer:= BASS_Mixer_StreamCreate(44100, 2, BASS_STREAM_DECODE);
BASS_Mixer_StreamAddChannel(Channel_Mixer, Channel_Stream, 0);
encFlag:= 0;
encFlag:= encFlag or
BASS_ENCODE_PAUSE or
BASS_ENCODE_PCM or
BASS_UNICODE;
Channel_Encoder:= BASS_Encode_Start(Channel_Mixer, PChar('C:\......\Desktop\New folder (2)\wavetest.wav'), encFlag, nil, nil) ;
WASAPI_Start();
BASS_Encode_SetPaused(Channel_Encoder, false);
end;
enWMA: ;
enMP3: ;
enOGG: ;
enFLAC: ;
enMPC: ;
enOFR: ;
enWV: ;
enMAC: ;
enTTA: ;
enAAC: ;
enMP4: ;
enSPX: ;
enACM: ;
end;
end;
function TRecorder.Recorder_Stop() : Boolean;
begin
BASS_Encode_Stop(Channel_Encoder)
end;
//EncoderType
end.
viel spass mit dem code Martin