Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
211 views
in Technique[技术] by (71.8m points)

c++ - adding echo effect to a .wav file

I have written the following code in c++ (sample code) to modify the data present in the original .wav file and write the modified data to a newly created file. This program gives 'echo-effect' to the sound (note:- this is written for a wav file with just 2 channels).

#include <iostream>
#include <conio.h>
#include <fstream>
#ifndef endl
#define endl "
"
#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  
  */

The program works fine, when I play the output file using windows media player,I get the echo effect, but in addition I get a 'hissing' sound. what causes this and in what way will I have to modify the above code to avoid it? Is it possible to simplify thewav_eco() macro such that the program's computation time is reduced?

my guess for the hissing sound is because of the addition ch[i][0] += ch2[i][0]; ch[i][1]+=ch2[i][1];. Does it modify the sound in the wrong way? (this is the first time I am editing sound)

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

There are several formats for this .wav file and the format list is given here. The above question can only be answered if the format is known (whether its 8 bit or 16 bit). to debug the code given in the question, we wouldn't need the bit_rate so we don't need to know if the format is PCM, etc. So if the file is 16 bit, then the following code for wav_echo() can be used:

#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;                                  
            }                                                   
                                                                
}

the above macro wav_echo2_16() provides the echo effect for 16 bit files (note that the echo_rate constant should be even as there are 2 channels). the following shows the code for a 8-bit format:

#define  wav_echo2_8(filin, fileout, eco_rate)
char temp;
char 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(char));
    for(i=0; i<eco_rate; i++)
            {
                temp  = ch[i];
                ch[i]+=ch2[i];
                fileout.write((char*)&ch[i], sizeof(char));
                ch2[i] = temp;
            }
            
}

and using the 8-bit macro for a 16-bit format causes the hissing sound!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...