2010-07-24 44 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

導入。