菜鸟问各位大侠:如何将几个声音文件并成一个文件?救救我!!!

NewSea 2000-08-22 10:35:00
如何使用Delphi将几个声音文件(Wav格式)合并成一个文件?救救我!!!
...全文
163 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
NewSea 2000-11-08
  • 打赏
  • 举报
回复
ok
jiangtao 2000-08-23
  • 打赏
  • 举报
回复
这是我写的一个程序,实现合并标准wav文件还是比较简单的
jiangtao 2000-08-23
  • 打赏
  • 举报
回复
unit waveutil;

interface

uses
Windows,Sysutils,MMSystem,Dialogs;

const
Wave_Format_ADPCM = 2;
MSADPCM_NUM_COEF = 7; { ADPCM: number of predictors }

FOURCC_RIFF = $46464952; { 'RIFF' }
FOURCC_WAVE = $45564157; { 'WAVE' }
FOURCC_fmt = $20746D66; { ' fmt' }
FOURCC_data = $61746164; { 'data' }

type

ArrayIndex = 0..99999999;
TByteArray = array[ArrayIndex] of Byte;
PByteArray = ^TByteArray;
TSmallintArray = array[ArrayIndex] of Smallint;
PSmallintArray = ^TSmallintArray;

WaveFileHeader = packed record
ckid: FOURCC; // chunk ID--'RIFF'
cksize: DWORD; // chunk size--File SIze
rifftype: FOURCC; // riff type --'WAVE'
end;

RawWaveData = packed record
chunkID: FOURCC; // fmt chunk id-'DATA'
chunkSize: LongInt; //
//waveformData: array[0..0] of byte;
end;

WaveFmtHeader =packed record
fmtid: FOURCC; // fmt chunk id-'fmt '
chunkSize: LongInt; // size of the chunk not include <id and size>
end;

PWaveFormatE = ^TWaveFormat;
TWaveFormatE = packed record
wFormatTag: Word; //format type-- PCM = 1
nChannels: Word; // number of channels (i.e. mono, stereo, etc.)
nSamplesPerSec: DWORD; // sample rate (11025,22050,44010)
nAvgBytesPerSec: DWORD; // for buffer estimation
nBlockAlign: Word; // block size of data
wBitsPerSample: Word; // number of bits per sample of mono data
//cbSize: Word; // the count in bytes of the size of extra
//extra data format
end;

{ Predictors for ADPCM }
TADPCMCoef = packed record
Coef1, Coef2: SmallInt;
end;
TADPCMCoefSet = Array[0..MSADPCM_NUM_COEF-1] of TADPCMCoef;
PADPCMCoefSet = ^TADPCMCoefSet;

TWaveFormatEx = packed record
wFormatTag: Word; { format type }
nChannels: Word; { number of channels (i.e. mono, stereo, etc.) }
nSamplesPerSec: Longint; { sample rate }
nAvgBytesPerSec: Longint; { for buffer estimation }
nBlockAlign: Word; { block size of data }
wBitsPerSample: Word;
cbSize: Word; { SizeOf(wSamplesPerBlock..Predictors. Optional with PCM
extra size}
wSamplesPerBlock: SmallInt;
wNumCoef: SmallInt; { const 7 }
CoefSet: TADPCMCoefSet;
end;
PWaveFormatEx = ^TWaveFormatEx;

TWaveFile = Class (TObject)
FMMioHandle :Integer;
FFileName :String;
FWaveFormat : TWaveFormatEx;
FDataBytes,FDataOffset: Integer;
FFileSize:Integer;
SampleCount: LongInt;
public
constructor Create;
destructor Destory;
function OpenWaveFile(FileName: string):Boolean;
function GetDataBuffer(Buffer:PChar):Integer;
function ReadData(Buffer:PChar;dataPos,readbytes:Integer):Integer;
function WriteData(Buffer:PChar;dataPos,readbytes:Integer):Integer;
procedure CloseWaveFile;
function GetDataSecs:Integer;
function IsFileOpen:Boolean;
published
property WaveFormat: TWaveFormatEx read FWaveFormat;
property FileSize:Integer read FFileSize;
property DataBytes:Integer read FDataBytes;
property DataSecs:Integer read GetDataSecs;
end;

function CreateWaveFile(FileName:String;SampleRate,BitsNum:Integer;Stereo:Boolean):Integer;
function PlayWaveFile(FileName:String):Integer;
function StripeWaveFile(FileName:String):Integer;
function writeWaveFileFromBuf(tmpBuffer:PChar;VocLen:Integer;TripSilence:Boolean):String;

//Used for 变换语音文件放大因子,由于输入Microphone声音太小或太大可以
//按比例进行放缩
function getBufferPeak(ptrBuf:PSmallInt;BufSize,FrameSize:Integer):Single;

function getWaveFileLen(fileName:String;var lSecs,lBytes:Integer):Bool;
function getWaveFileFormat(fileName:String;var Sample,BitsNum:Integer;var Stereo:Boolean):Bool;

implementation

Uses
{#IFDEF DETECT_VER}
Detect,
{#ENDIF}
Myutils;

function getWaveFileLen(fileName:String;var lSecs,lBytes:Integer):Bool;
begin
result:=False;
with TWaveFile.Create do
begin
if OpenWaveFile(fileName) then
begin
lSecs:=DataSecs;
lBytes:=DataBytes;
CloseWaveFile;
result:=True;
end;
Free;
end; // with

end;

function getWaveFileFormat(fileName:String;var Sample,BitsNum:Integer;var Stereo:Boolean):Bool;
begin
result:=False;
with TWaveFile.Create do
begin
if OpenWaveFile(fileName) then
begin
Sample:=FWaveFormat.nSamplesPerSec;
BitsNum:=FWaveFormat.wBitsPerSample;
if FWaveFormat.nChannels = 1 then
Stereo:=False
else
Stereo:=True;
CloseWaveFile;
result:=True;
end;
Free;
end; // with

end;


function PlayWaveFile(FileName:String):Integer;
begin
SndPlaySound(PChar(FileName),SND_SYNC or SND_NODEFAULT);
end;

procedure Error(Text: string);
var
StackTop: record end;
Stack: record
EBP: Integer;
ReturnAddress: Pointer;
end absolute StackTop;
begin
raise Exception.Create(Text) at Stack.ReturnAddress;
end;



constructor TWaveFile.Create;
begin
inherited Create;
FMMioHandle:=0;
FDataBytes:=0;
FDataOffset:=0;
FFileSize:=0;
end;

destructor TWaveFile.Destory;
begin
inherited;
if FMMioHandle <> 0 then
CloseWaveFile;
end;

//打开Wave文件,得到Wave的数据格式FWaveFormat
function TWaveFile.OpenWaveFile(FileName: string):Boolean;
var
ckRIFF, ck: TMMCKINFO;
procedure ErrExit(Msg: String);
begin
Error(FileName+': '+Msg);
end;
begin
result:=False;

if (FileName = '') or not FileExists(FileName)
then Error('File '+FileName+' not found.');

Assert(FMMioHandle=0);
FMMioHandle := mmioOpen(PChar(FileName), nil, MMIO_READ or MMIO_ALLOCBUF);
if FMMioHandle = 0 then ErrExit('mmioOpen failed');
try
FFileName:=FileName;
ckRIFF.fccType := mmioStringToFourCC('WAVE',0);
if mmioDescend(FMMioHandle, @ckRIFF, nil, MMIO_FINDRIFF) <> 0
then ErrExit('WAVE chunk not found');

FillChar(FWaveFormat,SizeOf(FWaveFormat), 0);
SampleCount := 0;

while mmioDescend(FMMioHandle, @ck, @ckRIFF, 0) = MMSYSERR_NOERROR do
begin
if (ck.dwDataOffset + ck.cksize) > (ckRIFF.dwDataOffset + ckRIFF.cksize)
then ErrExit('Chunk size mismatch');

if ck.ckid = mmioStringToFourCC('fmt ',0) then
begin
if FWaveFormat.wFormatTag = 0 then
begin
if ck.ckSize > SizeOf(TWaveFormatEx) then
ErrExit('ADPCM, unexpected number of coefficients');

if mmioRead(FMMioHandle, @FWaveFormat, ck.ckSize) <> ck.ckSize then
ErrExit('Error reading ''fmt '' chunk');
end;
end
else
if ck.ckid = mmioStringToFourCC('fact',0) then
begin
if (SampleCount = 0) and (FWaveFormat.wFormatTag = Wave_Format_ADPCM) then
begin
mmioRead(FMMioHandle, @SampleCount, SizeOf(LongInt));
end; { else multiple fact chunks - ignore }
end
else if ck.ckid = mmioStringToFourCC('data',0) then
begin
FDataBytes := ck.cksize;
case FWaveFormat.wFormatTag of
0:
ErrExit('No ''fmt '' chunk');
Wave_Format_PCM:
with FWaveFormat do
{ not documented: Avg div SamplesPerSec always integer }
SampleCount := FDataBytes div (nAvgBytesPerSec div nSamplesPerSec);
Wave_Format_ADPCM:
;
else
ErrExit('''fmt '' chunk exists, but unknown format');
end;
FDataOffset:=mmioSeek(FMmioHandle,0,1);//from cur
{
if bReadBuffer then
begin
GetMem(Buf, DataBytes);
mmioRead(FMMioHandle, PChar(Buf), DataBytes);
end;
}
end;
{ else leave subchunk }
mmioAscend(FMMioHandle, @ck, 0);
end; { while mmioDescend }
finally
//mmioClose(FMMioHandle,0);
FFileSize:=mmioSeek(FMMioHandle,0,2);
end;
result:=True;
end;

//返回Wave数据的总秒数
function TWaveFile.GetDataSecs:Integer;
begin
result:=DataBytes div FWaveFormat.nAvgBytesPerSec;
end;

//读出整个Wave数据区
function TWaveFile.GetDataBuffer(Buffer:PChar):Integer;
begin
result:=0;
if (FDataBytes > 0) and (FDataOffset>=44) then
begin
mmioSeek(FMMioHandle,FDataoffset,0);//from beginning
result:=mmioRead(FMmioHandle,Buffer,FDataBytes);
end;
end;



function TWaveFile.WriteData(Buffer:PChar;dataPos,readbytes:Integer):Integer;
begin
if FMMiohandle <> 0 then
begin
mmioSeek(FMMioHandle,FDataOffset+dataPos,0);
result:=mmioWrite(FMMioHandle,buffer,readBytes);
//可能有错
//应重新修改FWaveFormat的相关数据
end;
end;

function TWaveFile.ReadData(Buffer:PChar;dataPos,readbytes:Integer):Integer;
begin
if FMMiohandle <> 0 then
begin
mmioSeek(FMMioHandle,FDataOffset+dataPos,0);
result:=mmioRead(FMMioHandle,buffer,readBytes);
end;
end;


procedure TWaveFile.CloseWaveFile;
begin
if FMMioHandle <> 0 then
mmioClose(FMMioHandle,0);
FMMioHandle:=0;
end;

function TWaveFile.IsFileOpen:Boolean;
begin
result := (FMMioHandle <> 0);
end;


//功能:创建Wave文件
//参数:FileName-----文件名
//返回:其他:成功
// -1: 错误
function CreateWaveFile(FileName:String;SampleRate,BitsNum:Integer;Stereo:Boolean):Integer;
var
aHDr :WaveFileHeader;
aData :RawWaveData;
aFmt : WaveFmtHeader;
aWaveFormat:TWaveFormatEx;
begin
result:=FileCreate(FileName);
if result = -1 then
//ShowMessage('Create File Error');
Error('无法创建文件');
if result > 0 then
begin
with aHdr do
begin
ckid:=FOURCC_RIFF;
cksize:=44;
rifftype:=FOURCC_WAVE;
end;
FileWrite(result,aHDr,SizeOf(WaveFileHeader));

with aFmt do
begin
fmtid:=FOURCC_FMT;
chunksize:=$10; //for standard format
end;
FileWrite(result,aFmt,SizeOf(WaveFmtHeader));

with aWaveFormat do
begin
aWaveFormat.wFormatTag:=1; //pcm
{
aWaveFormat.nChannels:=1;
aWaveFormat.nSamplesPerSec:=11025;
aWaveFormat.wBitsPerSample:=16;
aWaveFormat.nAvgBytesPerSec:=22050;
}
if Stereo then
aWaveFormat.nChannels:=2
else
aWaveFormat.nChannels:=1;

aWaveFormat.nSamplesPerSec:=SampleRate;
aWaveFormat.wBitsPerSample:=BitsNum;
aWaveFormat.nBlockAlign:=(BitsNum div 8)*aWaveFormat.nChannels;
aWaveFormat.nAvgBytesPerSec:=SampleRate*aWaveFormat.nBlockAlign;
end;
FileWrite(result,aWaveFormat,SizeOf(TWaveFormatE));

with aData do
begin
chunkID:=FOURCC_DATA;
chunkSize:=0;
end;
FileWrite(result,aData,SizeOf(RawWaveData));
end;
end;
yinfudan 2000-08-23
  • 打赏
  • 举报
回复
非常困难,你得知道Wave文件的格式,然后手工读写文件完成。
我有Wave文件的格式,若要可以问我要,yinfudan@yahoo.com
alin 2000-08-23
  • 打赏
  • 举报
回复
想做什么?
可以用读二进制文件方法,
1.建新文件NEW.WAV
2.读第一个文件,写入NEW.WAV,记录长度(可在NEW.WAV前加文件头记录,如果是直接播放,即合并多个WAV的话,就不能用文件头了,WAV文件好像步接后可直接用,没什么影响的)
3.读第二个文件,在NEW.WAV后写入
4.第三个文件.,在NEW.WAV后写入......
5.关闭NEW.WAV

5,379

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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