我希望将ADPCM数据转换为XNA的.xnb文件中的PCM数据。 (这么多缩写!)
我使用了几个地方作为参考,包括: http://www.wooji-juice.com/blog/iphone-openal-ima4-adpcm.html http://www.cs.columbia.edu/~hgs/audio/dvi/p34.jpg和其他几个人。
我相信我很接近,因为我听到的声音有些相似,但输出声音中存在很多静电/损坏,我似乎无法弄清楚原因。
转换归结为两个功能。
private static byte[] convert(byte[] data)
{
byte[] convertedData = new byte[(data.Length) * 4];
stepSize = 7;
newSample = 0;
index = 0;
var writeCounter = 0;
for (var x = 4; x < data.Length; x++)
{
// First 4 bytes of a block contain initialization information
if ((x % blockSize) < 4)
{
if (x % blockSize == 0) // New block
{
// set predictor/NewSample and index from
// the preamble of the block.
newSample = (short)(data[x + 1] | data[x]);
index = data[x + 2];
}
continue;
}
// Get the first 4 bits from the byte array,
var convertedSample = calculateNewSample((byte)(data[x] >> 4)); // convert 4 bit ADPCM sample to 16 bit PCM sample
// Store 16 bit PCM sample into output byte array
convertedData[writeCounter++] = (byte)convertedSample >> 8;
convertedData[writeCounter++] = (byte)convertedSample & 0x0ff;;
// Convert the next 4 bits of the 8 bit array.
convertedSample = calculateNewSample((byte)(data[x] & 0x0f)); // convert 4 bit ADPCM sample to 16 bit PCM sample.
// Store 16 bit PCM sample into output byte array
convertedData[writeCounter++] = (byte)(convertedSample >> 8);
convertedData[writeCounter++] = (byte)(convertedSample & 0x0ff);
}
// Conversion complete, return data
return convertedData;
}
private static short calculateNewSample(byte sample)
{
Debug.Assert(sample < 16, "Bad sample!");
var indexTable = new int[16] { -1, -1, -1, -1, 2, 4, 6, 8, -1, -1, -1, -1, 2, 4, 6, 8 };
var stepSizeTable = new int[89] { 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767};
var sign = sample & 8;
var delta = sample & 7;
var difference = stepSize >> 3;
// originalsample + 0.5 * stepSize / 4 + stepSize / 8 optimization.
//http://www.cs.columbia.edu/~hgs/audio/dvi/p34.jpg
if ((delta & 4) != 0)
difference += stepSize;
if ((delta & 2) != 0)
difference += stepSize >> 1;
if ((delta & 1) != 0)
difference += stepSize >> 2;
if (sign != 0)
newSample -= (short)difference;
else
newSample += (short)difference;
// Increment index
index += indexTable[sample];
index = (int)MathHelper.Clamp(index, 0, 88);
newSample = (short)MathHelper.Clamp(newSample, -32768, 32767); // clamp between appropriate ranges
// compute new stepSize.
stepSize = stepSizeTable[index];
return newSample;
}
我不相信实际的calculateNewSample()函数是不正确的,因为我已经传递了来自http://www.cs.columbia.edu/~hgs/audio/dvi/p35.jpg的输入值,并收到了相同的输出。我已经尝试在高/低位字节之间翻转,看看我是否已经倒退也无济于事。我觉得可能有一些基本的东西,我错过了,但我很难找到它。
任何帮助都会受到重视。