Page 1 of 1

Mix 2 WAVE files together and delay one of them

Posted: Fri Jul 11, 2014 2:20 am
by PHP
Hi,

the following procedure mixes 2 wave sounds together and returns the "new" sound:

Code: Select all

Structure WaveFile
  chunkID .s{4}
  chunkSize.l
  riffType.s{4}
  FormatHeader.s{4}
  FormatLength.l
  wFormatTag.w
  wChannels.w
  dwSamplesPerSec.l
  dwAvgBytesPerSec.l
  wBlockAlign.w
  wBitsPerSample.w
  DataHeader.s{4}
  DataLen.l
EndStructure

InitSound()

Procedure MixSound(FileName1.s, FileName2.s)
 
  Protected Result.i = #False
  Protected Size1.i = FileSize(FileName1)
  Protected Size2.i = FileSize(FileName2)
 
  If Size1 And Size2

    Protected File1.i = OpenFile(#PB_Any, FileName1)
    If File1
     
      Protected File2.i = OpenFile(#PB_Any, FileName2) 
      If File2
       
        *Wave1.WaveFile = AllocateMemory(Size1)
       
        If *Wave1
          *Wave2.WaveFile = AllocateMemory(Size2)
         
          If *Wave2
         
            If Size1 > Size2
              *Wave3.WaveFile = AllocateMemory(Size1)
            Else
              *Wave3.WaveFile = AllocateMemory(Size2)
            EndIf
           
            If *Wave3
           
              ReadData(File1,*Wave1,Size1)
              ReadData(File2,*Wave2,Size2)
             
              If *Wave1\dwSamplesPerSec = *Wave2\dwSamplesPerSec And *Wave1\wChannels = *Wave2\wChannels

                If *Wave1\wBitsPerSample <> 8 And *Wave1\dwSamplesPerSec = *Wave2\dwSamplesPerSec
                 
                  Protected BitPerSample.i = *Wave1\wBitsPerSample
                  Protected MaxSamples.i = *Wave1\DataLen / (BitPerSample / 8)
                 
                  If *Wave2\DataLen / (BitPerSample / 8) > MaxSamples
                    MaxSamples = *Wave2\DataLen / (BitPerSample / 8)
                  EndIf
                 
                  Protected i.i
                  Protected Sample1.i
                  Protected Sample2.i
                 
                     
                    Debug MaxSamples
                   
                    
                    For i = 0 To MaxSamples - 1 
                      
                      If i < (*Wave1\DataLen / (BitPerSample / 8))
                        Sample1 = PeekW(*Wave1 + SizeOf(WaveFile) + i * 2)*1
                      Else
                        Sample1 = 0
                      EndIf
                      If i < (*Wave2\DataLen / (BitPerSample / 8))
                        Sample2 = PeekW(*Wave2 + SizeOf(WaveFile) + i * 2)*1
                      Else
                        Sample2 = 0
                      EndIf
                      PokeW(*Wave3  + SizeOf(WaveFile) + i * 2, (Sample1 + Sample2) /2)
                      
                    Next
                   
                 
                  If *Wave1\DataLen > *Wave2\DataLen
                    CopyMemory(*Wave1, *Wave3,  SizeOf(WaveFile))
                  Else
                    CopyMemory(*Wave2, *Wave3,  SizeOf(WaveFile))
                  EndIf
                 
                  Result = CatchSound(#PB_Any, *Wave3)
                 
                EndIf
             
              EndIf

              FreeMemory(*Wave3)
            EndIf
            FreeMemory(*Wave2)
          EndIf
          FreeMemory(*Wave1)
        EndIf
       
        CloseFile(File2)
      EndIf
     
      CloseFile(File1)
    EndIf
  EndIf
 
  ProcedureReturn Result
EndProcedure
All sounds are 44100 Hz / 16bit / mono = 705600 Bits/sec

Actually they start at the same time... but how can i delay one of the samples by some milliseconds?

1) convert e.g. 50 milliseconds to bits (705600/1000)*5 = 3528 bits
2) allocate (3528 bits * 8 = 28224 bytes) more for memory of Wave3.WaveFile
3) start mixing in the other sound AFTER x bits/"samples"?

If you don't understand it: Just imagine one sound and another sound with 50 milliseconds silence at the beginning.... and mixing them together.

Thanks!