我正在尝试将16位立体声声音从WAVE文件转换为16位单声道声音,但我有些困难。我试图将8位立体声转换为单声道,它的工作效果很好。这是代码:
if( bitsPerSample == 8 )
{
dataSize /= 2;
openALFormat = AL_FORMAT_MONO8;
for( SizeType i = 0; i < dataSize; i++ )
{
pData[ i ] = static_cast<Uint8>(
( static_cast<Uint16>( pData[ i * 2 ] ) +
static_cast<Uint16>( pData[ i * 2 + 1 ] ) ) / 2
);
}
但是,现在我尝试使用16位音频做同样的事情,但我无法让它工作。我只能听到某种奇怪的声音。我试图将“monoSample”设置为“left”(Uint16 monoSample = left;),来自该频道的音频数据效果非常好。正确的渠道。谁能看到我做错了什么? 这是代码(pData是一个字节数组):
if( bitsPerSample == 16 )
{
dataSize /= 2;
openALFormat = AL_FORMAT_MONO16;
for( SizeType i = 0; i < dataSize / 2; i++ )
{
Uint16 left = static_cast<Uint16>( pData[ i * 4 ] ) |
( static_cast<Uint16>( pData[ i * 4 + 1 ] ) << 8 );
Uint16 right = static_cast<Uint16>( pData[ i * 4 + 2 ] ) |
( static_cast<Uint16>( pData[ i * 4 + 3 ] ) << 8 );
Uint16 monoSample = static_cast<Uint16>(
( static_cast<Uint32>( left ) +
static_cast<Uint32>( right ) ) / 2
);
// Set the new mono sample.
pData[ i * 2 ] = static_cast<Uint8>( monoSample );
pData[ i * 2 + 1 ] = static_cast<Uint8>( monoSample >> 8 );
}
}
答案 0 :(得分:7)
在16位立体声WAV文件中,每个样本为16位,并且样本是交错的。我不确定您为什么要使用按位OR,但您可以直接检索数据而无需移位。下面的非可移植代码(假设sizeof(短)== 2)说明了这一点。
unsigned size = header.data_size;
char *data = new char[size];
// Read the contents of the WAV file in to data
for (unsigned i = 0; i < size; i += 4)
{
short left = *(short *)&data[i];
short right = *(short *)&data[i + 2];
short monoSample = (int(left) + right) / 2;
}
此外,虽然8位WAV文件是无符号的,但16位WAV文件已签名。要对它们进行平均,请确保将其存储在适当大小的签名类型中。请注意,其中一个样本会暂时提升为int以防止溢出。
正如Stix在下面的评论中指出的那样,简单平均可能无法获得最佳结果。您的里程可能会有所不同。
此外,Greg Hewgill正确地指出,这假设机器是小端的。