降低pcm音量后产生奇怪的噪音

strange noise after reduce volume on a pcm

本文关键字:噪音 pcm 降低      更新时间:2023-10-16

有人知道为什么我在c++中应用这个算法来降低pcm的音量后,背景中会出现白噪声吗?

for(int i = 0; i<pcm.length(); i+=2) {
   quint16 byte0 = pcm[i];
   quint16 byte1 = pcm[i+1];
   //merge byte0 and byte1
   qint16 n = (byte1 << 8) + byte0;
   n *= volume; // multiplier;
   //split n into byte0 and byte1
   byte1   = (n >> 8) & 255;
   byte0    = n & 255;
   //save the new values
   pcm[i] = byte0;
   pcm[i+1] = byte1;
}

过了很长时间,我找到了解决方案。问题是我把两个片段融合在一起的模式。

 for(int i = 0; i<pcm.length(); i+=2) {
   quint16 byte0 = pcm[i];
   quint16 byte1 = pcm[i+1];
   //merge byte0 and byte1
   qint16 n = 0;
   n |= speakersRaw[j][i+1] & 0xFF;
   n <<= 8;
   n |= speakersRaw[j][i] & 0xFF;
   n *= volume; // multiplier;
   //split n into byte0 and byte1
   byte1   = (n >> 8) & 255;
   byte0    = n & 255;
   //save the new values
   pcm[i] = byte0;
   pcm[i+1] = byte1;
}

您的n *= 0.5实际上和n >>= 1做得一样。您正在将byte1的最低有效位转换为byte0的最高有效位,这可能是您的噪声源。

为什么要将这两个值合并为一个整数,而不是分别处理?

也许您的字节打包和拆包顺序不对?

qint16 n = (byte0 << 8) + byte1;
byte0   = (n >> 8) & 255;
byte1   = n & 255;  

Mark Ransom提到的字节顺序是一个明显的可能问题。你应该检查一下。

另一个可能的问题是符号扩展。

如果您有带符号的样本,并且您正在以无符号类型操作它们,那么您将丢失所有负样本的符号位。

如果你的字节类型是有符号的,那么当你加载字节0和字节1时,你会得到高字节的符号扩展,同样不是你想要的。

quint16类型与样品的实际类型匹配吗?如果没有,则应使用相同的类型。您应该让用户使用unsigned char作为字节类型。

根据评论中的信息更新:

要测试符号扩展理论,请更改:

n *= 0.5;

线路至:

n = ((short) n) * 0.5;