移动学习网 导航

C/C++ 声卡编程代码 如何用C语言(或C++)关闭声卡驱动和打开声卡驱动,求代码

2024-05-10m.verywind.com
用c/c++如何实现读取声卡所发出的声音~

声音是无法直接读取的,如果有咪,咪将将声音变成声音数据,声音数据再通过声卡恢复为声音。通常程序是不需要转换声音的,在计算机世界,一切皆数字,直接读取音频原数据就可以了,声卡发出的声音也是声卡将音频数据转换为声音的。

你是说控制声卡声音吗?
直接用c很麻烦,不过有个变通的方法。
搜索nircmd,下载,这个命令有很多功能,可以使用这个:
增大系统音量2000个单位值 (最大65535) nircmd.exe changesysvolume 2000
降低系统音量5000个单位值 (out of 65535) nircmd.exe changesysvolume -5000
设置系统音量为最大 nircmd.exe setsysvolume 65535
系统音量静音 nircmd.exe mutesysvolume 1
取消系统静音 nircmd.exe mutesysvolume 0
改变当前系统静音设置(静音和非静音之间切换) nircmd.exe mutesysvolume 2

main()
{
system("nircmd.exe mutesysvolume 1");
}
这样就可以是上卡静音了。

事实上,声卡是PC的一种多媒体设备,所以可以用Windows 的MCI(Media Control I nterface)命令来控制声卡。MCI它提供了一组与设备无关的控制命令,是一种访问多媒体设备的高层次方法。也正因为它属于一种高层次方法,所以它提供给程序员的灵活性有限,利用MCI命令来控制声卡录音时,程序员不能在录音的过程中访问内存中的采样数据,只有在录音完成后通过访问*.WAV文件才可以得到采样数据,尽管最终还是得到了采样数据,但是这样做一方面嫌其麻烦,更重要的是存取文件需要耗费时间,声卡在采样的过程中有可能会停止下来等待文件操作,造成了采样的断续。在一些实时性要求比较高的场合(比如波形分析,实时控制等),断续的采样明显是不行的。 Windows的低级波形音频函数提供了对声卡的最大灵活性的操作,它允许在采样过程中随机地访问内存中的每个采样数据,完全可以克服使用MCI命令所遇到的实时性问题。 Windows以动态连接库Mmsystem.dll的形式提供低级波形音频函数,在Mmsystem.dll中总共包括了以下几个有关波形录入的函数:

waveInAddBuffer :向声音输入设备发送缓冲区 ;waveInClose :关闭声音输入设备
waveInGetDevCaps:获取声音输入设备性能; waveInGetErrorText:获取声音出错信息文本
waveInGetID :获取声音输入设备ID; waveInGetNumDevs:返回声音输入设备数量
waveInGetPosition :获取声音设备输入位置; waveInMessage :向声音输入设备发送信息
waveInOpen :打开声音输入设备; waveInPrepareHeader:预备声音输入缓冲区
waveInReset :停止声音输入设备工作; waveInStart :停止声音输入设备工作
waveInStop :停止声音输入; waveInUnprepareHeader : 清除预备的声音文件头

需要说明的是:不同的编程工具多会含有对这些低级波形音频函数进行说明的头文件(比如在Delphi4.0中,对Mmsystem.dll说明的文件是Mmsystem.pas),所以在不同的编程工具中调用这些函数时有可能会使用不同的名称。
与使用其他设备一样,要想用波形音频函数来控制声卡,必须要经过以下的步骤:
1. 打开波形输入设备。函数waveInOpen用于打开波形输入设备,其原型如下:
① WORD waveInOpen(lphWaveIn,wDeviceID,lpFormat,dwCallback,dwCallbackInstan ce, dwFlags) LPHWaveIn: lphWaveIn 该变量用来接收波形输入设备的句柄,该句柄应当保存下来,因为其他的波形输入函数还会用到它.
②WORD wDeviceID 该变量用来指明波形输入设备的标记号.当PC中有多块声卡(准确地说是波形输入设备)时,操作系统会为每一块声卡分配一个标记号.可以用waveInGetNumDev s函数来得到能够作为波形输入设备的数目N,则wDeviceID的取值范围为0~N-1.如果想得到没个标记号所对应的录音性能,可以使用函数waveInGetDevCaps.若把wDeviceID设为W AVE_MAPPER(即-1),则系统会自动选择一符合要求的设备(根据lpFormat的要求). ③lpFormat是一个指向PCMWAVEFORMAT数据结构的指针,应当在这个数据结构中指明所期望的采样模式,这个数据结构的定义是这样的:
Typedef structure pcmwaveformat_tag { WAVEFORMAT wf; //有关PCM格式设置的另外一种数据结构
WORD wBitsPerSample; //量化位数
}PCMWAVEFORMAT;
Typedef structure waveformat_tag {
WORD wFormatTag; //采样数据格式,目前只能用PCM格式
WORD nChannels; //通道数目(1或2)
DWORD nSamplesPerSec; //采样速率
DWORD nAvgBytesPerSec;//每秒采样得到的数据
WORD nBlockAlign; //记录区块对齐的单位。此值为nChannels*wBitsPerSample/8 }WAVEFORMAT;
④ DWORD dwCallback.定义回调函数的地址或回调窗口的句柄。回调函数的地址或回调窗口用来处理波形输入设备产生的消息。
⑤DWORD dwCallbackInstance。这是一个用户自定义的数据,该数据会一并传给回调函数(或窗口)。
⑥DWORD dwFlags。定义打开波形输入设备的标记。
CALLBACK_WINDOW 定义dwCallback为窗口句柄。
CALLBACK_FUNCTION 定义dwCallback为函数地址。
另外还可以在此指定:
WAVE_FORMAT_QUERY 只查询波形输入设备是否支持给定格式而不真的打开波形输入设备。
WAVE_ALLOWSYNC 同步方式开启波形输入设备,录音工作在后台进行。
下面一段Delphi程序说明了打开波形输入设备的过程:

type
TRecorder = class
private

FWaveFmt : TWaveFormatEx;//Delphi中,WAVEFORMAT和PCMWAVEFORMAT合为TwaveFor
matEx。
WaveHandle : HWaveIn;
WaveHdr1 : PWAVEHDR; //数据缓冲区头结构的指针 (见下文)
WaveBuffer1 : lpstr; //数据缓冲区的指针 (见下文)
procedure CallBack(uMsg,dwInstance,dwParam1,dwParam2 : DWORD); stdcall;

end;

Recorder:=TRecorder.Create;

Recorder.FWaveFmt.wFormatTag:=WAVE_FORMAT_PCM;
Recorder.FWaveFmt.wBitsPerSample:=16;
Recorder.FWaveFmt.nSamplesPerSec:=11025;
Recorder.FWaveFmt.nAvgBytesPerSec:=22050;
Recorder.FWaveFmt.nBlockAlign:=2;
WaveInOpen(@Recorder.WaveHandle,Wave_Mapper,mailto:@Recorder.FWaveFmt,
DWORD(@TRecorder.CallBack),DWORD(@Recorder),CALLBACK_FUNCTION + WAVE_ALLOW
SYNC);


2. 为采样数据分配缓冲空间

在Windows环境,可以用GlobalAllocPtr来获取一段内存空间,但是由于Windows操作系统采用了虚拟存储管理机制,这块内存空间随时有可能会被置换到硬盘上,读写硬盘所耗费的时间会造成采样的不连续。因此,在将缓冲区送往波形输入设备之前,必须调用WaveInPrepareHeader函数以保证缓冲区不会被置换到硬盘上。当然在用GlobalFreeP tr来释放缓冲区之前,必须先要用WaveInUnprepareHeader函数来解除这种保护。

下面几行Delphi语句说明了使用录音缓冲区的过程。


Recorder.WaveHdr1:=GlobalAllocPtr(GHND or GMEM_SHARE,Sizeof(WAVEHDR));
Recorder.WaveBuffer1:=GlobalAllocPtr(GHND or GMEM_SHARE,1024);
Recorder.WaveHdr1.lpData := Recorder.WaveBuffer1;
Recorder.WaveHdr1.dwBufferLength:=1024;
WaveInPrepareHeader(Recorder.WaveHandle, Recorder.WaveHdr1, sizeof(WAVEHDR
));
WaveInAddBuffer(Recorder.WaveHandle, Recorder.WaveHdr1, sizeof(WAVEHDR));

WaveInUnprepareHeader(Recorder.WaveHandle, Recorder.WaveHdr1, sizeof(TWAVE
HDR));
GlobalFreePtr(Recorder.WaveBuffer1);


但是,如果只为波形输入设备开辟一个缓冲区,则当该缓冲区被采样数据填满后,波形输入设备就无缓冲区可用,不得不停止采样,从而造成了采样的断续。所以在实际应用中,至少要为波形输入设备准备两个缓冲区,用上述方法同时送给波形输入设备。

3. 启动波形输入设备

当上述一切都准备好后,用WaveInStart启动波形输入设备,即可开始进行数据采集,在采集的过程中,一旦有缓冲区被采样数据填满,系统就回调WaveInOpen中指定的dwCa llback函数(或向指定的窗口发送消息)。在Delphi4.0中,回调函数的格式是这样的: procedure CallBack(uMsg,dwInstance,dwParam1,dwParam2 : DWORD); stdcall; 其中uMsg是Windows的消息标记号,有三种情况:

MM_WIM_OPEN 表示波形输入设备开启成功
MM_WIM_DATA 表示一个缓冲区已满。
此时dwParam1中携带有数据缓冲区头结的指针。正是通过这个指针,才可以随机地访问缓冲区中的每一个采样数据。如下面程序所示:


procedure TRecorder.CallBack(uMsg,dwInstance,dwParam1,dwParam2 : DWORD);
stdcall;
var i:Integer;
SPByte : ^Byte; //假设在打开设备时采用8位量化
SingleData : Integer;
BEGIN
case uMsg of //uMsg是Windows的消息标记号
MM_WIM_OPEN : //波形输入设备开启成功发回的消息

MM_WIM_DATA : //一个缓冲区已满发回的消息
begin
SPByte := Pointer(dwParam1);
for i :=0 to Recorder.DataLength-1 do
begin
SingleData := SPByte^; //通过SPByte来访问缓冲区中的数据

Inc(SPByte);
end;
end;
MM_WIM_CLOSE : //波形输入设备关闭成功发回的消息

end;
END;


MM_WIM_CLOSE 表示波形输入设备关闭成功。当波形输入设备关闭后,别忘了用Wave InPrepareHeader和GlobalFreePtr来释放缓冲区内存。

4. 关闭语音输入设备

waveInStop(hWaveIn) 停止语音输入
waveInReset(hWaveIn) 重置语音输入设备
waveInClose(hWaveIn) 关闭语音输入设备。其中hWaveIn是WaveInOpen得到的设备句柄。
在关闭语音输入设备前,必须重置语音输入设备,否则系统会出现这样的错误提示: "MMSYSTEM033 媒体数据仍在播放中,请重置设备或等到数据播放完毕"。但是只有当一个缓冲区填满数据后,才能重置语音输入设备
以上波形输入函数,若调用成功则返回0;否则返回非0,此时可以用waveInGetErrorText函数来得到出错信息,这样做的目的是方便调试。

三、必须注意的几点

以上阐述了作为A/D卡的声卡编程技术,但是还必须注意以下几点

1. 声卡的采样频率并不只限于11025Hz,22050Hz,44100 Hz三种,大多数声卡的采样频率在一定的范围内是可调的(当然会存在一定的偏差)。有的声卡的最高采样频率可达200K Hz(有可能随不同品牌而异)。
2. 缓冲区不能设得太小,否则也会造成采样的不连续。在作者的声卡上,若采用16为量化,22050Hz的采样速率,缓冲区设为1K字节,理论上每秒钟可以得到22050*2个字节的数据,实际上每秒钟只能得到大约16000*2个字节的数据。若缓冲区设为2K字节,则与理论值一致。
3. A/D转化后的数据格式是PCM格式,即:若是8位量化,对应着8位无符号数据,0对应着负满幅值,128对应着零电平,255对应着正满幅值;若是16位量化,对应着16位有符号数据,-32768对应着负满幅值,0对应着零电平,32767对应着正满幅值。编程过程中应注意所声明的数据类型是否与之相符合,比如在Delphi4.0中,8位无符号数据对应着 Byte型数据,16位有符号数据对应着SmallInt型数据。
4. 由于声卡的输入端往往带有隔直电容,所以不能用声卡直接对直流量进行采集。解决的办法就是将这个隔直电容短接。
5. 同样地,利用windows的API函数和声卡的D/A功能也可以使声卡产生模拟音频信号输出。

这么长啊

  • C的含义是什么?
  • 答:数学符号c右上角是1右下角是4的意思是数学中的组合,右下角的4表示总体个数,右上角的1表示抽取个数,且从4个里面抽取一个,C¹₄=4÷1=4。组合:一般地,从n个不同的元素中,任取m(m≤n)个元素...

  • c的计算公式是什么?
  • 答:c的计算公式是:C(n,m)=A(n,m)/m!=n!/m!(n-m)!与C(n,m)=C(n,n-m)。(n为下标,m为上标)。概率论是研究随机现象数量规律的数学分支。随机现象是相对于决定性现象而言的。在一定条件下必然发生某一...

  • 排列组合中的C是什么意思?
  • 答:排列组合中的C和A在计算方法、符号表示和应用上存在区别。1、计算方法不同:C表示组合数,是“取”的运算,表示从给定的n个元素中选取m个元素进行组合的数量。A表示排列数,是“排”的运算,表示从给定的n个元素中选取m...

  • 为什么c是组合?
  • 答:数学符号c右上角是1右下角是4的意思是数学中的组合,右下角的4表示总体个数,右上角的1表示抽取个数,且从4个里面抽取一个,C¹₄=4÷1=4。组合:一般地,从n个不同的元素中,任取m(m≤n)个元素...

  • C表示什么的数,是什么含义。
  • 答:数学符号c右上角是1右下角是4的意思是数学中的组合,右下角的4表示总体个数,右上角的1表示抽取个数,且从4个里面抽取一个,C¹₄=4÷1=4。组合:一般地,从n个不同的元素中,任取m(m≤n)个元素...

  • c是什么数集
  • 答:数学中c表示复数集合。在数学计算等场合中经常使用,是作为对文字说明的省略的符号表达。集合是数学中一个基本概念,也是集合论的主要研究对象。集合论的基本理论创立于19世纪,关于集合的最简单的说法就是在朴素集合论(最原始...

  • c在爱情的含义是什么
  • 答:c在爱情的含义是什么,用各种各样的符号来代替我们想要表达的真实意思是我们对一份感情的含蓄表示,世间万物存在的意义就是我们赋予的内涵,下面分享c在爱情的含义是什么。 c在爱情的含义是什么1 C指的是现在流行的C型爱情观。 C型爱情...

  • C语言和C++有什么区别?
  • 答:一、主体不同 1、C语言:是一门面向过程的、抽象化的通用程序设计语言,广泛应用于底层开发。2、C++:是C语言的继承,它既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计。二、优势不...

  • C代表什么数学
  • 答:在概率中,C表示组合数。c(6,3)=6×5×4/(3×2×1)=20 是从n个不同元素中每次取出m个不同元素(0≤m≤n),不管其顺序合成一组,称为从n个元素中不重复地选取m个元素的一个组合。所有这样的组合的总数称...

  • c语言中的c表示什么意思?
  • 答:C表示组合数。组合,数学的重要概念之一。从n个不同元素中每次取出m个不同元素(0≤m≤n),不管其顺序合成一组,称为从n个元素中不重复地选取m个元素的一个组合。所有这样的组合的总数称为组合数,这个组合数的计算...

    户户网菜鸟学习
    联系邮箱
    返回顶部
    移动学习网