文档章节

操作 Wave 文件(7): 建立一个空的 Wave 文件(三种方法)

涂孟超
 涂孟超
发布于 2014/09/26 15:37
字数 518
阅读 5
收藏 0

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses MMSystem;

//chan: 1 单声道、2 立体声;
//freq: 频率, 取值: 11025, 22050, 44100
//bit : 每个样本的大小, 取值 8、16
function CreateWav1(chan, freq, bit: Word; const FilePath: string): Boolean;
var
  h: HMMIO;
  ckiRiff, ckiFmt, ckiData: TMMCKInfo;
  fmt: TPCMWaveFormat;
begin
  //此函数是使用 mmioCreateChunk 函数来分别建立 Wave 文件的每个块.

  {初识化相关结构}
  ZeroMemory(@ckiRiff, SizeOf(TMMCKInfo));
  ckiRiff.cksize := 36; {mmioCreateChunk 函数会自动写上 ckid, 但其 cksize 需要手动给}
  ckiRiff.fccType := mmioStringToFOURCC('WAVE', 0);

  ZeroMemory(@ckiFmt, SizeOf(TMMCKInfo));
  ckiFmt.ckid := mmioStringToFOURCC('fmt', 0);

  ZeroMemory(@ckiData, SizeOf(TMMCKInfo));
  ckiData.ckid := mmioStringToFOURCC('data', 0);

  {指定 Wave 格式}
  fmt.wf.wFormatTag := WAVE_FORMAT_PCM;
  fmt.wf.nChannels := chan;
  fmt.wf.nSamplesPerSec := freq;
  fmt.wf.nAvgBytesPerSec := freq * chan * bit div 8;
  fmt.wf.nBlockAlign := chan * bit div 8;
  fmt.wBitsPerSample := bit;

  h := mmioOpen(PChar(FilePath), nil, MMIO_CREATE or MMIO_WRITE);
  if h = 0 then Exit(False);

  {分别建立 RIFF、fmt、data 块}
  if (mmioCreateChunk(h, @ckiRiff, MMIO_CREATERIFF) = MMSYSERR_NOERROR) and
    (mmioCreateChunk(h, @ckiFmt, 0) = MMSYSERR_NOERROR) and
    (mmioWrite(h, PAnsiChar(@fmt), SizeOf(TPCMWaveFormat)) = SizeOf(TPCMWaveFormat)) and
    (mmioAscend(h, @ckiFmt, 0) = MMSYSERR_NOERROR) and
    (mmioCreateChunk(h, @ckiData, 0) = MMSYSERR_NOERROR) then Result := True;

  mmioClose(h, 0);
end;

//把 PCM 编码的 WAVE 文件的前 44 个字节看成一个结构来操作:
function CreateWav2(chan, freq, bit: Word; const FilePath: string): Boolean;
type
  TWaveHeader = record
    Riff_ckid      : DWORD;
    Riff_cksize    : DWORD;
    Riff_fccType   : DWORD;
    fmt_ckid       : DWORD;
    fmt_cksize     : DWORD;
    wFormatTag     : Word;
    nChannels      : Word;
    nSamplesPerSec : DWORD;
    nAvgBytesPerSec: DWORD;
    nBlockAlign    : Word;
    wBitsPerSample : Word;
    data_ckid      : DWORD;
    data_cksize    : DWORD;
  end;
var
  wh: TWaveHeader;
  hFile: Integer;
begin
  wh.Riff_ckid := FOURCC_RIFF;
  wh.Riff_cksize := 36;
  wh.Riff_fccType := mmioStringToFOURCC('WAVE', 0);
  wh.fmt_ckid := mmioStringToFOURCC('fmt', 0);
  wh.fmt_cksize := 16;
  wh.wFormatTag := WAVE_FORMAT_PCM;
  wh.nChannels := chan;
  wh.nSamplesPerSec := freq;
  wh.nAvgBytesPerSec := freq * chan * bit div 8;
  wh.nBlockAlign := chan * bit div 8;
  wh.wBitsPerSample := bit;
  wh.data_ckid := mmioStringToFOURCC('data', 0);
  wh.data_cksize := 0;

  hFile := FileCreate(FilePath);
  Result := (FileWrite(hFile, wh, SizeOf(TWaveHeader)) <> -1);
  FileClose(hFile);
end;

//同上, 只是改用流来写文件
function CreateWav3(chan, freq, bit: Word; const FilePath: string): Boolean;
type
  TWaveHeader = record
    Riff_ckid      : DWORD;
    Riff_cksize    : DWORD;
    Riff_fccType   : DWORD;
    fmt_ckid       : DWORD;
    fmt_cksize     : DWORD;
    wFormatTag     : Word;
    nChannels      : Word;
    nSamplesPerSec : DWORD;
    nAvgBytesPerSec: DWORD;
    nBlockAlign    : Word;
    wBitsPerSample : Word;
    data_ckid      : DWORD;
    data_cksize    : DWORD;
  end;
var
  wh: TWaveHeader;
begin
  wh.Riff_ckid := FOURCC_RIFF;
  wh.Riff_cksize := 36;
  wh.Riff_fccType := mmioStringToFOURCC('WAVE', 0);
  wh.fmt_ckid := mmioStringToFOURCC('fmt', 0);
  wh.fmt_cksize := 16;
  wh.wFormatTag := WAVE_FORMAT_PCM;
  wh.nChannels := chan;
  wh.nSamplesPerSec := freq;
  wh.nAvgBytesPerSec := freq * chan * bit div 8;
  wh.nBlockAlign := chan * bit div 8;
  wh.wBitsPerSample := bit;
  wh.data_ckid := mmioStringToFOURCC('data', 0);
  wh.data_cksize := 0;

  with TFileStream.Create(FilePath, fmCreate) do begin
    Result := (Write(wh, SizeOf(TWaveHeader)) = SizeOf(TWaveHeader));
    Free;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  CreateWav1(1, 11025, 8,  'C:\Temp\X1.wav');
  CreateWav2(2, 22050, 16, 'C:\Temp\X2.wav');
  CreateWav3(2, 44100, 16, 'C:\Temp\X3.wav');
end;

end.

 
 
 
 
 

 

 

  

本文转载自:http://www.cnblogs.com/del/archive/2009/11/10/1599435.html

共有 人打赏支持
涂孟超
粉丝 12
博文 2011
码字总数 14107
作品 0
深圳
程序员
私信 提问
进阶音效控制与管理(转载)

摘要 以 XNA 为基础的游戏程序可以利用 SoundEffect 类别的功能执行简单的音效播放,或是利用 SoundEffectInstance 类别进行进阶的音效播放控制,包括播放、暂停、恢复、结束、是否要播放 3D...

junwong
2012/02/17
494
0
【wav音频解析】之wavread函数的C++实现

本文由三部分组成,第一部分背景介绍 —— 音频类型及本文动机,第二部分类比matlab下wavread()函数的作用,第三部分则给出该函数的C++实现。 一 背景介绍 1.1 本文动机 1)所有wav音频处理的...

刘小米
2014/09/29
0
8
Apache 基金会让Google Wave 重生?

北京时间11月25日消息,据国外媒体报道,谷歌于今年8月宣布关闭在线实时沟通协作服务 Google Wave。但开源项目Apache软件基金会日前宣布将推出一款类似于Google Wave的服务,在其开源软件Apa...

小卒过河
2011/10/11
1K
7
痞子衡嵌入式:PCM编码与Waveform音频文件(.wav)格式详解

  大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是PCM编码及Waveform音频文件格式。   嵌入式里有时候也会和音频打交道,比如最近特别火的智能音箱产品,离不开前端的...

痞子衡
2018/08/12
0
0
视音频数据处理入门:PCM音频采样数据处理

===================================================== 视音频数据处理入门系列文章: 视音频数据处理入门:RGB、YUV像素数据处理 视音频数据处理入门:PCM音频采样数据处理 视音频数据处理...

leixiaohua1020
2016/01/29
0
0

没有更多内容

加载失败,请刷新页面

加载更多

vue 对对象的属性进行修改时,不能渲染页面 vue.$set()

我在vue里的方法里给一个对象添加某个属性时,我console.log出来的是已经更改的object ,但是页面始终没有变化 原因如下: **受现代 JavaScript 的限制 (而且 Object.observe 也已经被废弃),...

Js_Mei
今天
2
0
开始看《Java学习笔记》

虽然书买了很久,但一直没看。这其中也写过一些Java程序,但都是基于IDE的帮助和对C#的理解来写的,感觉不踏实。 林信良的书写得蛮好的,能够帮助打好基础,看得出作者是比较用心的。 第1章概...

max佩恩
昨天
12
0
Redux 三大原则

1.单一数据源 在传统的MVC架构中,我们可以根据需要创建无数个Model,而Model之间可以互相监听、触发事件甚至循环或嵌套触发事件,这些在Redux中都是不被允许的。 因为在Redux的思想里,一个...

wenxingjun
昨天
8
0
跟我学Spring Cloud(Finchley版)-12-微服务容错三板斧

至此,我们已实现服务发现、负载均衡,同时,使用Feign也实现了良好的远程调用——我们的代码是可读、可维护的。理论上,我们现在已经能构建一个不错的分布式应用了,但微服务之间是通过网络...

周立_ITMuch
昨天
5
0
XML

学习目标  能够说出XML的作用  能够编写XML文档声明  能够编写符合语法的XML  能够通过DTD约束编写XML文档  能够通过Schema约束编写XML文档  能够通过Dom4j解析XML文档 第1章 xm...

stars永恒
昨天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部