C语言读写32位wav文件
Read and write 32bit wav file in C
我正在用 C 语言制作一个读写 32 位 wav 文件的小程序。
但是,我遇到了一个问题。
编译后,有时程序运行良好,但有时却无法运行......如:
- 输出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;
}
我猜你的平台有 8 个字节的 long。
您可以简单地检查它:
printf("Long= %zu bytes - int= %zu bytes\n", sizeof(long), sizeof(int));
那么当你使用时,例如
fread(&riff_chunk_size, 4, 1, fp);
由于字节顺序,您错误地读取了该值。
将所有 long 类型切换为 int
或更好的添加
#include <stdint.h>
并将您的变量类型更改为:
long
-> int32_t
int
-> int32_t
short
-> int16_t
我正在用 C 语言制作一个读写 32 位 wav 文件的小程序。
但是,我遇到了一个问题。
编译后,有时程序运行良好,但有时却无法运行......如:
- 输出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;
}
我猜你的平台有 8 个字节的 long。
您可以简单地检查它:
printf("Long= %zu bytes - int= %zu bytes\n", sizeof(long), sizeof(int));
那么当你使用时,例如
fread(&riff_chunk_size, 4, 1, fp);
由于字节顺序,您错误地读取了该值。
将所有 long 类型切换为 int
或更好的添加
#include <stdint.h>
并将您的变量类型更改为:
long
->int32_t
int
->int32_t
short
->int16_t