[英]How to get volume level in current sample? Delphi 7
在 Delphi 7 上,我正在使用 NewAC Audio 库运行此代码。 我有短 wav 文件,44.100 kHz,mono,16 位。
unit Main;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ACS_Classes, ACS_DXAudio, ACS_Wave, ACS_Misc, ACS_Types, StdCtrls;
type
TForm1 = class(TForm)
AudioProcessor1: TAudioProcessor;
WaveIn1: TWaveIn;
DXAudioOut1: TDXAudioOut;
OpenDialog1: TOpenDialog;
Button1: TButton;
Button2: TButton;
procedure AudioProcessor1GetData(
Sender: TComponent;
var Buffer: Pointer;
var NBlockBytes: Cardinal);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure DXAudioOut1Done(Sender: TComponent);
procedure AudioProcessor1Init(Sender: TComponent; var TotalSize: Int64);
procedure AudioProcessor1Flush(Sender: TComponent);
end;
var Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.AudioProcessor1GetData(Sender: TComponent;
var Buffer: Pointer; var NBlockBytes: Cardinal);
var Tmp : Integer;
i : Integer;
list1: TStringList;
list2: TStringList;
b1, b2, b3, b4:byte;
si1, si2, si3, si4: ShortInt;
mono: Boolean;
values: array of word;
begin
list1 := TStringList.Create;
list2 := TStringList.Create;
AudioProcessor1.Input.GetData(Buffer, NBlockBytes);
if Buffer = nil then
Exit;
mono := false;
case AudioProcessor1.Input.BitsPerSample of
16 :
begin
B16 := Buffer;
setlength(values, NBlockBytes div 2);
for i := 0 to (NBlockBytes div 4) - 1 do
begin
Tmp := B16[i*2];
move(B16[i*2], b1, 1); // copy left channel
move(B16[i*2+1], b2, 1); // copy right channel
move(B16[i*2+2], b3, 1); // copy left channel
move(B16[i*2+3], b4, 1); // copy right channel
si1 := b1;
si2 := b2;
si3 := b3;
si4 := b4;
list1.add(''+inttostr(si1));
list2.add(''+inttostr(si2));
list1.add(''+inttostr(si3));
list2.add(''+inttostr(si4));
B16[i*2] := B16[i*2 + 1];
B16[i*2 + 1] := Tmp;
end;
end;
end;
list1.free;
list2.free;
end;
procedure TForm1.AudioProcessor1Init(Sender: TComponent; var TotalSize: Int64);
begin
TAudioProcessor(Sender).Input.Init;
TotalSize := TAudioProcessor(Sender).Input.Size
end;
procedure TForm1.AudioProcessor1Flush(Sender: TComponent);
begin
TAudioProcessor(Sender).Input.Flush;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
if OpenDialog1.Execute then
begin
Button1.Enabled := False;
WaveIn1.FileName := OpenDialog1.FileName;
DXAudioOut1.Run;
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
DXAudioOut1.Stop;
end;
procedure TForm1.DXAudioOut1Done(Sender: TComponent);
begin
Button1.Enabled := True;
end;
end.
当我在编辑软件中打开文件时,我可以看到声音的幅度,我看到开始值为 0。但是当我运行这个程序时,我添加了 si1、si2、si3 和 si4 来观看(按这个顺序是watch 中的变量),所以我在第一次迭代中有这些值:
80,124,104,32。
我预计这些值应该为 0,因为一开始就没有声音。
首先,你能解释一下为什么这些不为零吗?
其次,我不确定这些值真正代表什么。 我知道 si1 和 si2 是第一个样本。 但这真的是音量的水平吗? 如何纠正程序以识别开始时的沉默?
测试文件 ->应该首先传递给 function 的部分。
这部分没有处理(因为我只处理了第一个循环的几个循环):
我对文件“silence plus”进行了一些测试,放大并查看前 8 个 cicles 值。
另一个用字代替字节的测试:
B16 := Buffer;
...
move(B16[i*2], w1, 2);
move(B16[i*2+1], w2, 2);
看起来确实需要交换位。 我认为在 Windows XP 中我的字节序很少。 所以我会写一个交换器。
我的代码的主要问题是:
1) 读取 1 个字节的样本而不是 2 个字节的样本。
2) 样本是签名的,不是未签名的。 因此,当我尝试读取两个字节的单词时,我得到了错误的数字(请参见最后一张表)。
3)我还尝试使用交换的两个字节的 SmallInt,但这导致了疯狂的数字,如 -25345、-1281、26624、-19968... 这是因为在我的系统上我使用的是小端(Windows XP)。 Windows 上无需更换。
所以解决方案是将 16 位复制到 SmallInt,不交换。
unit Main;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ACS_Classes, ACS_DXAudio, ACS_Wave, ACS_Misc, ACS_Types, StdCtrls;
type
TForm1 = class(TForm)
AudioProcessor1: TAudioProcessor;
WaveIn1: TWaveIn;
DXAudioOut1: TDXAudioOut;
OpenDialog1: TOpenDialog;
Button1: TButton;
Button2: TButton;
procedure AudioProcessor1GetData(
Sender: TComponent;
var Buffer: Pointer;
var NBlockBytes: Cardinal);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure DXAudioOut1Done(Sender: TComponent);
procedure AudioProcessor1Init(Sender: TComponent; var TotalSize: Int64);
procedure AudioProcessor1Flush(Sender: TComponent);
private
{ Private declarations }
public
{ Public declarations }
end;
var Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.AudioProcessor1GetData(Sender: TComponent;
var Buffer: Pointer; var NBlockBytes: Cardinal);
var
B16 : PBuffer16;
i, end_ : Integer;
si1, si2: SmallInt;
begin
AudioProcessor1.Input.GetData(Buffer, NBlockBytes);
if Buffer = nil then
Exit;
case AudioProcessor1.Input.BitsPerSample of
16 :
begin
B16 := Buffer;
end_ := (NBlockBytes div 2) - 1;
for i := 0 to end_ do
begin
move(B16[i*2], si1, 2);
move(B16[i*2+1], si2, 2);
end;
end;
end;
end;
procedure TForm1.AudioProcessor1Init(Sender: TComponent; var TotalSize: Int64);
begin
TAudioProcessor(Sender).Input.Init;
TotalSize := TAudioProcessor(Sender).Input.Size
end;
procedure TForm1.AudioProcessor1Flush(Sender: TComponent);
begin
TAudioProcessor(Sender).Input.Flush;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
if OpenDialog1.Execute then
begin
Button1.Enabled := False;
WaveIn1.FileName := OpenDialog1.FileName;
DXAudioOut1.Run;
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
DXAudioOut1.Stop;
end;
procedure TForm1.DXAudioOut1Done(Sender: TComponent);
begin
Button1.Enabled := True;
end;
结尾。
以下是值:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.