2016-05-11 3 views
0

Я делаю небольшую программу для чтения & пишу 32-битный wav-файл на языке C.Чтение и запись 32-битного wav-файла в C

Но у меня проблема.

После компиляции Иногда программа работает хорошо, но иногда это не работает ... как:

  • выходной файл WAV пуст
  • выходной файл WAV (1 сек) слишком большой , более 5 ГБ ...

Я действительно собираю здесь ... Кто-нибудь знает решение ???

Ниже моя программа

↓ ↓ 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)); 

Затем, когда вы используете, например

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

Вы неправильно считыванием значения, из-за байтов.

Переключить все длинные типы в int или лучше добавить

#include <stdint.h> 

и изменить типы переменных в:

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

Ваш ответ прекрасен. Моя программа начала работать хорошо. Я действительно высоко ценю. Благодаря! – ya90net