我想用C ++读取音频(.wav)文件。
到目前为止,我已经阅读了wav文件的标题。如何循环进入wav文件的数据部分,将其转换为-1和1,然后将其写入txt文件。
我已经完成了以下操作,但是当我使用MATLAB绘制生成的txt文件时,信号似乎失真了。
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <fstream>
using namespace std;
//double byteToDouble( char firstByte, char secondByte );
// WAVE PCM soundfile format (you can find more in https://ccrma.stanford.edu/courses/422/projects/WaveFormat/ )
typedef struct header_file
{
char chunk_id[4];
int chunk_size;
char format[4];
char subchunk1_id[4];
int subchunk1_size;
short int audio_format;
short int num_channels;
int sample_rate; // sample_rate denotes the sampling rate.
int byte_rate;
short int block_align;
short int bits_per_sample;
char subchunk2_id[4];
int subchunk2_size; // subchunk2_size denotes the number of samples.
//char data; // actual data : Added by tarmizi
} header;
typedef struct header_file* header_p;
int main()
{
ofstream myFile;
myFile.open("mizi.txt");
FILE * infile = fopen("0BF1S1T0.wav","rb"); // Open wave file in read mode
FILE * outfile = fopen("Output.txt","wb"); // Create output ( wave format) file in write mode;
FILE * svFile;
int BUFSIZE = 256; // BUFSIZE can be changed according to the frame size required (eg:512)
int count = 0; // For counting number of frames in wave file.
short int buff16[BUFSIZE]; // short int used for 16 bit as input data format is 16 bit PCM audio
header_p meta = (header_p)malloc(sizeof(header)); // header_p points to a header struct that contains the wave file metadata fields
int nb; // variable storing number of bytes returned
if (infile)
{
fread(meta, 1, sizeof(header), infile);
//fwrite(meta,1, sizeof(*meta), outfile);
cout << "first chunk is :" << sizeof(meta->chunk_id) << " bytes in size" << endl;
cout << "The file is a :" << meta->chunk_id << " format" << endl;
cout << " Size of Header file is "<<sizeof(*meta)<<" bytes" << endl;
cout << " Sampling rate of the input wave file is "<< meta->sample_rate <<" Hz" << endl;
cout << " Number of bits per sample is: "<< meta->bits_per_sample <<"bits" << endl;
cout << " Size of data in the audio is: " << sizeof(meta->subchunk2_size)<< " bytes" << endl;
cout << " The number of channels of the file is "<< meta->num_channels << " channels" << endl;
cout << " The audio format is PCM:"<< meta->audio_format << endl;
//cout << " The size of actual data is "<< sizeof(meta->data) << "bytes" << endl;
while (!feof(infile)) //(nb = fread(buff16,1,BUFSIZE,infile))>0
{
// Reading data in chunks of BUFSIZE
//cout << nb <<endl;
nb = fread(buff16,1,BUFSIZE,infile);
count++;
// Incrementing > of frame
for (int i = 0; i<BUFSIZE; i+=meta->num_channels) // BUFSIZE = 256, meta->num_channels = 1
{
int c = (buff16[i]<<8) | buff16[1+i];
double t = c/32768.0;
myFile << t<< endl;
}
}
cout << " Number of frames in the input wave file are " <<count << endl;
/
return 0;
}
}
有什么想法吗?我认为我不会循环数据并正确转换。任何人都可以帮我在这里展示正确的方法吗?提前谢谢......
答案 0 :(得分:1)
将两个字节组合成int的方式总是会产生正结果。为了正确处理符号,您应该将字节组合成short而不是int。
答案 1 :(得分:0)
问题似乎在于:
nb = fread(buff16,1,BUFSIZE,infile);
它实际上读取1 * BUFSIZE
个字节,而它应该读取2 * BUFSIZE
个字节(每个元素2个字节)。
将该行更改为以下内容:
nb = fread(buff16,sizeof(short int),BUFSIZE,infile);
另外,在
行int c = (buff16[i]<<8) | buff16[1+i];
buff16[i]
应该移位16位。
我对音频格式知之甚少。所以可能还有其他错误。
答案 2 :(得分:0)
此代码看起来不对:
int c = (buff16[i]<<8) | buff16[1+i];
double t = c/32768.0;
您应该将缓冲区声明为unsigned char[32]
。
然后为每个频道计算t
:
int hi = (signed char) buffer[i + 1]; // always little endian
int c = (hi << 8) | buffer[i + 0];
double t = c / 32768.0;
i += 2;