2016-05-11 148 views
0

我正在製作一個小程序來讀取&用C語言編寫32位wav文件。讀寫32bit wav文件C

但是,我遇到了問題。

編譯後,有時程序運作良好,但有時,它不工作...這樣的:

  • 輸出wav文件是空
  • 輸出wav文件(1秒)過大,大於5GB ...

我真的在這裏堆疊... 任何人都知道一個解決方案?

下面是我的程序

↓↓wave32.h

typedef struct 
{ 
    int fs; 
    int bits; 
    int length; 
    double *s; 
} MONO_PCM; 

void wave_read_32bit_mono(MONO_PCM *pcm, char *file_name) 
{ 
    FILE *fp; 
    char riff_chunk_ID[4]; 
    long riff_chunk_size; 
    char file_format_type[4]; 
    char fmt_chunk_ID[4]; 
    long fmt_chunk_size; 
    short wave_format_type; 
    short channel; 
    long samples_per_sec; 
    long bytes_per_sec; 
    short block_size; 
    short bits_per_sample; 
    char data_chunk_ID[4]; 
    long data_chunk_size; 
    int data; 
    int n; 

    fp = fopen(file_name, "rb"); 

    fread(riff_chunk_ID, 1, 4, fp); 
    fread(&riff_chunk_size, 4, 1, fp); 
    fread(file_format_type, 1, 4, fp); 
    fread(fmt_chunk_ID, 1, 4, fp); 
    fread(&fmt_chunk_size, 4, 1, fp); 
    fread(&wave_format_type, 2, 1, fp); 
    fread(&channel, 2, 1, fp); 
    fread(&samples_per_sec, 4, 1, fp); 
    fread(&bytes_per_sec, 4, 1, fp); 
    fread(&block_size, 2, 1, fp); 
    fread(&bits_per_sample, 2, 1, fp); 
    fread(data_chunk_ID, 1, 4, fp); 
    fread(&data_chunk_size, 4, 1, fp); 


    pcm->fs = samples_per_sec; 
    pcm->bits = bits_per_sample; 
    pcm->length = data_chunk_size/4; 
    pcm->s = calloc(pcm->length, sizeof(double)); 

    for (n = 0; n < pcm->length; n++) 
    { 
    fread(&data, 4, 1, fp); 
    pcm->s[n] = ((double)data/2147483648.0) ; 
    } 

    fclose(fp); 
} 
void wave_write_32bit_mono(MONO_PCM *pcm, char *file_name) 
{ 
    FILE *fp; 
    char riff_chunk_ID[4]; 
    long riff_chunk_size; 
    char file_format_type[4]; 
    char fmt_chunk_ID[4]; 
    long fmt_chunk_size; 
    short wave_format_type; 
    short channel; 
    long samples_per_sec; 
    long bytes_per_sec; 
    short block_size; 
    short bits_per_sample; 
    char data_chunk_ID[4]; 
    long data_chunk_size; 
    double s; 
    int data; 
    int n; 

    riff_chunk_ID[0] = 'R'; 
    riff_chunk_ID[1] = 'I'; 
    riff_chunk_ID[2] = 'F'; 
    riff_chunk_ID[3] = 'F'; 
    riff_chunk_size = 36 + pcm->length * 2; 
    file_format_type[0] = 'W'; 
    file_format_type[1] = 'A'; 
    file_format_type[2] = 'V'; 
    file_format_type[3] = 'E'; 

    fmt_chunk_ID[0] = 'f'; 
    fmt_chunk_ID[1] = 'm'; 
    fmt_chunk_ID[2] = 't'; 
    fmt_chunk_ID[3] = ' '; 
    fmt_chunk_size = 16; 
    wave_format_type = 1; 
    channel = 1; 
    samples_per_sec = pcm->fs; 
    bytes_per_sec = pcm->fs * pcm->bits/8; 
    block_size = pcm->bits/8; 
    bits_per_sample = pcm->bits; 

    data_chunk_ID[0] = 'd'; 
    data_chunk_ID[1] = 'a'; 
    data_chunk_ID[2] = 't'; 
    data_chunk_ID[3] = 'a'; 
    data_chunk_size = pcm->length * 4; 

    fp = fopen(file_name, "wb"); 

    fwrite(riff_chunk_ID, 1, 4, fp); 
    fwrite(&riff_chunk_size, 4, 1, fp); 
    fwrite(file_format_type, 1, 4, fp); 
    fwrite(fmt_chunk_ID, 1, 4, fp); 
    fwrite(&fmt_chunk_size, 4, 1, fp); 
    fwrite(&wave_format_type, 2, 1, fp); 
    fwrite(&channel, 2, 1, fp); 
    fwrite(&samples_per_sec, 4, 1, fp); 
    fwrite(&bytes_per_sec, 4, 1, fp); 
    fwrite(&block_size, 2, 1, fp); 
    fwrite(&bits_per_sample, 2, 1, fp); 
    fwrite(data_chunk_ID, 1, 4, fp); 
    fwrite(&data_chunk_size, 4, 1, fp); 

    for (n = 0; n < pcm->length; n++) 
    { 
    s = (pcm->s[n]) * 2147483648.0; 


    if (s > 2147483647.0) 
    { 
     s = 2147483647.0; 
    } 
    else if (s < -2147483647.0) 
    { 
     s = -2147483647.0; 
    } 

    data = (int)(s + 0.5); 
    fwrite(&data, 4, 1, fp); 
    } 

    fclose(fp); 
} 

↓↓wave32.c

#include <stdio.h> 
#include <stdlib.h> 
#include <stdint.h> 
#include <math.h> 
#include "wave32.h" 

int main(void) 
{ 
    MONO_PCM pcm0, pcm1; 
    int n; 

    wave_read_32bit_mono(&pcm0, "sine32.wav"); // 1 sec sine wave 

    pcm1.fs = pcm0.fs; 
    pcm1.bits = pcm0.bits; 
    pcm1.length = pcm0.length; 
    pcm1.s = calloc(pcm1.length, sizeof(double)); 

    for (n = 0; n < pcm1.length; n++) 
    { 

    pcm1.s[n] = pcm0.s[n]; 

    } 

    wave_write_32bit_mono(&pcm1, "b.wav"); 

    free(pcm0.s); 
    free(pcm1.s); 

    return 0; 
} 
+1

爲什麼在h文件中有函數定義?你的程序設計很混亂。 – Lundin

+1

我會檢查整數類型的字節順序和大小。您應該切換到固定大小的整數,而不是依賴具有特定大小的'short' /'int' /'long'。 –

+2

我不知道你的平臺,但可能你所有的'long'變量都必須是'int'。最好的東西是'#include '並使用它的類型:'uint32_t','uint16_t'等 – LPs

回答

0

我猜你的平臺有長有大小8個字節。

你可以簡單地檢查一下:

printf("Long= %zu bytes - int= %zu bytes\n", sizeof(long), sizeof(int)); 

然後,當你使用,e.g

fread(&riff_chunk_size, 4, 1, fp); 

你被錯誤讀取值,由於大小端。

交換機所有long類型int或最好加

#include <stdint.h> 

,改變你的變量類型:

  • long - >int32_t
  • int - >int32_t
  • short - >int16_t
+1

你的答案是完美的。我的程序開始運作良好。 我真的很羨慕。謝謝! – ya90net