我在c ++(示例代码)中编写了以下代码来修改原始.wav文件中存在的数据,并将修改后的数据写入新创建的文件中。该程序为声音提供“回声效果”(注意: - 这是为只有2个声道的wav文件编写的)。
#include <iostream>
#include <conio.h>
#include <fstream>
#ifndef endl
#define endl "\n"
#endif
#define wav_eco(filin, fileout, eco_rate) \
char temp[2]; \
char ch[eco_rate][2], ch2[eco_rate][2]; \
int i,j; \
for(i=0; i<eco_rate; i++) \
for(j=0; j<2; j++) \
ch2[i][j] = 0; \
while(!filin.eof()) \
{ \
for(i=0; i<eco_rate && !filin.eof(); i++) \
filin.read((char*)&ch[i], sizeof(char[2])); \
for(i=0; i<eco_rate; i++) \
{ \
temp[0] = ch[i][0]; \
temp[1] = ch[i][1]; \
ch[i][0]+=ch2[i][0]; \
ch[i][1]+=ch2[i][1]; \
fileout.write((char*)&ch[i], sizeof(char[2])); \
ch2[i][0] = temp[0]; \
ch2[i][1] = temp[1]; \
} \
}
using namespace std;
struct WAVEFILEHEADER
{
char ChunkId[4];
int ChunkSize;
char Format[4];
char SubChunkFmt[4];
int SubChunkFmtSize;
short int AudioFormat;
short int NumChannels;
int SampleRate;
int ByteRate;
short int BlockAlign;
short int BitsPerSample;
char ChunkData[4];
int SubChunkDataSize;
};
int main()
{
fstream filin("C:\\Users\\chess.Admin-PC.000\\Music\\ExampleRead.wav", ios::in|ios::binary);
fstream fileout("C:\\Users\\chess.Admin-PC.000\\Music\\ExampleWrite.wav",ios::out| ios::binary);
WAVEFILEHEADER wav;
filin.read((char*)&wav,sizeof(wav));
//to display the contents of the header
cout<<wav.ByteRate
<<endl<<wav.ChunkSize
<<endl<<wav.SampleRate// no of samples per second
<<endl<<wav.SubChunkDataSize
<<endl<<wav.SubChunkFmtSize
<<endl<<wav.ChunkData
<<endl<<wav.ChunkId
<<endl<<wav.Format
<<endl<<wav.SubChunkFmt
<<endl<<wav.AudioFormat
<<endl<<wav.AudioFormat
<<endl<<wav.BitsPerSample//no of bits per second
<<endl<<wav.BlockAlign
<<endl<<wav.NumChannels
<<endl<<endl<<sizeof(wav); /* size of the wav variable*/
getch();
fileout.write((char*)&wav, sizeof(wav));/// write the header to output file
wav_eco(filin,fileout,10000) ///modify the data and update the output file
filin.close();
fileout.close();
return 0;
}
/*algorithm implemented by the wav_eco function(this is not some stranded algorithm. I wrote it myself) :-
1) obtain the 'echo_rate' of the samples
2) read the data present in the original wav file
3) write this data, by adding each sample from the previously obtained data to the data that was read now
4) follow steps 2 and 3 until eof is reached
*/
程序工作正常,当我使用Windows媒体播放器播放输出文件时,我得到了回声效果,但另外我得到了“嘶嘶”的声音。是什么导致这种情况以及以何种方式修改上述代码以避免它?是否可以简化wav_eco()
宏,以便减少程序的计算时间?
我对嘶嘶声的猜测是因为加法ch[i][0] += ch2[i][0]; ch[i][1]+=ch2[i][1];
。它是否以错误的方式修改声音? (这是我第一次编辑声音)
答案 0 :(得分:1)
此.wav文件有多种格式,格式列表为here。只有格式已知(无论是8位还是16位),才能回答上述问题。为了调试问题中给出的代码,我们不需要bit_rate,所以我们不需要知道格式是否是PCM等。所以如果文件是16位,那么{的以下代码可以使用{1}}:
wav_echo()
上面的宏#define wav_echo2_16(filin, fileout, eco_rate) \
short int temp; \
short int ch[eco_rate], ch2[eco_rate]; \
int i,j; \
for(i=0; i<eco_rate; i++) \
ch2[i] = 0; \
while(!filin.eof()) \
{ \
for(i=0; i<eco_rate && !filin.eof(); i++) \
filin.read((char*)&ch[i], sizeof(short int)); \
for(i=0; i<eco_rate; i++) \
{ \
temp = ch[i]; \
ch[i]+=ch2[i]; \
fileout.write((char*)&ch[i], sizeof(short int));\
ch2[i] = temp; \
} \
\
}
为16位文件提供了回声效果(请注意,wav_echo2_16()
常量应该是偶数,因为有2个通道)。
以下显示了8位格式的代码:
echo_rate
使用8位宏作为16位格式会产生嘶嘶声!
答案 1 :(得分:0)
您尝试一次添加8位的16位值。您需要检测低字节的溢出并将其转移到高字节添加,或者从一开始就使用16位算术。