Delphi 如何获取当前样本中的卷级别?德尔福7

Delphi 如何获取当前样本中的卷级别?德尔福7,delphi,audio,Delphi,Audio,在Delphi7上,我使用NewAC音频库运行此代码。我有短wav文件,44.100千赫,单声道,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 = c

在Delphi7上,我使用NewAC音频库运行此代码。我有短wav文件,44.100千赫,单声道,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(watch中的变量按此顺序排列)时,我在第一次迭代中得到了这些值:

80124104,32

我希望这些值应该是0,因为开始时没有声音

首先,请你解释一下为什么这些不是零

第二,我不确定这些值真正代表什么。我知道si1和si2是第一个样本。但它真的是音量的水平吗?如何纠正程序以识别开始时的静音

测试文件->应首先传递给函数的部分

未处理此部分(因为我只处理了第一个循环的几个循环):

我用文件“silence plus”进行了一些测试,放大后看到了前8个cicles值

另一个测试使用word代替byte:

B16 := Buffer;
...
move(B16[i*2], w1, 2);
move(B16[i*2+1], w2, 2);


看起来这些比特真的需要交换。我认为在WindowsXP中,我有一个小小的endian位顺序。因此,我将编写一个交换程序。

我的代码的主要问题是:

1) 读取1字节的样本,而不是2字节的样本

2) 样本是有符号的,而不是无符号的。因此,当我试图读取两个字节的单词时,我得到了错误的数字(见最后一个表)

3) 我还尝试使用两个字节的SmallInt交换,但结果是出现了像-25345、-12812624、-19968这样的疯狂数字。。。这是因为在我的系统上我使用Little endian(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;
结束

以下是数值:


wav文件的音频内容为。因为在你的例子中每个样本有16位,最高的位代表波形的顶部,最低的位代表波形的底部,所以静默在中间(所以它不是0)。这个值代表什么,它是音量级别吗?振幅=音量更多信息你必须知道有50多种可能的格式,所以字节本身没有意义,不看标题。无论如何,您的代码是不正确的,您指定的文件是16位mono,这意味着您需要读取每个样本2个字节(并且没有左或右通道,并舍弃短字符),您需要交换它们,因为wav数据以小端格式存储。做一些