我正在尝试从波形文件数据库中读取音频波形文件。我读取波形文件的代码看起来像这样
/**
* Read and parse a wave file
*
**/
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "wave.h"
#define TRUE 1
#define FALSE 0
// WAVE header structure
unsigned char buffer4[4];
unsigned char buffer2[2];
char* seconds_to_time(float seconds);
FILE *ptr;
char *filename;
struct HEADER header;
int main(int argc, char **argv) {
filename = (char*) malloc(sizeof(char) * 1024);
if (filename == NULL) {
printf("Error in malloc\n");
exit(1);
}
// get file path
char cwd[1024];
if (getcwd(cwd, sizeof(cwd)) != NULL) {
strcpy(filename, cwd);
// get filename from command line
if (argc < 2) {
printf("No wave file specified\n");
return;
}
strcat(filename, "/");
strcat(filename, argv[1]);
printf("%s\n", filename);
}
// open file
printf("Opening file..\n");
ptr = fopen(filename, "rb");
if (ptr == NULL) {
printf("Error opening file\n");
exit(1);
}
int read = 0;
// read header parts
read = fread(header.riff, sizeof(header.riff), 1, ptr);
printf("(1-4): %s \n", header.riff);
read = fread(buffer4, sizeof(buffer4), 1, ptr);
printf("%u %u %u %u\n", buffer4[0], buffer4[1], buffer4[2], buffer4[3]);
// convert little endian to big endian 4 byte int
header.overall_size = buffer4[0] |
(buffer4[1]<<8) |
(buffer4[2]<<16) |
(buffer4[3]<<24);
printf("(5-8) Overall size: bytes:%u, Kb:%u \n", header.overall_size, header.overall_size/1024);
read = fread(header.wave, sizeof(header.wave), 1, ptr);
printf("(9-12) Wave marker: %s\n", header.wave);
read = fread(header.fmt_chunk_marker, sizeof(header.fmt_chunk_marker), 1, ptr);
printf("(13-16) Fmt marker: %s\n", header.fmt_chunk_marker);
read = fread(buffer4, sizeof(buffer4), 1, ptr);
printf("%u %u %u %u\n", buffer4[0], buffer4[1], buffer4[2], buffer4[3]);
// convert little endian to big endian 4 byte integer
header.length_of_fmt = buffer4[0] |
(buffer4[1] << 8) |
(buffer4[2] << 16) |
(buffer4[3] << 24);
printf("(17-20) Length of Fmt header: %u \n", header.length_of_fmt);
read = fread(buffer2, sizeof(buffer2), 1, ptr); printf("%u %u \n", buffer2[0], buffer2[1]);
header.format_type = buffer2[0] | (buffer2[1] << 8);
char format_name[10] = "";
if (header.format_type == 1)
strcpy(format_name,"PCM");
else if (header.format_type == 6)
strcpy(format_name, "A-law");
else if (header.format_type == 7)
strcpy(format_name, "Mu-law");
printf("(21-22) Format type: %u %s \n", header.format_type, format_name);
read = fread(buffer2, sizeof(buffer2), 1, ptr);
printf("%u %u \n", buffer2[0], buffer2[1]);
header.channels = buffer2[0] | (buffer2[1] << 8);
printf("(23-24) Channels: %u \n", header.channels);
read = fread(buffer4, sizeof(buffer4), 1, ptr);
printf("%u %u %u %u\n", buffer4[0], buffer4[1], buffer4[2], buffer4[3]);
header.sample_rate = buffer4[0] |
(buffer4[1] << 8) |
(buffer4[2] << 16) |
(buffer4[3] << 24);
printf("(25-28) Sample rate: %u\n", header.sample_rate);
read = fread(buffer4, sizeof(buffer4), 1, ptr);
printf("%u %u %u %u\n", buffer4[0], buffer4[1], buffer4[2], buffer4[3]);
header.byterate = buffer4[0] |
(buffer4[1] << 8) |
(buffer4[2] << 16) |
(buffer4[3] << 24);
printf("(29-32) Byte Rate: %u , Bit Rate:%u\n", header.byterate, header.byterate*8);
read = fread(buffer2, sizeof(buffer2), 1, ptr);
printf("%u %u \n", buffer2[0], buffer2[1]);
header.block_align = buffer2[0] |
(buffer2[1] << 8);
printf("(33-34) Block Alignment: %u \n", header.block_align);
read = fread(buffer2, sizeof(buffer2), 1, ptr);
printf("%u %u \n", buffer2[0], buffer2[1]);
header.bits_per_sample = buffer2[0] |
(buffer2[1] << 8);
printf("(35-36) Bits per sample: %u \n", header.bits_per_sample);
read = fread(header.data_chunk_header, sizeof(header.data_chunk_header), 1, ptr);
printf("(37-40) Data Marker: %s \n", header.data_chunk_header);
read = fread(buffer4, sizeof(buffer4), 1, ptr);
printf("%u %u %u %u\n", buffer4[0], buffer4[1], buffer4[2], buffer4[3]);
header.data_size = buffer4[0] |
(buffer4[1] << 8) |
(buffer4[2] << 16) |
(buffer4[3] << 24 );
printf("(41-44) Size of data chunk: %u \n", header.data_size);
// calculate no.of samples
long num_samples = (8 * header.data_size) / (header.channels * header.bits_per_sample);
printf("Number of samples:%lu \n", num_samples);
long size_of_each_sample = (header.channels * header.bits_per_sample) / 8;
printf("Size of each sample:%ld bytes\n", size_of_each_sample);
// calculate duration of file
float duration_in_seconds = (float) header.overall_size / header.byterate;
printf("Approx.Duration in seconds=%f\n", duration_in_seconds);
printf("Approx.Duration in h:m:s=%s\n", seconds_to_time(duration_in_seconds));
// read each sample from data chunk if PCM
if (header.format_type == 1) { // PCM
printf("Dump sample data? Y/N?");
char c = 'n';
scanf("%c", &c);
if (c == 'Y' || c == 'y') {
long i =0;
char data_buffer[size_of_each_sample];
int size_is_correct = TRUE;
// make sure that the bytes-per-sample is completely divisible by num.of channels
long bytes_in_each_channel = (size_of_each_sample / header.channels);
if ((bytes_in_each_channel * header.channels) != size_of_each_sample) {
printf("Error: %ld x %ud <> %ld\n", bytes_in_each_channel, header.channels, size_of_each_sample);
size_is_correct = FALSE;
}
if (size_is_correct) {
// the valid amplitude range for values based on the bits per sample
long low_limit = 0l;
long high_limit = 0l;
switch (header.bits_per_sample) {
case 8:
low_limit = -128;
high_limit = 127;
break;
case 16:
low_limit = -32768;
high_limit = 32767;
break;
case 32:
low_limit = -2147483648;
high_limit = 2147483647;
break;
}
printf("\n\n.Valid range for data values : %ld to %ld \n", low_limit, high_limit);
for (i =1; i <= num_samples; i++) {
printf("==========Sample %ld / %ld=============\n", i, num_samples);
read = fread(data_buffer, sizeof(data_buffer), 1, ptr);
if (read == 1) {
// dump the data read
unsigned int xchannels = 0;
int data_in_channel = 0;
for (xchannels = 0; xchannels < header.channels; xchannels ++ ) {
printf("Channel#%d : ", (xchannels+1));
// convert data from little endian to big endian based on bytes in each channel sample
if (bytes_in_each_channel == 4) {
data_in_channel = data_buffer[0] |
(data_buffer[1]<<8) |
(data_buffer[2]<<16) |
(data_buffer[3]<<24);
}
else if (bytes_in_each_channel == 2) {
data_in_channel = data_buffer[0] |
(data_buffer[1] << 8);
}
else if (bytes_in_each_channel == 1) {
data_in_channel = data_buffer[0];
}
printf("%d ", data_in_channel);
// check if value was in range
if (data_in_channel < low_limit || data_in_channel > high_limit)
printf("**value out of range\n");
printf(" | ");
}
printf("\n");
}
else {
printf("Error reading file. %d bytes\n", read);
break;
}
} // for (i =1; i <= num_samples; i++) {
} // if (size_is_correct) {
} // if (c == 'Y' || c == 'y') {
} // if (header.format_type == 1) {
printf("Closing file..\n");
fclose(ptr);
// cleanup before quitting
free(filename);
return 0;
}
/**
* Convert seconds into hh:mm:ss format
* Params:
* seconds - seconds value
* Returns: hms - formatted string
**/
char* seconds_to_time(float raw_seconds) {
char *hms;
int hours, hours_residue, minutes, seconds, milliseconds;
hms = (char*) malloc(100);
sprintf(hms, "%f", raw_seconds);
hours = (int) raw_seconds/3600;
hours_residue = (int) raw_seconds % 3600;
minutes = hours_residue/60;
seconds = hours_residue % 60;
milliseconds = 0;
// get the decimal part of raw_seconds to get milliseconds
char *pos;
pos = strchr(hms, '.');
int ipos = (int) (pos - hms);
char decimalpart[15];
memset(decimalpart, ' ', sizeof(decimalpart));
strncpy(decimalpart, &hms[ipos+1], 3);
milliseconds = atoi(decimalpart);
sprintf(hms, "%d:%d:%d.%d", hours, minutes, seconds, milliseconds);
return hms;
}
包含的wave.h看起来像这样
// WAVE file header format
struct HEADER {
unsigned char riff[4]; // RIFF string
unsigned int overall_size ; // overall size of file in bytes
unsigned char wave[4]; // WAVE string
unsigned char fmt_chunk_marker[4]; // fmt string with trailing null char
unsigned int length_of_fmt; // length of the format data
unsigned int format_type; // format type. 1-PCM, 3- IEEE float, 6 - 8bit A law, 7 - 8bit mu law
unsigned int channels; // no.of channels
unsigned int sample_rate; // sampling rate (blocks per second)
unsigned int byterate; // SampleRate * NumChannels * BitsPerSample/8
unsigned int block_align; // NumChannels * BitsPerSample/8
unsigned int bits_per_sample; // bits per sample, 8- 8bits, 16- 16 bits etc
unsigned char data_chunk_header [4]; // DATA string or FLLR string
unsigned int data_size; // NumSamples * NumChannels * BitsPerSample/8 - size of the next chunk that will be read
};
。我尝试过其他wav文件,似乎得到了正确的输出(即标题中的“RIFF”和“WAVE”)。但是,我关心的是输出
________________________________________________________________________________~/Downloads/libmfcc-master $: ./a.out audioclip-1523814201.wav
/home/sfelde2/Downloads/libmfcc-master/audioclip-1523814201.wav
Opening file..
(1-4):
102 116 121 112
(5-8) Overall size: bytes:1887007846, Kb:1842781
(9-12) Wave marker: isom
(13-16) Fmt marker:
105 115 111 109
(17-20) Length of Fmt header: 1836020585
105 115
(21-22) Format type: 29545
111 50
(23-24) Channels: 12911
109 112 52 49
(25-28) Sample rate: 825520237
0 0 0 8
(29-32) Byte Rate: 134217728 , Bit Rate:1073741824
102 114
(33-34) Block Alignment: 29286
101 101
(35-36) Bits per sample: 25957
(37-40) Data Marker:
109 100 97 116
(41-44) Size of data chunk: 1952539757
Number of samples:8
Size of each sample:41891353 bytes
Approx.Duration in seconds=14.059304
Approx.Duration in h:m:s=0:0:14.59
Closing file..
我开始怀疑它所说的“isom”的波场是否表示它的对齐方式不同,但我无法在ISOM上找到任何东西。这是因为它没有打印RIFF字符串并且为数据吐出错误的值,这让我想知道无论如何我都能找出数据的起始位置。关于可能是什么问题的任何想法,或者无论如何我都可以调试这个以便我可以使用wav文件将非常感激。
答案 0 :(得分:0)
对于遇到此问题的任何人,我意识到数据是在我的计算机上自动下载后转换的。下载文件时,由于某种原因我们不知道这些文件被转换为.png文件。为了避免这种情况,如果你遇到同样的问题,请确保检查输入文件的类型,即使它以.wav结尾结束。