Advertisement
thecplusplusguy

mixing wavs

Aug 24th, 2012
226
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.00 KB | None | 0 0
  1. //mix 2 wav file
  2. //http://www.youtube.com/user/thecplusplusguy
  3. #include <iostream>
  4. #include <fstream>
  5. #include <string>
  6. #include <cstring>
  7.  
  8. bool isBigEndian()
  9. {
  10.     int a=1;
  11.     return !((char*)&a)[0];
  12. }
  13.  
  14. int convertToInt(char* buffer,int len,bool n=false)
  15. {
  16.     int a=0;
  17.     bool neg;   //we have to manually handle the negative sign in this case
  18.     if(!isBigEndian())
  19.     {
  20.         neg=(buffer[len-1] & 128) ? 1 : 0;
  21.         for(int i=0;i<len;i++)
  22.             ((char*)&a)[i]=buffer[i];
  23.     }else{
  24.         neg=(buffer[0] & 128) ? 1 : 0;
  25.         for(int i=0;i<len;i++)
  26.             ((char*)&a)[sizeof(int)-1-i]=buffer[i];
  27.     }
  28.     if(!n)
  29.         return a;
  30.     else
  31.         return a-(neg ? 65536 : 0);
  32. }
  33.  
  34. //convert an integer to a char array
  35. void convertToChar(char* buffer,int data,int len)
  36. {
  37.     for(int i=0;i<len;i++)
  38.         buffer[i]=0;
  39.     if(isBigEndian())
  40.     {
  41.         for(int i=0;i<len;i++)
  42.             buffer[sizeof(int)-1-i]=((char*)&data)[i];
  43.     }else{
  44.         for(int i=0;i<len;i++)
  45.             buffer[i]=((char*)&data)[i];   
  46.     }
  47. }
  48.  
  49.  
  50. //loads the wave file like in the tutorial
  51. char* loadWav(const char* filename,int& ochannels,int& osampleRate,int& osamplesPerSecond,int& osize)
  52. {
  53.     std::ifstream in(filename,std::ios::binary);
  54.     char tmpBuffer[4];
  55.     in.read(tmpBuffer,4);
  56.     if(strncmp(tmpBuffer,"RIFF",4)!=0)
  57.     {
  58.         std::cout << "This is not a valid WAV file (1) " << tmpBuffer[0] << tmpBuffer[1] << tmpBuffer[2] << tmpBuffer[3] << tmpBuffer[4] << '\n';
  59.         return 0;
  60.     }
  61.     in.read(tmpBuffer,4);
  62.     int sizeInBytes=convertToInt(tmpBuffer,4);
  63.     in.read(tmpBuffer,4);
  64.     if(strncmp(tmpBuffer,"WAVE",4)!=0)
  65.     {
  66.         std::cout << "This is not a valid WAV file (2) " << tmpBuffer[0] << tmpBuffer[1] << tmpBuffer[2] << tmpBuffer[3] << tmpBuffer[4] << '\n';
  67.         return 0;
  68.     }
  69.     in.read(tmpBuffer,4);
  70.     if(strncmp(tmpBuffer,"fmt ",4)!=0)
  71.     {
  72.         std::cout << "This is not a valid WAV file (3) " << tmpBuffer[0] << tmpBuffer[1] << tmpBuffer[2] << tmpBuffer[3] << tmpBuffer[4] << '\n';
  73.         return 0;
  74.     }  
  75.     in.read(tmpBuffer,4);
  76.     int fmtSize=convertToInt(tmpBuffer,4);
  77.     if(fmtSize!=16)
  78.     {
  79.         std::cout << "Sorry only PCM (not compressed WAV)" << fmtSize << '\n';
  80.         return 0;      
  81.     }
  82.     in.read(tmpBuffer,2);
  83.     int PCM=convertToInt(tmpBuffer,2);
  84.     if(PCM!=1)
  85.     {
  86.         std::cout << "Sorry only PCM (not compressed WAV)\n";
  87.         return 0;  
  88.     }
  89.     in.read(tmpBuffer,2);
  90.     int channels=convertToInt(tmpBuffer,2);
  91.     in.read(tmpBuffer,4);
  92.     int samples=convertToInt(tmpBuffer,4);
  93.     in.read(tmpBuffer,4);
  94.     int byteRate=convertToInt(tmpBuffer,4);
  95.     in.read(tmpBuffer,2);
  96.     int blockAlign=convertToInt(tmpBuffer,2);
  97.     in.read(tmpBuffer,2);
  98.     int bitsPerSample=convertToInt(tmpBuffer,2);
  99.     in.read(tmpBuffer,4);
  100.     if(strncmp(tmpBuffer,"data",4)!=0)
  101.     {
  102.         std::cout << "This is not a valid WAV file (4) " << tmpBuffer[0] << tmpBuffer[1] << tmpBuffer[2] << tmpBuffer[3] << tmpBuffer[4] << '\n';
  103.         return 0;
  104.     }      
  105.     in.read(tmpBuffer,4);
  106.     int dataSize=convertToInt(tmpBuffer,4);
  107.     if(dataSize<=0)
  108.     {
  109.         std::cout << "This is not a valid WAV file (4) " << dataSize << '\n';
  110.         return 0;  
  111.     }  
  112.     char* data=new char[dataSize];
  113.     in.read(data,dataSize);
  114.     ochannels=channels;
  115.     osampleRate=bitsPerSample;
  116.     osamplesPerSecond=samples;
  117.     osize=dataSize;
  118.     return data;
  119. }
  120.  
  121. //writes out the file
  122. void writeWAV(const char* filename,char* data,int datasize,const char* original)
  123. {
  124.     std::ifstream in(original,std::ios::binary);
  125.     std::ofstream out(filename,std::ios::binary);
  126.     char header[44];    //no conversation, use the same header as the original file (of course, you might want to change that)
  127.     in.read(header,44);
  128.     out.write(header,44);
  129.     out.write(data,datasize);
  130.     out.close();
  131.     in.close();
  132. }
  133.  
  134. int main()
  135. {
  136.     int ch1,bps1,sps1,size1;
  137.     int ch2,bps2,sps2,size2;
  138.     char* buf1=loadWav("first.wav",ch1,bps1,sps1,size1);
  139.     char* buf2=loadWav("second.wav",ch2,bps2,sps2,size2);
  140.     char* mixed=NULL;   //mixed, final result
  141.     if(ch1!=ch2 || ch1>=2 || bps1!=bps2 || sps1!=sps2)
  142.     {
  143.         std::cout << "Sorry, in this demonstration the channels, bitpersample samplespersecond have to be equal, and no stereo" << std::endl;
  144.     }else{
  145.         int bytePerSample=bps1/8;
  146.         char buf[2];
  147.         if(size2>size1)
  148.         {
  149.             //swap buffers
  150.             char* tmp=buf1;
  151.             buf1=buf2;
  152.             buf2=tmp;
  153.             //swap size
  154.             int itmp=size1;
  155.             size1=size2;
  156.             size2=itmp;
  157.         }
  158.         mixed=new char[size1];
  159.         for(int i=0;i<size2;i+=bytePerSample)   //either go byte-by-byte, or 2-byte at a loop (depent, if it's 8 bit or 16 bit per sample)
  160.         {
  161.             int sample1,sample2;
  162.             sample1=convertToInt(buf1+i,bytePerSample,true);
  163.             sample2=convertToInt(buf2+i,bytePerSample,true);
  164.             int result=(sample1+sample2)/2; //get the avarage of two
  165.             if(bytePerSample==1 && result>255)  //2^8 - 1
  166.                 result=255;
  167.             if(bytePerSample==2 && result>65536) //2^16 - 1
  168.                 result=65536;
  169.             convertToChar(buf,result,bytePerSample);
  170.             for(int j=0;j<bytePerSample;j++)
  171.             {
  172.                 mixed[i+j]=buf[j];
  173.             }
  174.         }
  175.         for(int i=size2;i<size1;i++)    //copy the rest of the data (if there is)
  176.             mixed[i]=buf1[i];
  177.         writeWAV("mixed.wav",mixed,size1,"first.wav");
  178.         std::cout << "mixed.wav created" << std::endl;
  179.     }
  180.     delete[] mixed;
  181.     delete[] buf1;
  182.     delete[] buf2;
  183.    
  184. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement