音频处理:关于wavein和waveout的使用.

wensusy 2005-01-20 11:22:45
怎样用wavein和waveout分别指定不同的声卡呀?

我现在要用wavein指定到一个固定的虚拟声卡去,用waveout指定到真实声卡,请问怎样寻找真实声卡?怎样指定真实声卡?还有如果系统默认声卡不是我的虚拟声卡我怎么更改默认为虚拟声卡呢?
...全文
909 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
wensusy 2005-01-25
  • 打赏
  • 举报
回复
我要实现的功能是这样的,我要将系统播放出来的声音数据保存下来,我作了一个虚拟声卡,如果将系统默认播放和录音设备改为我作的这个虚拟声卡,那么我通过waveinopen打开这个设备就可以得到系统播放的声音数据。如果系统默认的录音和播放设备不是我作的这个设备,那么我就无法得到这些数据了,所以我必须判断系统默认的录放音设备是否是我作的这个虚拟声卡设备。我现在只知道用
if (waveInOpen (&hwi, WAVE_MAPPER, &waveformat,
(DWORD)handle, 0, CALLBACK_WINDOW) != MMSYSERR_NOERROR)
来打开默认设备,但是这样用
waveInGetDevCaps(WAVE_MAPPER,&pwic,sizeof(WAVEINCAPS)就返回不了当前设备名称,请问怎么解决?

输入设备的名称好像是按名称排列的,对应的ID就是排列顺序,那么不同机器中同一个设备的ID可能不同,一直用这个ID号好像行不通吧。

flyforlove 2005-01-25
  • 打赏
  • 举报
回复
首先确定你要使用哪一个输入设备(根据名字判断),输入设备的名称和设备ID号是对应的,这样以后操作就一直都用这个ID号就可以了。我不知道你想要得是什么功能。

获得硬件信息,好像MMSDK中没有提供这些函数,得通过其他途径,对这方面我没有研究过。
wensusy 2005-01-25
  • 打赏
  • 举报
回复
多谢!

但是我现在要确认当前系统默认的录音设备是否是我要的设备,如果不是我要提示用户更改或者自己强行更改用户的默认录音设备(请问如何强行指定),否则实现不了我的功能的。我无法知道我要的设备是编号0、1或2中的哪一个.

另外,如何在程序中获得系统的硬件声卡(即真正的声卡)是什么型号?
flyforlove 2005-01-25
  • 打赏
  • 举报
回复
if (waveInGetDevCaps(WAVE_MAPPER,&pwic,sizeof(WAVEINCAPS))!= MMSYSERR_NOERROR)

不要使用WAVE_MAPPER,看看名字就知道这是个映射器,既然你要指定具体的输入设备,这个参数就要使用具体的ID号,先用waveInGetNumDevs得到播放器的数目,然后ID号的指定是从0开始,依次递增。
比如你有三个输入设备,那么ID号就是0,1,2
wensusy 2005-01-25
  • 打赏
  • 举报
回复
flyforlove(为情飞) ,多谢你关注此贴

我现在用if (waveInOpen (&hwi, WAVE_MAPPER, &waveformat,
(DWORD)handle, 0, CALLBACK_WINDOW) != MMSYSERR_NOERROR)
打开默认录音设备,用
if (waveInGetDevCaps(WAVE_MAPPER,&pwic,sizeof(WAVEINCAPS))!= MMSYSERR_NOERROR),怎么得到的pwic.szPname是:微软 声音映射器。怎么会这样呀,我要确认的是当前系统默认录音设备是否是我需要用的声卡驱动,得到这样的字符串我就无法确认了。

再次麻烦你了
flyforlove 2005-01-25
  • 打赏
  • 举报
回复
首选设备是保存在注册表的HKEY_CURRENT_USER\Software\Microsoft\Multimedia\Sound Mapper位置,你可以通过查询注册表的形式来判断系统的首选设备到底是不是你的虚拟声卡,

对于更改这个设备,当然也可以通过更改这个注册表的数据来更改,但是更改以后能不能立即生效,因为没有做过这方面的东西,所以不知道,也许像更改默认打印机一样要广播一个消息。

可以提示对话框,让用户自己去更改默认设备。
wensusy 2005-01-25
  • 打赏
  • 举报
回复
我现在倒不是要用程序操控所有的播放软件都指定到我的虚拟声卡上,我是主要想检测当前默认录放音是否为我的虚拟声卡,如果不是就可以提示用户,最好是修改系统的默认播放和录音设备。因为如果不提示我的程序运行时容易让不太懂的用户误会系统出问题。

非常感谢你!
flyforlove 2005-01-25
  • 打赏
  • 举报
回复
我的意思是说,你想要使用的设备名称应该是已知的,既然这样在程序使用设备之前,就可以查找这个设备所对应的ID(不是让你在一台机子上得到一个ID后就在所有机子上都使用这个ID,这显然是行不通的。)。

对于你想纪录声音数据,我想使用WAVE_MAPPER不是总能行得通的,比如说winamp吧,他是可以指定输出设备的,并不一定是用的默认输出设备,如果你想录音的话,就要手工指定你的虚拟声卡作为输出设备。但是显然你很难用程序操控所有的播放软件都指定到你的虚拟声卡上。
flyforlove 2005-01-24
  • 打赏
  • 举报
回复
使用UINT waveInGetNumDevs(VOID);
得到输入设备数目,

然后使用
MMRESULT waveInGetDevCaps(
UINT uDeviceID,
LPWAVEINCAPS pwic,
UINT cbwic
);

得到一个WAVEINCAPS结构体变量的值。
typedef struct {
WORD wMid;
WORD wPid;
MMVERSION vDriverVersion;
CHAR szPname[MAXPNAMELEN]; //这个是产品名称。
DWORD dwFormats;
WORD wChannels;
WORD wReserved1;
} WAVEINCAPS;

wensusy 2005-01-24
  • 打赏
  • 举报
回复
多谢flyforlove(为情飞),我知道waveInOpen和waveoutopen的第二个参数是设备的ID号,问题是我怎么知道我要的设备的ID号是多少呢?设备号的排列应该是按照名称排的吧,那么我装的虚拟声卡可能是设备1,也有可能是设备2呀,怎么知道这个设备的名称呀?多谢了!

waveInGetNumDevs只是得到当前设备数,无法得到当前设备的名称。
Cipherliu 2005-01-24
  • 打赏
  • 举报
回复
看看这个函数的用法
waveInGetNumDevs
getit911 2005-01-24
  • 打赏
  • 举报
回复
找AudioIO控件,是开源的
Cipherliu 2005-01-24
  • 打赏
  • 举报
回复
到MSDN上去查帮助,一定可以找到绑定指定设备的API函数
flyforlove 2005-01-24
  • 打赏
  • 举报
回复
MMRESULT waveInOpen(

LPHWAVEIN phwi,
UINT uDeviceID,
LPWAVEFORMATEX pwfx,
DWORD dwCallback,
DWORD dwCallbackInstance,
DWORD fdwOpen
);

MMRESULT waveOutOpen(

LPHWAVEOUT phwo,
UINT uDeviceID,
LPWAVEFORMATEX pwfx,
DWORD dwCallback,
DWORD dwCallbackInstance,
DWORD fdwOpen
);

第二个参数就是指定设备ID的,0,1,2....
wensusy 2005-01-24
  • 打赏
  • 举报
回复
多谢各位!

我知道waveinopen和waveoutopen的用法,但是我一般都只用于打开系统默认的设备。现在我就是要用他打开非默认的设备,例如,我现在机上装了两个虚拟声卡,一个真实声卡,所以在我机器的默认播放和录音设备就有三个,我现在要用waveinopen指向三个中的一个,waveoutopen指向另外一个,请问这样该怎么作?
Kshape_zh 2005-01-22
  • 打赏
  • 举报
回复
http://search.csdn.net/Expert/topic/952/952985.xml?temp=.8836176
Kshape_zh 2005-01-22
  • 打赏
  • 举报
回复
WaveIn(录音)WaveHdr.lpData Buffer size is Format.nAvgBytesPerSec;
WaveOut(输出)那就想多大就多大,不超过内存即可。

WaveOut:

WaveOutOpen(FWaveID, 0, @FFormat, Handle, 0, CALLBACK_WINDOW or WAVE_MAPPED); //用这个Flag

//对应的消息是:MM_WOM_DONE
//procedure WaveOutCallback(var msg: TMessage); message MM_WOM_DONE;
procedure TWaveOut.WaveOutCallback(var msg: TMessage);
var
Header: PWaveHdr;
begin
Header := PWaveHdr(msg.LParam);
try
if FActive then
begin
WaveOutUnPrepareHeader(FWaveID^, Header, SizeOf(TWaveHdr));
//再继续输出,就是增加输出Buffer
AutoPlayBuffer;
end;
finally
DeleteBuffer(Header); //删除/Free指针
end;
end;

还有错误处理,只要调用对应的GetErrorText即可,不要用上面的raiseException(ErrorCode)函数了。

function GetLen(S: string): Integer;
var
Len: Integer;
begin
Result := 1;
Len := Length(S);
while not (S[Result] = #0) and (Result < Len) do Inc(Result);
end;

procedure TWaveOut.CheckError(Res: Integer);
var
S: string;
begin
if Res <> 0 then
begin
SetLength(S, MAXERRORLENGTH);
waveOutGetErrorText(Res, PChar(S), MAXERRORLENGTH);
//waveInGetErrorText(Res, PChar(S), MAXERRORLENGTH);
SetLength(msg, GetLen(msg));
raise EWaveException.Create(msg);
end;
end;

Wave一般操作是:
New(WaveID); //var WaveID: PInteger;
WaveInOpen/WaveOutOpen打开这个WaveID,并为它提供消息回调
之后
WaveIn: 在回调函数中,进行录音数据处理(数据在消息的LParam, WParam中)
,因为在作存数据(Buffer),所以要增加一定的Buffer给它,waveInPrepareHeader-->waveInAddBuffer
然后就可能WaveInStart了。

WaveOut简单,打开后就直接WaveOutPrepareHeader-->WaveOutWrite

wxzcsut 2005-01-22
  • 打赏
  • 举报
回复
wensusy 2005-01-21
  • 打赏
  • 举报
回复
哪位高手帮帮忙呀,我很急呀!
Kshape 2005-01-20
  • 打赏
  • 举报
回复
不清楚

帮你顶一下!
加载更多回复(1)
高性能的可视电话软件 NetTalk效率很高,比我所见的一些可视通话软件要好(如AVPHONE,注:在此并无破坏AVPHONE所在公司形象之意图,仅将软件作客观上的比较) AVIOMgr模块 AVIOMgr是一个可视通信的通用模块,在NetTalk中是一个独立的模块,对它进行一些简单的处理,可以做成静态库、动态库或ActiveX控件,以用于其他软件。 AVIOMgr封装了包括:视频采集、视频压缩、音频采集、音频压缩、音频播放、数据传输、命令控制等一系列与可视通讯有关的功能 分网络传输部分、音频输入、音频输出、视频输入、视频输出、音频视频压缩、音频波形显示、界面。共创建个线程,音频输入线程、音频输出线程(这两个有WINAPI隐式创建)、音频视频压缩传送线程和主线程。因为音频的采样率比视频采样率高得多,这里的音频的采样率为8000Hz而视频仅为20左右,所以从宏观来看,音频是连续的,而视频是非连续的,这也就是无须为视频输入输出创建独立线程的原因。 网络传输:基于UDP协议,有两组SOCKET,一组用于指令发送和接受(要求可靠),另一组负责音频视频数据的传送和接受(不保证可靠性)。 音频输入:通过waveIn函数族完成连续的录音 音频输出:通过waveOut函数族完成连续的放音 视频输入:通过cap函数族对视频进行捕获 视频输出:通过cap函数族实现视频输出 音频视频压缩:音频压缩采用G.729标准(8:1,1kbps),视频压缩采用H.263+标准 音频波形显示:将PCM音频数据以波形动态地显示出来 界面:与用户交互

1,183

社区成员

发帖
与我相关
我的任务
社区描述
Delphi GAME,图形处理/多媒体
社区管理员
  • GAME,图形处理/多媒体社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧