您当前的位置:首页 > 电子 > 无线/电,信号与通信

pcm2wav: 将PCM数据转换成WAV文件

时间:04-14来源:作者:点击数:

1 perl脚本

在北大中文论坛看到一位网友问起怎样把大尾的PCM数据播放出来。我以前在工作中碰到过8K采样的PCM数据,当时不清楚wav文件的格式, 正好perl模块中有个Audio::Wav模块可以写wav文件,就写了个perl脚本:

use Audio::Wav;

my $wav = new Audio::Wav;

my $sample_rate = 8000;
my $bits_sample = 16;

my $details = {
              'bits_sample'       => $bits_sample,
              'sample_rate'       => $sample_rate,
              'channels'          => 1,
            };

my $write = $wav -> write( 'testout.wav', $details );

my $inputFile = "dout.txt";
open (INFILE, "<$inputFile") or die "The file $inputFile ".
	"could not be opened.\n";
my @pcm_data = ;
close(INFILE);

my $samp;
foreach $samp(@pcm_data) {
	chomp($samp);
	$write -> write( $samp );
}

$write -> finish();

这几行脚本就可以把PCM数据转换到wav文件。后来我看过wav文件格式,觉得很简单,这次又看到网友提到这个问题,就抽空写了个小程序。

2 pcm2wav

将PCM数据转换成WAV文件其实只是加个文件头。但要做给普通用户用,界面比较费时间。我找了一个以前写的html2txt工程修改一下,花了半个晚上和一个中午,完成了这个pcm2wav程序。

3 实现原理

网上有一篇曹京写的《wav文件格式分析详解》已经介绍过wav文件格式,有兴趣的读者可以查阅。wav文件通常包含4段:RIFF、格式段、FACT段和数据段。 PCM数据就放在数据段。只要格式段设置的格式与数据段的数据一致,播放程序就可以正确解析。 下面这个数组的数据其实就是一个最小的wav文件。

static const unsigned char wav_template[] =
{
	// RIFF WAVE Chunk
	0x52, 0x49, 0x46, 0x46,		// "RIFF"
	0x30, 0x00, 0x00, 0x00,		// 总长度 整个wav文件大小减去ID和Size所占用的字节数
	0x57, 0x41, 0x56, 0x45,		// "WAVE"
	
	// Format Chunk
	0x66, 0x6D, 0x74, 0x20,		// "fmt "
	0x10, 0x00, 0x00, 0x00,		// 块长度
	0x01, 0x00,			// 编码方式
	0x01, 0x00,			// 声道数目
	0x80, 0x3E, 0x00, 0x00,		// 采样频率
	0x00, 0x7D, 0x00, 0x00,		// 每秒所需字节数=采样频率*块对齐字节
	0x02, 0x00,			// 数据对齐字节=每个样本字节数*声道数目
	0x10, 0x00,			// 样本宽度
	
	// Fact Chunk
	0x66, 0x61, 0x63, 0x74,		// "fact"
	0x04, 0x00, 0x00, 0x00,		// 块长度
	0x00, 0xBE, 0x00, 0x00, 

	// Data Chunk
	0x64, 0x61, 0x74, 0x61,		// "data"
	0x00, 0x00, 0x00, 0x00,		// 块长度
};

这个wav文件的数据长度为0。我们要增加PCM数据只要完成以下工作:

  • 在数据段尾增加PCM数据;
  • 修改数据段的块长度,修改RIFF段的总长度;
  • 正确设置格式段的PCM参数。

样本长度可能不是8的整数倍,这时wav文件还是要求样本按照字节对齐。在一个样本中数据是左对齐的,右侧空位用0填充。 pcm2wav只考虑了样本长度是16位的情况。

如果有多个声道,wav文件要求先放样本1的各声道数据,再放样本2的各声道数据,依此类推。 因为我没有碰到过处理多声道数据的需求,所以pcm2wav只考虑了单声道。

4 结束语

用户可以从这里下载pcm2wav程序。如果转换个别文件,其实可以用一个叫WaveCN的程序。 不过WaveCN不支持big endian。我现在不怎么用到PCM数据,但写这种简单的程序,其实和打一个小游戏也差不多, 一些按部就班,几个小关卡和一点成功的喜悦。

5 后记

根据网友需求,增加了单声道、双声道选择,样本宽度,提供更多采样率,并允许输入采样率。

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门