如何获得当前样本的音量?德尔福7 [英] How to get volume level in current sample? Delphi 7

查看:81
本文介绍了如何获得当前样本的音量?德尔福7的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Delphi 7上,我正在使用NewAC Audio库运行此代码。我有短的wav文件,44.100 kHz,单声道,16位。

On Delphi 7 I am running this code with NewAC Audio library. I am having short wav file, 44.100 kHz, mono, 16 bit.

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中的变量),因此我在第一次迭代中具有以下值:

When I open the file in editing software I can see the amplitude of the sound and I see that the beginning values are 0. But when I run this program and I add the si1, si2, si3 and si4 to watch (in this order are the variables in watch), so I have these values in first iteration:

80,124,104,32。

80,124,104,32.

我希望这些值应为0,因为开始时会保持沉默。

I expected that these values should be 0 because there is silence on the begin.

首先,您能解释一下为什么它们不为零吗?

First, may you explain why these are not zero?

第二,我不确定这些值是多少真正代表。我知道si1和si2是第一个样本。但这真的是音量水平吗?

Second, I am not sure what these values really represent. I know that si1 and si2 are first sample. But is it really level of the volume? How to correct the program to recognize the silence in the begin?

经过测试的文件-> 应该

Tested file -> the section which should be passed to the function as first.

该部分不会进行处理(因为我只处理了第一个循环的几个小块):

This part is not proccessed (because I processed only few cicles of the first loop):

我对文件 silence plus做了一些测试,放大并看到了前8个cicle值。

I did some tests with file "silence plus", amplifications and see the first 8 cicles values.

另一个用单词代替字节的测试:

Another test with word instead byte:

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

看起来确实需要交换位。我以为在Windows XP中我的字节序很少。因此,我将写一个交换器。

It really looks like the bits need to swap. I thought that in Windows XP I have little endian bit order. So I will write a swapper.

推荐答案

我的代码的主要问题是:

The main problems of my code were:

1)读取1个字节的示例,而不是2个字节的示例。

1) Reading 1 byte of sample instead 2 bytes of sample.

2)该示例已签名,而不是未签名。因此,当我尝试读取两个字节的单词时,我得到了错误的数字(请参阅有问题的最后一张表)。

2) The sample is signed, not unsigned. So when I tried to read two bytes of word, I get wrong numbers (see the last table in question).

3)我也尝试使用两个字节的SmallInt交换,但是导致出现疯狂的数字,例如-25345,-1281、26624和-19968 ...这是因为在我的系统上,我使用的是Little Endian(Windows XP)。在Windows上不需要交换它。

3) I also tried to use two bytes of SmallInt swapped, but that resulted to crazy numbers like -25345, -1281, 26624, -19968 ... This is because on my system I use Little endian (Windows XP). There is not need to swap it on Windows.

因此解决方案是将16位复制到SmallInt,而无需交换。

So the solution was to copy 16 bits to SmallInt, no swap.

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;

end。

以下是值:

这篇关于如何获得当前样本的音量?德尔福7的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆