请参阅我在http://textsnip.com/see/WAVinAS3创建的类,以便在ActionScript 3.0中解析WAVE文件。
此课程正确地从文件标题中删除信息& fmt chunk,隔离数据块,并创建一个新的ByteArray来存储数据块。它接收一个格式为1的未压缩WAVE文件.WWVE文件嵌入到我的SWF中,带有以下Flex嵌入标记:
[Embed(source="some_sound.wav", mimeType="application/octet-stream")]
public var sound_class:Class;
public var wave:WaveFile = new WaveFile(new sound_class());
在数据块分离后,该类尝试创建一个可以从数据块中流式传输样本的Sound对象。我遇到流式传输过程的问题,可能是因为我不擅长数学,也不知道比特/字节等发生了什么。
以下是我用作WAVE文件格式参考的两个文档: http://www.lightlink.com/tjweber/StripWav/Canon.html https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
现在,文件正在播放!实时,甚至!但是......声音真的扭曲了。发生了什么事?
答案 0 :(得分:1)
问题在于onSampleData处理程序。
在你的wav文件中,幅度存储为有符号短路,即16位整数。您正在以32位签名浮动的形式阅读它们。整数和浮点数以二进制表示,因此永远不会正常工作。
现在,玩家期待浮动。他们为什么使用花车?不确定,但一个很好的理由是它允许玩家接受每个样本的标准化值。这样你就不必关心或知道玩家正在使用什么bitdept:最大值为1,最小值为-1,就是这样。
所以,您的问题是您必须将签名的短片转换为标准化的有符号浮点数。短路需要16位,因此它可以存储2 ^ 16(或65,536)个不同的值。由于它已签名并且符号占用一位,因此最大值将为2 ^ 15.因此,您知道您的输入范围是-32,768 ... 32,767。
样本值已标准化,另一方面必须在-1 ... 1范围内。
所以,你必须规范你的输入。这很容易。只需读取读取值并将其除以最大值,然后将输入幅度转换为-1 ... 1的范围。
这样的事情:
private function onSampleData(evt:SampleDataEvent):void
{
var amplitude:int = 0;
var maxAmplitude:int = 1 << (bitsPerSample - 1); // or Math.pow(2, bitsPerSample - 1);
var sample:Number = 0;
var actualSamples:int = 8192;
var samplesPerChannel:int = actualSamples / channels;
for ( var c:int = 0; c < samplesPerChannel ; c++ ) {
var i:int = 0;
while(i < channels && data.bytesAvailable >= 2) {
amplitude = data.readShort();
sample = amplitude / maxAmplitude;
evt.data.writeFloat(sample);
i++;
}
}
}
有几点需要注意:
maxAmplitude可能(也可能是 应该)当你阅读时计算 bitdepth。我在做这件事 方法只是为了让你可以在中看到它 粘贴代码。
虽然计算了maxAmplitude 基于读取的bitdepth,因此 任何bitdepth都是正确的, 我在循环中读短裤,所以 如果您的wav文件碰巧使用了 不同的bitdepth,这个功能 将无法正常工作。你可以 添加一个开关并阅读必要的 数据量(即readInt if) bitdepth是32)。但是,16位是 这样一个广泛使用的标准,我 怀疑这是否真的需要。
此功能适用于 立体声波。如果你想要它的工作 对于单声道,重新写它来写 相同的样品两次。也就是说,每个人 读,你做两次写(你的输入 是单声道,但玩家期望2 样本)。
我尽可能地删除了EOF捕获 知道你是否有足够的数据来阅读 来自你的缓冲区检查 信息bytesAvailable。到了尽头 流不是特例 方式,IMO,所以我宁愿控制它 没有异常处理程序的情况, 但这只是个人的 偏好。