Thread: Karaoke algorithm didn't work...

  1. #1
    Registered User
    Join Date
    Oct 2001
    Posts
    104

    Karaoke algorithm didn't work...

    Hi all!

    What I wanted to do is to filter the vocal. The algorithm that I know is:

    newLeft = oldLeft - oldRight
    newRight = oldRight - oldLeft

    This way, the vocal which in most cases is in the middle, should be eliminated, because equal amplitude phases with different sign (+ and -) will be added.

    My code is:

    Code:
    #include <iostream.h> 
    #include <fstream.h> 
    #include <windows.h> 
    
    typedef struct tagWAVEHEADER 
    { 
            char    RIFF[4];                // 'R','I','F','F'                
            DWORD   size;                   // size of wave file from here on 
            char    WAVEfmt[8];             // 'W','A','V','E','f','m','t',' ' 
            DWORD   wFormatLength;          // The length of the TAG format    
            WORD    wFormatTag;             // should be 1 for PCM type data  
            WORD    nChannels;              // should be 1 for MONO type data 
            DWORD   nSamplesPerSec;         // should be 11025, 22050, 44100  
            DWORD   nAvgBytesPerSec;        // Average Data Rate              
            WORD    nBlockAlign;            // 1 for 8 bit data, 2 for 16 bit 
            WORD    wBitsPerSample;         // 8 for 8 bit data, 16 for 16 bit 
            char    data[4];                // 'd','a','t','a'                        
            DWORD   datasize;               // size of data from here on              
    } WAVEHEADER; 
    
    int wavKaraoke(char *InputFileName,char *OutputFileName); 
    double ModifyVolume(double chunk, int value); 
    int ReadWaveHeader(char *FileName, WAVEHEADER &wave); 
    
    //chunk- a temporary data chunk which has the sample data. 
    //value- [0;100]. 0->min volume, 100->max volume 
    double  ModifyVolume(double chunk,int value) 
    { 
       return (chunk*value)/100; 
    } 
    
    int  ReadWaveHeader(char *FileName, WAVEHEADER &wave) 
    { 
    
       //First, open the wave file in binary mode 
       ifstream OpenFile(FileName,ios::binary | ios::in); 
    
    
       //Read the first 4 bytes, which will hold 'RIFF' 
       OpenFile.read(wave.RIFF,sizeof(wave.RIFF)); 
    
       //Now, read the size 
       OpenFile.read((char*)&wave.size,sizeof(wave.size)); 
    
       //Now, read 'WAVE' and 'fmt' in a single procedure 
       OpenFile.read(wave.WAVEfmt,sizeof(wave.WAVEfmt)); 
    
       //Now, read wFormatLength 
       OpenFile.read((char*)&wave.wFormatLength,sizeof(wave.wFormatLength)); 
    
       //Now, read the wFormatTag (which tells whther it is PCM wave file) 
       OpenFile.read((char*)&wave.wFormatTag,sizeof(wave.wFormatTag)); 
    
       //Now, read the number of channels (1-mono, 2-stereo) 
       OpenFile.read((char*)&wave.nChannels,sizeof(wave.nChannels)); 
    
       //Read the sample rate - 11025,22050 or 44100 
       OpenFile.read((char*)&wave.nSamplesPerSec,sizeof(wave.nSamplesPerSec)); 
    
       //The average number of bytes per second 
       OpenFile.read((char*)&wave.nAvgBytesPerSec,sizeof(wave.nAvgBytesPerSec)); 
    
       //1 is for 8bit data, 2 is for 16bit data 
       OpenFile.read((char*)&wave.nBlockAlign,sizeof(wave.nBlockAlign)); 
    
       //The same as above 
       OpenFile.read((char*)&wave.wBitsPerSample,sizeof(wave.wBitsPerSample)); 
    
       //Now, read 'data' 
       OpenFile.read(wave.data,sizeof(wave.data)); 
    
       //The number of bytes of the sound itself 
       OpenFile.read((char*)&wave.datasize,sizeof(wave.datasize)); 
    
    
       //Close the file 
       OpenFile.close(); 
       return 0; 
    } 
    
    
    
    
    int wavKaraoke(char *InputFileName, char *OutputFileName) 
    { 
    
       ifstream OpenFile(InputFileName,ios::binary); 
       ofstream SaveFile(OutputFileName, ios::binary); 
    
       //Read the wave header 
       WAVEHEADER waveHeader; 
       ReadWaveHeader(InputFileName,waveHeader); 
       //Now, put it into the new file 
       SaveFile.write((char *)&waveHeader,sizeof(waveHeader)); 
    
    
    
       int oldLeft,oldRight,newLeft,newRight; 
    
       while(!OpenFile.eof()) 
       { 
          //assume that it is stereo file 
          //Read one left one right channel 
          OpenFile.read((char *)&oldLeft, sizeof(oldLeft)); 
          OpenFile.read((char *)&oldRight,sizeof(oldRight)); 
    
          newLeft = oldLeft - oldRight; 
          newRight = oldRight - oldLeft; 
    
          SaveFile.write((char *)&newLeft, sizeof(newLeft)); 
          SaveFile.write((char *)&newRight,sizeof(newRight)); 
    
    
       } 
    
       OpenFile.close(); 
       SaveFile.close(); 
       return 0; 
    } 
    
    int main() 
    { 
    
       wavKaraoke("e:\\Shadows.wav","e:\\zShadowsKaraoke.wav"); 
       cout << "Done!" << endl; 
       return 0; 
    }
    It does the new file, but the new file sounds very bad... nothing to do with Karaoke.

    Any ideas and suggestions?

    Thanks!
    Ilia Yordanov,
    http://www.cpp-home.com ; C++ Resources

  2. #2
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    I know zilch about .wav files, so can't comment on your algorithm. But I did notice one problem.
    Code:
    >int  ReadWaveHeader(char *FileName, WAVEHEADER &wave) 
    >{ 
    >
    >   //First, open the wave file in binary mode 
    >   ifstream OpenFile(FileName,ios::binary | ios::in);
    You should probably pass in the input stream instead of a filename:
    Code:
    int  ReadWaveHeader(ifstream &OpenFile, WAVEHEADER &wave) 
    {
    And then your call would be:
    ReadWaveHeader(OpenFile,waveHeader);

    Otherwise when you get to this loop you are reading from the beginning of the file, not after the WAVEHEADER:
    > int oldLeft,oldRight,newLeft,newRight;
    >
    > while(!OpenFile.eof())

  3. #3
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    You could do it like that or you could linear interpolate between the left and the right channels.

    You are simply subtracting the values which will produce garbage, especially on underflow conditions. You can also average the two channels and combine them into one. This is called additive mixing.

    You are trying to do subtractive mixing or something.


    newLeft=(oldLeft-oldRight)/NumberOfSamples;
    newRight=(oldRight-oldLeft)/NumberOfSamples;

  4. #4
    Registered User
    Join Date
    Oct 2001
    Posts
    104
    What is "NumberOfSamples" variable? The number of samples per second or what?
    Also, this thing doesn't work of course, because I read every signle sample, so there is no point to divide it into 44100 for example.

    P.S. About the File I/O thing- yes, I corrected it! Thanks a lot!

    So, any other suggestions about how channels should be substracted/added?

    Thanks in advance!
    Ilia Yordanov,
    http://www.cpp-home.com ; C++ Resources

  5. #5
    Registered User
    Join Date
    Dec 2003
    Posts
    11

    question for you

    Hey,
    Where can you find information about how .wav files are built? I'm very interested in building programs that alter .wav files, but I just can't find any good info. How did you learn about it loobian?
    -joris

  6. #6
    Registered User
    Join Date
    Oct 2003
    Posts
    9
    first suggestion :

    in your "int ReadWaveHeader(char *FileName, WAVEHEADER &wave)" you read the WAVEHEADER struct member by member, why don't you just do

    OpenFile.read((char*)&wave,sizeof(WAVEHEADER));

    next:

    your samples are read as 32 bit signed integers

    >int oldLeft,oldRight,newLeft,newRight;
    >
    >OpenFile.read((char *)&oldLeft, sizeof(oldLeft));
    >OpenFile.read((char *)&oldRight,sizeof(oldRight));

    assuming you have a 16 bit .wav file you should use short for this
    Last edited by epic; 12-17-2003 at 07:06 AM.

  7. #7
    Registered User
    Join Date
    Oct 2001
    Posts
    104
    Thanks! That worked I tottaly forgot that int is 4 bytes not two (I use VB a lot, where int is 2 bytes).

    I made one more little change. And here is the code in case anyone is interested:
    Code:
    int wavKaraoke(char *InputFileName, char *OutputFileName)
    {
    
    	ifstream OpenFile(InputFileName,ios::binary);
    	ofstream SaveFile(OutputFileName, ios::binary);
    
    	//Read the wave header
    	WAVEHEADER waveHeader;
    	ReadWaveHeader(OpenFile,waveHeader);
    	//Now, put it into the new file
    	SaveFile.write((char *)&waveHeader,sizeof(waveHeader));
    
    	const float coefficent = 0.7;
    
    	
    	short oldLeft,oldRight,newLeft,newRight;
    
    	while(!OpenFile.eof())
    	{
    		//assume that it is stereo file
    		//Read one left one right channel
    		OpenFile.read((char *)&oldLeft, sizeof(oldLeft));
    		OpenFile.read((char *)&oldRight,sizeof(oldRight));
    
    		newLeft=(oldLeft-oldRight)*coefficent;
    	newRight=(oldRight-oldLeft)*coefficent;
    
    		SaveFile.write((char *)&newLeft, sizeof(newLeft));
    		SaveFile.write((char *)&newRight,sizeof(newRight));
    
    
    	}
    
    	OpenFile.close();
    	SaveFile.close();
    	return 0;
    }
    P.S. There is some clicks and such + something like echo... how do I remove these?

    Thanks!
    Ilia Yordanov,
    http://www.cpp-home.com ; C++ Resources

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Binary Search Trees Part III
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 16
    Last Post: 10-02-2004, 03:00 PM
  2. If you are employed as a programmer, please look
    By Flood Fighter in forum A Brief History of Cprogramming.com
    Replies: 10
    Last Post: 09-28-2004, 02:35 AM
  3. Database Search Algorithm
    By Krupux in forum C Programming
    Replies: 1
    Last Post: 08-28-2003, 09:57 PM
  4. Algorithm question
    By PJYelton in forum C++ Programming
    Replies: 2
    Last Post: 10-28-2002, 10:52 AM
  5. string searching algorithm......help
    By Unregistered in forum C Programming
    Replies: 3
    Last Post: 12-07-2001, 09:59 AM