合并两个 Wav 文件的函数

实例一

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

{合并两个 Wav 文件的函数}
function ConWavFile(AWavFile1, AWavFile2, ANewFile: string): Boolean;
type
TWavFormat = packed record
ChunkID: array[0..3] of AnsiChar; {'RIFF'}
ChunkSize: Longword; {size-8}
Format: array[0..3] of AnsiChar; {'WAVE'}
SubChunk1ID: array[0..3] of AnsiChar; {'fmt '}
SubChunk1Size: Longword; {hex10}
AudioFormat: Word; {hex 01}
NumOfChannels: Word; {1 mono, 2 stereo}
SampleRate: Longword; {number of samples/sec}
ByteRate: Longword; {samplerate* num of channels*bytes per (mono) sample}
BytesperSample: Word; {size of (mono) sample}
BitsPerSample: Word; {BytesperSample *8}
SubChunk2ID: array[0..3] of AnsiChar; {'data'}
SubChunk2Size: Longword; {number of data bytes}
end;
var
vWavFormat1: TWavFormat;
vWavFormat2: TWavFormat;
vFileHandle1: THandle;
vFileHandle2: THandle;
vFileStream1: TFileStream;
vFileStream2: TFileStream;
vChunkSize1, vChunkSize2: Integer;
begin
Result := False;
if not FileExists(AWavFile1) then Exit;
if not FileExists(AWavFile2) then Exit;

vFileHandle1 := _lopen(PAnsiChar(AnsiString(AWavFile1)), OF_READ or OF_SHARE_DENY_NONE);
vFileHandle2 := _lopen(PAnsiChar(AnsiString(AWavFile2)), OF_READ or OF_SHARE_DENY_NONE);

if (Integer(vFileHandle1) <= 0) or (Integer(vFileHandle2) <= 0) then
begin
_lclose(vFileHandle1);
_lclose(vFileHandle2);
Exit;
end;

vFileStream1 := TFileStream.Create(vFileHandle1);
vFileStream2 := TFileStream.Create(vFileHandle2);
try
if vFileStream1.Read(vWavFormat1, SizeOf(TWavFormat)) <> SizeOf(TWavFormat) then Exit;
if vFileStream2.Read(vWavFormat2, SizeOf(TWavFormat)) <> SizeOf(TWavFormat) then Exit;
if vWavFormat1.ChunkID <> 'RIFF' then Exit;
if vWavFormat1.SubChunk2ID <> 'data' then Exit;
vChunkSize1 := vWavFormat1.SubChunk2Size;
vChunkSize2 := vWavFormat2.SubChunk2Size;
vWavFormat1.ChunkSize := 0;
vWavFormat1.SubChunk2Size := 0;
vWavFormat2.ChunkSize := 0;
vWavFormat2.SubChunk2Size := 0;
if not CompareMem(@vWavFormat1, @vWavFormat2, SizeOf(TWavFormat)) then Exit; {格式不同}
with TMemoryStream.Create do try
vWavFormat1.ChunkSize := vChunkSize1 + vChunkSize2 + SizeOf(vWavFormat1) - 8;
vWavFormat1.SubChunk2Size := vChunkSize1 + vChunkSize2;
Write(vWavFormat1, SizeOf(TWavFormat));
CopyFrom(vFileStream1, vChunkSize1);
CopyFrom(vFileStream2, vChunkSize2);
try
SaveToFile(ANewFile);
except
Exit;
end;
finally
Free;
end;
finally
vFileStream1.Free;
vFileStream2.Free;
end;
Result := True;
end; { ConWavFile End}

{测试}
procedure TForm1.Button1Click(Sender: TObject);
var
Wav1,Wav2,WavDest: string;
begin
Wav1 := 'c:\temp\1.wav';
Wav2 := 'c:\temp\2.wav';
WavDest := 'c:\temp\12.wav';
if ConWavFile(Wav1, Wav2, WavDest) then
ShowMessageFmt('''%s'' 和 ''%s'' 已成功合并到 ''%s''', [Wav1,Wav2,WavDest]);
end;

end.

实例二

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

uses MMSystem;

{合并两个 Wav 文件流的函数}
function ConWavStream(AWavStream1, AWavStream2: TStream; var ANewStream: TStream): Boolean;
type
TWavFormat = packed record
ChunkID: array[0..3] of AnsiChar; {'RIFF'}
ChunkSize: Longword; {size-8}
Format: array[0..3] of AnsiChar; {'WAVE'}
SubChunk1ID: array[0..3] of AnsiChar; {'fmt '}
SubChunk1Size: Longword; {hex10}
AudioFormat: Word; {hex 01}
NumOfChannels: Word; {1 mono, 2 stereo}
SampleRate: Longword; {number of samples/sec}
ByteRate: Longword; {samplerate* num of channels*bytes per (mono) sample}
BytesperSample: Word; {size of (mono) sample}
BitsPerSample: Word; {BytesperSample *8}
SubChunk2ID: array[0..3] of AnsiChar; {'data'}
SubChunk2Size: Longword; {number of data bytes}
end;
var
vWavFormat1: TWavFormat;
vWavFormat2: TWavFormat;
vChunkSize1, vChunkSize2: Integer;
begin
Result := False;
if AWavStream1.Read(vWavFormat1, SizeOf(TWavFormat)) <> SizeOf(TWavFormat) then Exit;
if AWavStream2.Read(vWavFormat2, SizeOf(TWavFormat)) <> SizeOf(TWavFormat) then Exit;
if vWavFormat1.ChunkID <> 'RIFF' then Exit;
if vWavFormat1.SubChunk2ID <> 'data' then Exit;
vChunkSize1 := vWavFormat1.SubChunk2Size;
vChunkSize2 := vWavFormat2.SubChunk2Size;
vWavFormat1.ChunkSize := 0;
vWavFormat1.SubChunk2Size := 0;
vWavFormat2.ChunkSize := 0;
vWavFormat2.SubChunk2Size := 0;
if not CompareMem(@vWavFormat1, @vWavFormat2, SizeOf(TWavFormat)) then Exit; {格式不同}

vWavFormat1.ChunkSize := vChunkSize1 + vChunkSize2 + SizeOf(vWavFormat1) - 8;
vWavFormat1.SubChunk2Size := vChunkSize1 + vChunkSize2;
ANewStream.Write(vWavFormat1, SizeOf(TWavFormat));
ANewStream.CopyFrom(AWavStream1, vChunkSize1);
ANewStream.CopyFrom(AWavStream2, vChunkSize2);

Result := True;
end; { ConWavStream End}

var
WavStream: TStream;

{合并两个资源流; 之前要在资源中分别加载两个 WAV 文件, 并分别命名: wav1、wav2}
procedure TForm1.FormCreate(Sender: TObject);
var
rs1,rs2: TResourceStream;
begin
rs1 := TResourceStream.Create(HInstance, 'wav1', RT_RCDATA);
rs2 := TResourceStream.Create(HInstance, 'wav2', RT_RCDATA);
WavStream := TMemoryStream.Create;
ConWavStream(rs1, rs2, WavStream);
rs1.Free;
rs2.Free;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
WavStream.Free;
end;

{循环播放}
procedure TForm1.Button1Click(Sender: TObject);
begin
sndPlaySound(TMemoryStream(WavStream).Memory, SND_ASYNC or SND_MEMORY or SND_LOOP);
end;

{暂停}
procedure TForm1.Button2Click(Sender: TObject);
begin
sndPlaySound(nil, 0);
end;

end.

delphi 合并两个 Wav 文件流的函数的更多相关文章

  1. 利用bat合并两个hex文件

    单片机程序如果有IAP功能的话,就会生成两个hex文件,一个是Boot,一个是App,如果给让生产烧录两个文件,就会降低生产效率,所以在烧录前最好将两个文件合并成一个文件,烧录一次即可,合并方法如下: ...

  2. 合并两个yuv文件的C++代码

    //将BasketballPass_416x240_50.yuv序列的前50帧和BlowingBubbles_416x240_50.yuv序列的前250帧合并成out.yuv //参数配置416 24 ...

  3. c语言中的文件流

    一.打开和关闭文件 #include int main( void ) { FILE* pReadFile = fopen( "E:\\mytest.txt", "r&q ...

  4. ionic2+集成第三方sdk时,合并多个清单文件的方法

    具体方案android studio官网上已经给出,但需要架梯子,所以这篇文章直接把它搬到墙内,方便查看: 合并多个清单文件 合并优先级 合并冲突启发式算法 合并规则标记 节点标记 属性标记 标记选择 ...

  5. (C/C++学习)2.C语言中文件流操作基本函数总结

    函数所在头文件:stdio.h 说明:前半部分主要为对各个文件流操作函数的例举,后半部分着重于上机运行分析.文中部分引用自王桂林老师的C/C++课件. 1.FIELE *fopen(const cha ...

  6. 两个js文件之间函数互调问题

    按照常理来说,在<body>标签结束之前以下面的方式引入两个js文件 <script src="a.js"></script> <scri ...

  7. C语言对文件的操作函数用法详解2

    fopen(打开文件) 相关函数 open,fclose 表头文件 #include<stdio.h> 定义函数 FILE * fopen(const char * path,const  ...

  8. C# 使用NAudio合并mp3、wav音频文件

    1.什么是wav格式    WAV为微软公司(Microsoft)开发的一种声音文件格式,它符合RIFF(Resource Interchange File Format)文件规范,用于保存Windo ...

  9. delphi 基础之三 文件流操作

    文件流操作 Delphi操作流文件:什么是流?流,简单来说就是建立在面向对象基础上的一种抽象的处理数据的工具.在流中,定义了一些处理数据的基本操作,如读取数据,写入数据等,程序员是对流进行所有操作的, ...

随机推荐

  1. 巧用PHP数组函数

    2014年3月5日 08:48:39 情景:项目中需要根据传递来的参数的不同,使用不同的缓存 假如传递来的参数最多有这几个(在这个范围内,但是每次传过来的参数不确定): $arg = array( ' ...

  2. 解决依赖的moduleBuildConfig.DEBUG总是未false的问题

    Android 开发中一般会通过 BuildConfig.DEBUG 判断是否是 Debug 模式,从而做一些在 Debug 模式才开启的特殊操作,比如打印日志.这样好处是不用在发布前去主动修改,因为 ...

  3. win7(x64)安装scrapy框架

    Scrapy(官网http://scrapy.org/)是Python开发网络爬虫,一个极好的开源工具.本次安装Scrapy确实不易啊.居然花了2天多时间,需要的支持包比较多,这些支持包相互之间的依赖 ...

  4. Java 基本语法---流程控制

    Java 基本语法---流程控制 0. 概述 三大流程控制语句:顺序.选择.循环. 选择结构: if 结构,if - else结构: 多重 if - else 语句 ; 嵌套 if - else 语句 ...

  5. 使用html+css+js实现弹球游戏

    使用html+css+js实现弹球游戏 效果图: 代码如下,复制即可使用: <!doctype html> <head> <style type="text/c ...

  6. Visual C++中最常用的类与API函数

    这篇文章能让初学者快速了解visual C++ MFC中常见的核心的类与函数,虽然全部看下来有点枯燥,但对初学者快速了解MFC的框架结构很有好处. 常用类 CArchive类:用于二进制保存档案 CB ...

  7. Java编程的逻辑 (67) - 线程的基本协作机制 (上)

    ​本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http: ...

  8. Vue.js项目集成ElementUI

    Vuejs实例-02Vue.js项目集成ElementUI   Vuejs实例-02Vue.js项目集成ElementUI 0:前言 vue.js的UI组件库,在git上有多个项目,我见的使用者比较多 ...

  9. 如何对手机使用adb

    因为要配合前端做测试,所以我需要在本机中安装adb驱动,以便可以连接手机进行各种操作. 好吧...装adb驱动这块当时我没有把流程给做记录...郁闷,下次再安装的时候再谷歌吧. 使用的简单脚本就是 有 ...

  10. AngularJS过滤器filter入门

    在开发中,经常会遇到这样的场景 如用户的性别分为“男”和“女”,在数据库中保存的值为1和0,用户在查看自己的性别时后端返回的值自然是1或0,前端要转换为“男”或“女”再显示出来: 如我要换个羽毛球拍, ...