24位音频处理

时间:2011-07-15 12:22:17

标签: c++ c

我编写了一些代码,根据位深度从音频缓冲区读取数据,处理它并将其写回相同的缓冲区。我必须处理16和24位深度。 16位代码工作正常但24位代码却没有。

以下是我为24位数据的每个样本所做的事情:

int data = 0;

//read data from buffer
RtlCopyMemory (&data, ((char*)Source) + head, 3);

//scale data for integer

data = data << 8;

//data processing

data = data * m_CurOutVolLevel;

//scaling down the data
data = (data >> 8);

RtlCopyMemory (((char*)Source) + head, &data, 3);

但输出不正确。有人能指出这里有什么问题吗?

由于

感谢您的建议。我实现了你们的建议,但仍有一些缺陷:

unsigned __int64 newData;
unsigned char* s = ((unsigned char*)Source) + head;
unsigned int data = ((unsigned int)s[0] << 8) | ((unsigned int)s[1] << 16) |((unsigned int)s[2] << 24);

// data processing
newData = (unsigned __int64)(data * m_pMiniport->m_CurOutVolLevel);
//divide this by 2 to the power 16
newData = (newData >> 16); 

// store back
s[0] = (unsigned char)((newData >> 32)  & 0xff);
s[1] = (unsigned char)((newData >> 40) & 0xff);
s[2] = (unsigned char)((newData >> 48) & 0xff);

有人看到上述代码有问题吗?

谢谢,安妮

4 个答案:

答案 0 :(得分:1)

好吧,你使用int,如果是在32位机器上,这通常是32位。如果数据是24位,则移位将意味着您甚至可以使用最高位。这导致两件事:

  • 移位时第一个可能的重载,因为你的int是有符号的,如果位“24”(数据中的最高位)是1,结果中的位32将是1并且它将变为负数号。

  • 乘法的第二个可能的溢出,假设上面没有发生,你现在很可能会过度增加32位数的边界。假设第23位置位,所以你的数字保持正确,如果m_curOutVolLevel甚至只低至2,这等于exta位移,再次你溢出。更有可能你甚至会丢失比特,因为这个数字不能再存储在32位中。

修改:可能的解决方案,如果这是问题:使用uint64_t中的stdint.h

编辑 2 :另请注意,您的代码可能会出现endianness的问题,因为您只需将int编码为字节流(除非RtlCopyMemory处理此问题,我怀疑)。

答案 1 :(得分:0)

您无法修改int的部分内容,只希望代码可以使用(更不用说是可移植的了)。

假设数据以无符号的小端顺序存储,您可以像这样访问它:

unsigned char* s = ((unsigned char*)Source) + head;
uint32_t data = ((uint32_t)s[0] << 8) | ((uint32_t)s[1] << 16) | ((uint32_t)s[2] << 24);
// use data
// store back
s[0] = (unsigned char)((data >> 8) & 0xff);
s[1] = (unsigned char)((data >> 16) & 0xff);
s[2] = (unsigned char)((data >> 24) & 0xff);

但这取决于数据的存储方式。

答案 2 :(得分:0)

你需要对endianness issues这样的代码非常小心,将字节复制到一个多字节的单个变量是不安全的。

最好一次读取一个字节,这样您就可以以字节顺序的方式表达您期望每个字节着陆的值。当然,这需要您考虑数据中多字节24位值的字节顺序。

答案 3 :(得分:0)

概括@ user786653以获得多个位深度。

uint32_t sample = 0;
for (int i = 0; i < bit_depth / 8; i++) {
    sample = ((uint32_t)source[i] << (i * 8)) | sample;
}