谁有用过TAudioIO,请教如何才能把被填充到buffer中的数据存成.wav文件?

donghaiw 2003-11-10 08:38:21
不知道谁有用过这个很不错的声音控件TAudioIO,
用来对波形音频的录制和播放,还可同时显示声音的峰值,
下载地址:
http://www.csdn.net/dev/Delphi/vcl/multimedia/taudioio.zip

我的问题是:
这个控件录音时只存到buffer中,
我想把录音的数据存成wav文件,不知道怎么做啊。
希望各位帮忙。先谢了。

TAudioIO分成TAudioIn和TAudioOut,其中TAudioIn是用来录音的,
它有一个事件叫,AudioIn1BufferFilled().
这个事件在录音的过程中不停的被激活,
它是把产生的数据填入buffer中,然后产生声音峰值,
如何才能把这些buffer中的数据最终存成.wav文件呢。

具体如下:
unit TAudioInputDemo;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, AudioIO, ExtCtrls, Buttons, ComCtrls, MMSYSTEM;

type
TForm1 = class(TForm)
StartButton: TButton;
Timer1: TTimer;
StopButton: TButton;
RunStatusLabel: TLabel;
BufferStatusLabel: TLabel;
TimeStatusLabel: TLabel;
Panel1: TPanel;
RecordSpeedButton: TSpeedButton;
ProgressBar1: TProgressBar;
MaxLabel: TLabel;
AudioIn1: TAudioIn;
procedure StartButtonClick(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure AudioIn1Stop(Sender: TObject);
procedure UpdateStatus;
procedure StopButtonClick(Sender: TObject);
procedure RecordSpeedButtonClick(Sender: TObject);
function AudioIn1BufferFilled(Buffer: PChar;
var Size: Integer): Boolean;
private
{ Private declarations }
public
{ Public declarations }
Min, Max : Integer;
TempMax : Integer;
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.StartButtonClick(Sender: TObject);
begin
If (Not AudioIn1.Start(AudioIn1)) Then ShowMessage(AudioIn1.ErrorMessage)
Else
Begin
Min := 0;
Max := 0;
RecordSpeedButton.Down := TRUE;
End;
end;

function TForm1.AudioIn1BufferFilled(Buffer: PChar; var Size: Integer): Boolean;
Var
SP : ^SmallInt;
i, N, v : Integer;
xMin, xMax : Integer;

begin
N := Size Div 2;
SP := Pointer(Buffer);
xMin := SP^;
xMax := xMin;


For i := 0 to N-1 Do
Begin
v := SP^; Inc(SP);
If (xMin > v) Then xMin := v;
If (xMax < v) Then xMax := v;
End;

If (Min > xMin) Then Min := xMin;
If (Max < xMax) Then Max := xMax;

TempMax := xMax;
If (Abs(xMin) > xMax) Then TempMax := Abs(xMin);
Result := TRUE;
end;

Procedure TForm1.UpdateStatus;
begin
With AudioIn1 Do
If (AudioIn1.Active) Then
Begin
RunStatusLabel.Caption := 'Started';
BufferStatusLabel.Caption := Format('Queued: %3d; Processed: %3d',[QueuedBuffers, ProcessedBuffers]);
TimeStatusLabel.Caption := Format('Seconds %.3n',[ElapsedTime]);
End
Else
Begin
RunStatusLabel.Caption := 'Stopped';
BufferStatusLabel.Caption := '';
TimeStatusLabel.Caption := '';
End;

{ Update the progress bar }
If (AudioIn1.Active) Then
Begin
ProgressBar1.Position := Round(100*TempMax/36768.0);
If (Abs(Min) > Max) Then Max := Abs(Min);
MaxLabel.Caption := Format('Max %5d; Peak %5d',[Max,TempMax]);
End
Else
Begin
ProgressBar1.Position := 0;
MaxLabel.Caption := '';
End;

End;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
UpdateStatus;
end;

procedure TForm1.AudioIn1Stop(Sender: TObject);
begin
RecordSpeedButton.Down := FALSE;
end;


procedure TForm1.StopButtonClick(Sender: TObject);
begin
AudioIn1.StopAtOnce;
end;

procedure TForm1.RecordSpeedButtonClick(Sender: TObject);
begin
If (RecordSpeedButton.Down) Then
StartButtonClick(Sender)
Else
AudioIn1.StopAtOnce;
end;

end.
...全文
161 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
Haofei 2003-11-18
  • 打赏
  • 举报
回复
最好请将procedure TForm1.StartButtonClick(Sender: TObject);过程中的
WaveHeader.nChannels :=2;
WaveHeader.nSamplesPerSec := 11025;
WaveHeader.wBitsPerSample := 16;
成如下
if AudioIn1.Stereo then WaveHeader.nChannels :=2
else WaveHeader.nChannels := 1;
WaveHeader.nSamplesPerSec := AudioIn1.FrameRate;
WaveHeader.wBitsPerSample := AudioIn1.Quantization;
Haofei 2003-11-18
  • 打赏
  • 举报
回复
我帮你改了一下,在D7下通过,代码如下:
unit TAudioInputDemo;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, AudioIO, ExtCtrls, Buttons, ComCtrls, MMSYSTEM;

type
TWaveHeader = record
rId : longint; //固定标记 值为"RIFF"
rLen : longint; //随后的字节数 值为文件大小-8
wId : longint; //固定标记 值为"WAVE"
fId : longint; //ckID 值为"fmt "
fLen : longint; //nChunkSize Wave文件块的大小 16
wFormatTag : word; //音频数据的编码方式 此值常为1 表示PCM方式
nChannels : word; //声道数
nSamplesPerSec : longint; //每秒采样频率
nAvgBytesPerSec : longint; //每秒字节数
nBlockAlign : word; //一次输出的字节数 值为采样位数*声道数/8
wBitsPerSample : word; //采样位数 一般16位和8位
dId : longint; //固定标记 值为"data"
wSampleLength : longint; //采样数据长度 值为文件大小-文件头大小(44)
end;

TForm1 = class(TForm)
StartButton: TButton;
Timer1: TTimer;
StopButton: TButton;
RunStatusLabel: TLabel;
BufferStatusLabel: TLabel;
TimeStatusLabel: TLabel;
Panel1: TPanel;
RecordSpeedButton: TSpeedButton;
ProgressBar1: TProgressBar;
MaxLabel: TLabel;
AudioIn1: TAudioIn;
Label1: TLabel;
procedure StartButtonClick(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure AudioIn1Stop(Sender: TObject);
procedure UpdateStatus;
procedure StopButtonClick(Sender: TObject);
procedure RecordSpeedButtonClick(Sender: TObject);
function AudioIn1BufferFilled(Buffer: PAnsiChar;
var Size: Integer): Boolean;
private

public
{ Public declarations }
WaveHeader : TWaveHeader ;
fs : TFileStream ;
Min, Max : Integer;
TempMax : Integer;
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.StartButtonClick(Sender: TObject);
begin

fs := TFileStream.Create('d:\b.wav',fmCreate);
WaveHeader.rId := $46464952;
WaveHeader.wId := $45564157;
WaveHeader.fId := $20746d66;
WaveHeader.dId := $61746164;
WaveHeader.wFormatTag := 1 ;
WaveHeader.nChannels :=2;
WaveHeader.nSamplesPerSec := 11025;
WaveHeader.wBitsPerSample := 16;
WaveHeader.wSampleLength := 0;
WaveHeader.fLen := WaveHeader.wBitsPerSample;
WaveHeader.nAvgBytesPerSec := WaveHeader.wBitsPerSample *
WaveHeader.nSamplesPerSec *
WaveHeader.nChannels div 8;
WaveHeader.nBlockAlign := WaveHeader.wBitsPerSample*WaveHeader.nChannels div 8;
fs.Write(WaveHeader,Sizeof(WaveHeader));

If (Not AudioIn1.Start(AudioIn1)) Then ShowMessage(AudioIn1.ErrorMessage)
Else
Begin
Min := 0;
Max := 0;
RecordSpeedButton.Down := TRUE;
End;
end;

Procedure TForm1.UpdateStatus;
begin
With AudioIn1 Do
If (AudioIn1.Active) Then
Begin
RunStatusLabel.Caption := 'Started';
BufferStatusLabel.Caption := Format('Queued: %3d; Processed: %3d',[QueuedBuffers, ProcessedBuffers]);
TimeStatusLabel.Caption := Format('Seconds %.3n',[ElapsedTime]);
End
Else
Begin
RunStatusLabel.Caption := 'Stopped';
BufferStatusLabel.Caption := '';
TimeStatusLabel.Caption := '';
End;

{ Update the progress bar }
If (AudioIn1.Active) Then
Begin
ProgressBar1.Position := Round(100*TempMax/36768.0);
If (Abs(Min) > Max) Then Max := Abs(Min);
MaxLabel.Caption := Format('Max %5d; Peak %5d',[Max,TempMax]);
End
Else
Begin
ProgressBar1.Position := 0;
MaxLabel.Caption := '';
End;

End;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
UpdateStatus;
end;

procedure TForm1.AudioIn1Stop(Sender: TObject);
begin
RecordSpeedButton.Down := FALSE;
end;


procedure TForm1.StopButtonClick(Sender: TObject);
begin
AudioIn1.StopAtOnce;
WaveHeader.rLen := WaveHeader.wSampleLength+36;
fs.Seek(0,soFromBeginning);
fs.Write(WaveHeader,Sizeof(WaveHeader));
fs.Free;
end;

procedure TForm1.RecordSpeedButtonClick(Sender: TObject);
begin
If (RecordSpeedButton.Down) Then
StartButtonClick(Sender)
Else
AudioIn1.StopAtOnce;
end;

function TForm1.AudioIn1BufferFilled(Buffer: PAnsiChar;
var Size: Integer): Boolean;
Var
SP : ^SmallInt;
i, N, v : Integer;
xMin, xMax : Integer;
begin
fs.Write(buffer^,Size);
WaveHeader.wSampleLength := WaveHeader.wSampleLength + Size;
Label1.Caption := IntToStr(WaveHeader.wSampleLength);

N := Size Div 2;
SP := Pointer(Buffer);
xMin := SP^;
xMax := xMin;

For i := 0 to N-1 Do
Begin
v := SP^; Inc(SP);
If (xMin > v) Then xMin := v;
If (xMax < v) Then xMax := v;
End;

If (Min > xMin) Then Min := xMin;
If (Max < xMax) Then Max := xMax;

TempMax := xMax;
If (Abs(xMin) > xMax) Then TempMax := Abs(xMin);
Result := TRUE;
end;

end.
xiangwangz 2003-11-15
  • 打赏
  • 举报
回复
也 太长了吧 !帮你up !顶 呵呵
donghaiw 2003-11-14
  • 打赏
  • 举报
回复
怎么没有人回答?

就是声音已经存到buffer中,怎样才能从buffer中输出到wav文件中?

谢谢。
donghaiw 2003-11-11
  • 打赏
  • 举报
回复
没有人知道吗?大家快up啊

1,183

社区成员

发帖
与我相关
我的任务
社区描述
Delphi GAME,图形处理/多媒体
社区管理员
  • GAME,图形处理/多媒体社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧