将 16 位立体声转换为 16 位单声道声音
Posted
技术标签:
【中文标题】将 16 位立体声转换为 16 位单声道声音【英文标题】:Convert 16 bit stereo sound to 16 bit mono sound 【发布时间】:2014-05-06 21:31:51 【问题描述】:我正在尝试将 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 );
【问题讨论】:
【参考方案1】:在 16 位立体声 WAV 文件中,每个样本为 16 位,并且样本是交错的。我不确定您为什么使用按位 OR,但您可以直接检索数据而无需移位。下面的不可移植代码(假设 sizeof(short) == 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 在下面的 cmets 中所指出的,简单的平均可能不会给出最好的结果。您的里程可能会有所不同。
此外,Greg Hewgill 正确地指出,这是假设机器是 little-endian 的。
【讨论】:
应该是i += 4
不是吗?否则,您的左通道将只是您的右通道是最后一次迭代。
为什么要除以 2?这会将原始信号降低 3 dB。
哦,你修好了哈哈
它除以二,因为它是两个样本的平均值。
根据数据准确性的要求,您可能不希望对信号进行平均。例如,如果左声道有 50 dB 200 Hz 音调,右声道有 50 dB 600 Hz 音调,则单声道流中将有两个 47 dB 音调。在我看来,最好将它们简单地加在一起,因为这会导致原始信号的复制,只是缺少方向信息。以上是关于将 16 位立体声转换为 16 位单声道声音的主要内容,如果未能解决你的问题,请参考以下文章