用声卡OUT固定频率的声音,请教!(50分)

  • 主题发起人 主题发起人 lubfc
  • 开始时间 开始时间
L

lubfc

Unregistered / Unconfirmed
GUEST, unregistred user!
我想用声卡播放固定频率的声音,比如1k赫兹或者10k赫兹的声音,不知该如何播放!谢谢大家 给些建议(不是 windows speaks而是声卡)
 
最简单方法找个虚拟仪器,再用虚拟声卡录下再到程序中播放即可。要求不高的化这个最简单
 
这个方法 我也想过 但是我想自己通过程序控制声音的频率,如果我需要声音的样本很多的话,你这种方法就需要采集很多声音样本,这样太麻烦了。我想Beep()既然可以发固定频率的声音,声卡应该也可以控制。
 
在程序中你用什么来播放?mmtools?dspack?
不管用什么来播放,最后输出到声卡的音频数据都是wav格式的。
可以找到输出wav格式数据的一步,直接输出你自造的wav数据。
我使用mmtools,知道怎么实现你的这样的目标,但是没有试过。
查一下书,找到正弦波的公式,自己生成所需要的频率数据就可以了。
 
我用的是 win api的 waveOutWrite 等函数,录制时用的是waveIn*等函数,我也想过人为计算一个正弦波,计算一个数值,但是如何算这个数(也就是如何用公式)和计算出的结果如何把它数字化(本身音频是通过电压波形进行A/D转换成数字信号,这个数字信号是否与计算的结果对等, :)不知我说明白了吗),所以不知怎么下手,skadon能不能 详细一下 thanks
 
找出了以前做的简单例子,合成二个频率,单声道,44100Hz,16位,时间长度为10秒。
Type
TPCMWaveHeader = record
rID : array[0..3] of char;
{ 'RIFF' Identifier }
rLen : longint;
wID : array[0..3] of char;
{ 'WAVE' Identifier }
fId : array[0..3] of char;
{ 'fmt ' Identifier }
fLen : longint;
{ Fixed, must be 16 }
wFormatTag : word;
{ Fixed, must be 1 }
nChannels : word;
{ Mono=1, Stereo=2 }
nSamplesPerSec : longint;
{ SampleRate in Hertz }
nAvgBytesPerSec : longint;
nBlockAlign : word;
nBitsPerSample : word;
{ Resolution, e.g. 8 or 16 }
dId : array[0..3]of char;
{ 'data' Identifier }
dLen : longint;
{ Number of following data bytes }
end;


频率合成代码:
procedure TForm1.Button2Click(Sender: TObject);
var
h : TPCMWaveHeader;
f : file;
FileName : String;
i, DataBytes, SampleRate, Channels, Resolution : integer;
d: SmallInt;
delta1, delta2 :do
uble;
begin

FileName:='01.wav';
SampleRate:=44100;
delta1:= Freq1.Value * 3.1415926 * 2 / SampleRate;
delta2:= Freq2.Value * 3.1415926 * 2 / SampleRate;
DataBytes:=SampleRate*20;
Channels:=1;
Resolution :=16;
FillChar(h,SizeOf(TPCMWaveHeader),#0);
with hdo
begin

rID[0]:='R';
rID[1]:='I';
rID[2]:='F';
rID[3]:='F';
{ 1st identifier }
rLen:=DataBytes+36;
wID[0]:='W';
wID[1]:='A';
wID[2]:='V';
wID[3]:='E';
{ 2nd identifier }
fId[0]:='f';
fId[1]:='m';
fId[2]:='t';
fID[3]:=Chr($20);
{ 3rdidentifier ends with a space character }
fLen:=$10;
{ Fixed, must be 16 }
wFormatTag:=1;
{ Fixed, must be 1 }
nChannels:=Channels;
{ Channels }
nSamplesPerSec:=SampleRate;
{ Sample rate in Hertz }
nAvgBytesPerSec:=SampleRate*Channels*trunc(Resolution div 8);
nBlockAlign:=Channels*(Resolution div 8);
{ Byte order, see below }
nBitsPerSample:=Resolution;
dId[0]:='d';
dId[1]:='a';
dId[2]:='t';
dId[3]:='a';
{ Data identifier }
dLen:=DataBytes;
{ number of following data bytes }
end;

AssignFile(f,FileName);
ReWrite(f,1);
BlockWrite(f,h,SizeOf(h));
for i:=0 to databytes-1do
begin

d:=Trunc(8192 * sin (delta1 * i));
d:=d + Trunc(8192 * sin (delta2 * i));
BlockWrite(f,d,2);
end;

CloseFile(f);
end;
 
skadon: 谢谢了
不过
delta1:= Freq1.Value * 3.1415926 * 2 / SampleRate;
delta2:= Freq2.Value * 3.1415926 * 2 / SampleRate;
这两句是取什么值 Freq*好像在这段代码中没有定义
d:=Trunc(8192 * sin (delta1 * i));
d:=d + Trunc(8192 * sin (delta2 * i));
根据这两句 delta* 应该是 1/44100秒时采样的角度 为什么这么写能说明一下吗
 
Freq1.Value就是频率,单位Hz,整数,我是用TSpinEdit控件的。
delta1:= Freq1.Value * 3.1415926 * 2 / SampleRate;
需要生成频率为Freq1.Value时,每相邻采样点的周期间隔,
正弦函数:y=A*sin(wt + b)
w=2*pi*f
 
哦 我大致明白了 不过 8192这个值是不是有什么特出意义? 这个demo是不是将两个频率 合到一个16位中表示一个采样,不知我的理解对不对,这是不是就是混音啊
 
8192是振幅,16位时最大振幅是32767。
可以算是简单的混音吧
 
谢谢 skadon的帮助
问题 已经完全解决了 散分
同时也感谢 z1234参与
 
后退
顶部