合并两个 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. ipsec-tools安装教程

    ipsec-tools最新版本为0.8.2,此处以0.7.3版本为例说明安装和使用过程.可参考ipsec-howto. 安装步骤 ipsec-tools依赖于linux2.6版本内核,在安装ipsec ...

  2. vue项目里的日期格式化

    在项目中,我们经常需要把后台传回的日期进行格式化,可以在common里定义一个公共的js export function formatDate (date, fmt) { if (/(y+)/.tes ...

  3. java JVM指令2

    https://www.cnblogs.com/dreamroute/p/5089513.html 指令码 助记符 说明 0x00 nop 什么都不做 0x01 aconst_null 将null推送 ...

  4. 有没有 linux 命令可以获取我的公网 ip, 类似 ip138.com 上获取的 ip?

    curl ipinfo.iocurl ifconfig.me 阿里云 :139.129.242.131赤峰:   219.159.38.197开平:   221.194.113.146定州:  121 ...

  5. C#小票打印机

    使用的佳博GP-5890XIII http://www.cnblogs.com/lovenan/p/3217448.html using System; using System.Collection ...

  6. MAC下代理工具Charles使用

    一.跟踪HTTPS 1.下载官方的证书ssl.zip证书,解压成*.crt 2.可以通过邮箱或者发布到自己的服务器的方式,然后用手机去下载安装crt文件. 3.charles设置Proxy--> ...

  7. 洛谷P4107 [HEOI2015]兔子与樱花 [贪心,DFS]

    题目传送门 兔子与樱花 题目描述 很久很久之前,森林里住着一群兔子.有一天,兔子们突然决定要去看樱花.兔子们所在森林里的樱花树很特殊.樱花树由n个树枝分叉点组成,编号从0到n-1,这n个分叉点由n-1 ...

  8. Redis创建高可用集群教程【Windows环境】

    模仿的过程中,加入自己的思考和理解,也会有进步和收获. 在这个互联网时代,在高并发和高流量可能随时爆发的情况下,单机版的系统或者单机版的应用已经无法生存,越来越多的应用开始支持集群,支持分布式部署了. ...

  9. 小成就之解决调用spring中FileSystemXmlApplicationContext路径问题

    此文写下调用spring过程中遇到的一个问题!或许对于入行的人一看觉得我很傻逼吧,这问题谁都会了!但我觉得对于新手(自已)来说,算是一个好思路与好办法! 问题: 对于 test_aa ta = (te ...

  10. 使用Newlife网络库管道模式解决数据粘包(二)

    上一篇我们讲了 如何创建一个基本的Newlife网络服务端 这边我们来讲一下如何解决粘包的问题 在上一篇总我们注册了Newlife的管道处理器 ,我们来看看他是如何实现粘包处理的 svr.Add< ...