2010-07-24 105 views
4

作为一个小型实验性音乐作品,我试图用标准C编写一首歌曲。代码输出一个可导入Audacity的原始PCM文件。目前一切正常,但我在尝试将每个采样写入16位时遇到问题,而不是当前使用的8位。编写16位原始PCM文件时出现问题

直到被写入的点,当前样本计算为一个浮点数,并且其边界几乎保留在有符号的8位整数的范围内。然后在重复下一个采样的过程之前将其写为8位整数。这工作正常,并正常播放。当我尝试将它写入16位原始PCM文件时出现问题 - 我将浮点数乘以256,并将结果复制到整数,于是我使用fwrite写入所得的16位整数。这在导入时不会给出预期的结果,导致我期望的结果高度扭曲。

我已经添加了下面的有效代码,因为问题只发生在写作阶段。

工作的8位代码:

if (out<-127) {out=-128;} else if (out>126) {out=127;} 
putc(out,fo); 

不工作的16位代码:

if (out<-127) {out=-128;} else if (out>126) {out=127;} 
pcm=out*256; 
fwrite(&pcm,2,1,fo); 

我可能只是缺少明显的东西,但我一直在努力工作吧用了几个小时。提前致谢!

+0

是pcm an int16_t? – RWS 2010-07-24 14:41:52

+0

嗯...我认为8位WAV文件应该使用*无符号*样本。 – 2010-07-24 14:43:14

+0

你需要显示'pcm'的声明。 – caf 2010-07-25 03:59:40

回答

3

我会想象看看Audacity中的波形会给你一些线索。

你检查:

  • 字节顺序是正确的?
  • 你不应该使用例如无符号整数?
  • 您已正确将该文件标记为16位?

我不知道PCM的预期格式是什么,但这些都是可能的问题的候选人。

+0

如果他正在写一个原始的PCM文件,那么将不会有任何文件格式标题(所以你的第三点可能不是必需的)。在输入Audacity时,OP将不得不选择格式(如单声道/立体声,采样率,每个采样的位宽等)。 – stakx 2010-07-24 15:28:06

+0

导入时会选择位,有符号/无符号和字节顺序(尝试所有类型)。 – blkrbt 2010-07-24 16:06:43

+0

@blkrbt:你能够合成任意波形吗?你能产生一个完整的正弦波,看看Audacity中的波形,看看它是否被剪切/包裹/其他? – 2010-07-24 20:11:00

0

在转换时进行类型转换是一种很好的做法。例如,如果是浮点数,则

putc((int) out, fo); 

将让编译器知道你想要写你的电话号码为整数。

当然,编译器会找出类似于putc的东西,但这对于引用无效。如果你声明变量为float,那么fwrite将写入浮点数据而不是你想要的。所以我会问同样的问题:是pcm一个整数类型?

另一个问题是:你真的需要浮点吗?如果你可以使用小数精度,那么你可能会需要它(然后再输出8位或16位格式就会失去精度),但是如果你只对样本进行简单的数学计算,那就太浪费了。因此,你可以通过坚持一个整数类型来简化很多事情,并且在写入时将其转换为char/int8_t。

+0

pcm是一个整数。我也尝试使用它作为一个16位整数,如其他响应之一所示(同样的结果)。我确实需要使用浮点数来计算样本,直到写入它为止。 – blkrbt 2010-07-24 16:10:15

0

去的肢体在这里,但既然你要签署16位值,试试这个:

int16_t pcm = out * 256; 
fwrite(&pcm, sizeof(pcm), 1, fo); 

此外,还要确保你已经正确标记您的文件,即。原始PCM用适当的字节顺序签名16位。(编辑:这是不适用于PCM)

+0

这给出了与我上面发布的内容相同的结果。 – blkrbt 2010-07-24 16:12:00

0

僵尸这个线程:

从WAV维基:

有在WAV格式某些不一致:例如,8位数据是无符号的,而16位数据有签名

+1

请提供您正在引用的文章的链接。 – 2012-07-17 11:31:13

4

我不能确定你的代码有什么错误没有看到它,但这会让你在Audacity中打开一个不错的1 KHz正弦波16位PCM:

#include <stdio.h> 
#include <math.h> 

#ifndef M_PI 
#define M_PI 3.14159265358 
#endif 

int main(void) 
{ 
    FILE* f = fopen("sinewave.pcm", "wb"); 
    double t; 
    for (t = 0; t < 1; t += 1./8000) // 8000 is the sample rate in Hz 
    { 
    double sample = 15000 * sin(2 * M_PI * 1000 * t); // 1000 Hz sine wave 
    short s16 = (short)sample; 
    unsigned char c; 
    c = (unsigned)s16 % 256; 
    fwrite(&c, 1, 1, f); 
    c = (unsigned)s16/256 % 256; 
    fwrite(&c, 1, 1, f); 
    } 
    fclose(f); 
    return 0; 
} 

在Audacity的导航通过文件 - >导入 - >原始数据:

编码:符号16位PCM
字节顺序:小端
频道:1个通道(单声道)
采样率:8000

导入。