我正在尝试在 AS3 中将 8000hz、16 位 wav 文件上采样到 11025hz。在这一点上,我并不关心应用我知道我最终需要的低通滤波器。
我一直在参考这个 wiki 页面。
这是我到目前为止所做的:
- 计算出最小公倍数为 3528000
- 计算 L 为 441
- 计算 M 为 320
- 在样本之间添加了 440 个零
- 每 320 个样本写入一个新的字节数组
但是,当我去播放新的 wav 时,它是无法区分的噪音。这是我的代码:
const sourceRate:uint = 8000;
const targetRate:uint = 11025;
var lcm:uint = lcm(targetRate, sourceRate); // = 3528000
var l:uint = lcm / sourceRate; // = 441
var m:uint = lcm / targetRate; // = 320
// upsample by factor of l
var upsampleData:ByteArray = new ByteArray();
upsampleData.endian = Endian.LITTLE_ENDIAN;
// originalWavData is a ByteArray of the source wav data
// fill is a ByteArray that contains 440 zeroes, written using writeShort(0x0)
while(originalWavData.bytesAvailable > 1) {
upsampleData.writeBytes(fill);
upsampleData.writeShort(originalWavData.readShort());
}
// downsample by factor of m
var downsampleData:ByteArray = new ByteArray();
downsampleData.endian = Endian.LITTLE_ENDIAN;
upsampleData.position = 0;
for(var k:uint=0; k<upsampleData.length; k++) {
upsampleData.position = k * m;
if(upsampleData.bytesAvailable < 2) break;
downsampleData.writeShort(upsampleData.readShort());
}
谁能告诉我我在代码中做错了什么?这是我的第一个问题帖子,所以如果我忘记了什么,或者需要提供更多信息,请告诉我。
谢谢!
更新:
我简化了 Aric 的答案,现在使用以下代码成功地进行了上采样:
/**
* Generates a ByteArray containing numSamples of
* data using linear interpolation between points
* y0 and y1.
*/
function interpolate(y0:int, y1:int, numSamples:uint):ByteArray {
var b:ByteArray = new ByteArray();
b.endian = Endian.LITTLE_ENDIAN;
var m:Number = Math.round((y1-y0)/numSamples);
for(var i:uint=0; i<numSamples; i++) {
var n:int = m * i + y0;
b.writeShort(n);
}
b.position = 0;
return 0;
}
// upsample by factor of l
var n1:int = 0;
while(originalWavData.bytesAvailable > 1) {
var sample:int = originalWavData.readShort();
upsampleData.writeBytes(interpolate(n1, sample, (l-1)));
n1 = sample;
}
// downsample by factor of m
while(upsampleData.bytesAvailable > 1) {
downsampleData.writeShort(upsampleData.readShort());
upsampleData.position += ((m-1)*2);
}
关于此解决方案需要注意的几点:我正在对音频验证码进行上采样,因此音质并不是非常重要。此外,第一个样本只是静音,所以我不需要计算第一个样本左侧的值。这就是为什么 n1 最初等于 0 的原因。此外,我没有在我的下采样中对生成的样本进行平均,而是抓住了每个 Mth 样本,这听起来对我的目的来说很好。
我确信有 1000 种更好的方法可以做到这一点,但对于我所需要的,它是有效的。再次感谢 Aric 的回答。