编写Wave播放器的频谱显示问题,急!(100分)

  • 主题发起人 主题发起人 nest
  • 开始时间 开始时间
N

nest

Unregistered / Unconfirmed
GUEST, unregistred user!
我在编写WAVE播放器时(DELPHI),用下面的语句:
mixerGetControlDetails(hMx,@mcdMixerData,MIXER_GETCONTROLDETAILSF_VALUE);
pmcdsPeak:=pmcdsMixerDataSigned;
来实现实时的频谱显示,但有的声卡能显示,有的声卡不行。具体就是若在Windows的音量控制窗口中Wave音量控制条旁边有频谱显示,我的程序就可以显示,否则就不能。
这是为何?如何解决?
急!!!
 
可能跟声卡有关。
 
wait for answer
 
你说的“Wave音量控制条旁边有频谱显示”好像是声音的幅度把,真正的频谱要经过FFT变换以后
求模得到。你要实现的频谱是不是和winamp频谱类似的?
如果你要在自己的播放其里面实现频谱显示应该是没有能够直接调用的函数的,你可以自己
写一个FFT变换的函数,然后对声音文件每一小段(比如64个数据)作FFT变换,然后计算
各个频率上的幅度(也就是求模),然后显示出来
 
你要求的是显示实时的电平, 而不是频谱分析. 但是实时的电平还是要靠声卡硬件和驱动来
支持的.不需要支持的话就要自己来分析wave的数据了. 建议看看mmtools1.0 的源代码.会有很大收获的.
 
alongsun@sina.com
我有想知道哪里有MMTOOLS的源代码呀!
 
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls;

type

TPCMWaveHeader = record

rID : array[0..3] of char;
// 'RIFF' 标志

rLen : longint;
// 文件长度

wID : array[0..3] of char;
// 'WAVE' 标志

fId : array[0..3] of char;
// 'fmt '标志 以空格结束(fID[3]:=Chr($20);)

fLen : longint;
// 过度字节(不定)

wFormatTag : word;
// 格式字节(过度字节为PCM形式的声音数据)

nChannels : word;
// 通道数 单声道=1, 双声道=2 }

nSamplesPerSec : longint;
// 采样频率 (每秒样本数),表示每个通道的播放速度

nAvgBytesPerSec : longint;
// 波形音频数据传送速度(值:通道数X每秒数据位数X每
// 样本的数据位数/8。播放软件利用根据此值估计缓
// 冲区的大小)

nBlockAlign : word;
// 数据块的调整数(按字节计算),值为通道数*没样本的数据位值/8。
// 播放软件需要一次处理多个该值大小的字节数据,以便
// 将其值用于缓冲区的调整。

nBitsPerSample : word;
// 每样本数据位数,表示每个声道中各个样本的数据位
// 数。如果有多个声道,对每个声道而言,样本大
// 小都一样 8 or 16

dId : array[0..3]of char;
// 'data' 标志

dLen : longint;
// 语音数据长度

end;


TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
Button2: TButton;
Button3: TButton;
Image1: TImage;
procedure Button2Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
filename:string;
pcm:TPCMWaveHeader;
Data:TByteArray;
procedure PrintPcm;
procedure PrintData;
public
{ Public declarations }
end;


var
Form1: TForm1;

implementation


{$R *.DFM}

procedure TForm1.PrintPcm;
begin

memo1.lines.add('FileName:'+Filename);
memo1.lines.add('RIFF:'+pcm.rID);
memo1.lines.add('RLEN:'+inttostr(pcm.rLen));
memo1.lines.add('WAVE:'+pcm.wID);
memo1.lines.add('fmt:'+pcm.fId);
memo1.lines.add('Fixed:'+inttostr(pcm.fLen));
memo1.lines.add('wFormatTag:'+inttostr(pcm.wFormatTag));
memo1.lines.add('nChannels:'+inttostr(pcm.nChannels));
memo1.lines.add('nSamplesPerSec:'+inttostr(pcm.nSamplesPerSec));
memo1.lines.add('nAvgBytesPerSec:'+inttostr(pcm.nAvgBytesPerSec));
memo1.lines.add('nBlockAlign:'+inttostr(pcm.nBlockAlign));
memo1.lines.add('nBitsPerSample:'+inttostr(pcm.nBitsPerSample));
memo1.lines.add('dLen:'+inttostr(pcm.dLen));
end;


procedure TForm1.Button2Click(Sender: TObject);
var
iFileHandle: Integer;
iFileLength: Integer;
iBytesRead: Integer;
Buffer: PChar;
i, Size: Integer;
begin

iFileHandle := FileOpen(filename, fmOpenRead);
iFileLength := FileSeek(iFileHandle, 0, 2) - FileSeek(iFileHandle, 0, 0);
Buffer := PChar(AllocMem(iFileLength + 1));
iBytesRead := FileRead(iFileHandle, Buffer^, iFileLength);
//把文件读到buffer
FileClose(iFileHandle);
Move((Buffer)^, pcm, sizeof(pcm));
Move((Buffer)^, Data, pcm.dLen);
printpcm;
//显示头信息
printData;
//画波形图
end;


procedure TForm1.FormCreate(Sender: TObject);
begin

filename:='c:/SOUND108.WAV';
end;


procedure TForm1.PrintData;
var
i:Integer;
begin

for i:=0 to pcm.dLen -1do
begin

//memo1.lines.add(inttostr(Data));
Canvas.LineTo(i,Data)
end;

end;


end.
 
多人接受答案了。
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
2K
DelphiTeacher的专栏
D
后退
顶部