Differenze tra le versioni di "Fondere insieme due file WAV"

Da Gambas-it.org - Wikipedia.
Riga 28: Riga 28:
 
   fl = Open fileWAV_1 For Read
 
   fl = Open fileWAV_1 For Read
 
   Seek #fl, 44
 
   Seek #fl, 44
   ss1.Read(fl, 0, (Lof(fl) - 44) / SizeOf(gb.Short))
+
   ss1.Read(fl, 0, (Lof(fl) - 44) / SizeOf(gb.Short))
 
   fl.Close
 
   fl.Close
 
    
 
    
Riga 34: Riga 34:
 
   fl = Open fileWAV_2 For Read
 
   fl = Open fileWAV_2 For Read
 
   Seek #fl, 44
 
   Seek #fl, 44
   ss2.Read(fl, 0, (Lof(fl) - 44) / SizeOf(gb.Short))
+
   ss2.Read(fl, 0, (Lof(fl) - 44) / SizeOf(gb.Short))
 
   fl.Close
 
   fl.Close
 
    
 
    
  <FONT color=gray>' ''Crea un terzo vettore (destinato a contenere i dati del file wav finale) assegnandogli la medesima dimensione di elementi pari a quella maggiore individuata tra i due file wav:''</font>
+
  <FONT color=gray>' ''Crea un terzo vettore (destinato a contenere i dati del file wav finale) assegnandogli la medesima dimensione di elementi pari a quella maggiore individuata tra i due file wav + 44 singoli byte del blocco d'intestazione del nuovo file wav:''</font>
   ss3 = New Short[ss1.Count]
+
   ss3 = New Short[ss1.Count + 44]
 
   
 
   
   For i = 0 To ss3.Max
+
<FONT color=gray>' ''Passa "per Indirizzo" alla funzione il 3° vettore, al fine di creare il blocco di intestazione del futuro file wav:''</font>
  <FONT color=gray>' ''Somma le due onde e carica ciascun dato nel 3° vettore creato:''</font>
+
  CreaBloccoIntestazione(ss3)
     ss3[i] = CShort((CInt(ss1[i]) + CInt(ss2[i])) / SizeOf(gb.Short))
+
 +
   For i = 0 To (ss3.Max - 44) / SizeOf(gb.Short))
 +
  <FONT color=gray>' ''Somma le due onde e carica ciascun dato nel 3° vettore creato al byte d'indice 44, individuandolo tenuto conto della risoluzione a 16-bit del file wav:''</font>
 +
     ss3[i + (44 / SizeOf(gb.Short)] = CShort((CInt(ss1[i]) + CInt(ss2[i])) / SizeOf(gb.Short))
 
   Next
 
   Next
 
<FONT color=gray>' ''Crea il blocco di intestazione del futuro file wav:''</font>
 
  he = CreaBloccoIntestazione(ss3.Count)
 
 
   
 
   
 
   fl = Open "/tmp/nuovo.wav" For Create
 
   fl = Open "/tmp/nuovo.wav" For Create
 
  <FONT color=gray>' ''Crea il nuovo file wav:''</font>
 
  <FONT color=gray>' ''Crea il nuovo file wav:''</font>
   he.Write(fl, 0, he.Count)
+
   ss3.Write(fl, 0, ss3.Count / SizeOf(gb.Short))
 
   fl.Close
 
   fl.Close
 
  fl = Open "/tmp/nuovo.wav" For Write Append
 
<FONT color=gray>' ''Crea il nuovo file wav:''</font>
 
  ss3.Write(fl, Stat("/tmp/nuovo.wav").Size, ss3.Count / 2)
 
 
 
<FONT color=gray>' ''Va in chiusura:''</font>
 
  fl.Close
 
  he.Clear
 
  ss1.Clear
 
  ss2.Clear
 
 
   
 
   
 
  '''End'''
 
  '''End'''
 
   
 
   
  '''Private''' Function CreaBloccoIntestazione(dati_grezzi As Integer) as Byte[]
+
  '''Private''' Function CreaBloccoIntestazione(vettore As Short[])
 
  Dim ini As String = "RIFF"
 
  Dim bh As Byte[] = [&57, &41, &56, &45, &66, &6D, &74, &20, &10, &00, &00, &00, &01, &00, &02, &00,
 
                    &44, &AC, &00, &00, &10, &B1, &02, &00, &04, &00, &10, &00, &64, &61, &74, &61]
 
  Dim bb As New Byte[]
 
  Dim i As Integer
 
 
   
 
   
   bb = Byte[].FromString(ini)
+
   Dim st As Stream
 
   
 
   
   i = dati_grezzi + 36
+
<FONT color=gray>' ''Per scrivere i dati del blocco d'intestazione del nuovo file wav, usa la risorsa "Memory Stream" operando nella'area di memoria restituita dalla proprietà ".Data" del 3° vettore: ''</font>
 +
   st = Memory vettore.Data For Write
 
   
 
   
 +
  Write #st, "RIFF"
 
  <FONT color=gray>' ''Imposta il valore dimensionale di 4 byte a partire dal 5° byte del futuro file: ''</font>
 
  <FONT color=gray>' ''Imposta il valore dimensionale di 4 byte a partire dal 5° byte del futuro file: ''</font>
   bb.Add(i And &FF)
+
   Write #st, vettore.Count - 8 As Integer
   bb.Add(Shr(i And &FF00&, 8))
+
   Write #st, "WAVEfmt "
   bb.Add(Shr(i And &FF0000&, 16))
+
   Write #st, 16 As Integer
   bb.Add(Shr(i And &FF000000&, 24))
+
  Write #st, 1 As Short
+
  Write #st, 2 As Short
   bb = bb.Insert(bh)
+
  Write #st, 44100 As Integer
+
   Write #st, 176400 As Integer
 +
  Write #st, 4 As Short
 +
   Write #st, 16 As Short
 +
  Write #st, "data"
 
  <FONT color=gray>' ''Imposta il valore dimensionale di 4 byte a partire dal 41° byte del futuro file e relativo alla dimensione dei dati audio grezzi:''</font>
 
  <FONT color=gray>' ''Imposta il valore dimensionale di 4 byte a partire dal 41° byte del futuro file e relativo alla dimensione dei dati audio grezzi:''</font>
   bb.Add(dati_grezzi And &FF)
+
   Write #st, vettore.Count - 44 As Integer
  bb.Add(Shr(dati_grezzi And &FF00&, 8))
 
  bb.Add(Shr(dati_grezzi And &FF0000&, 16))
 
  bb.Add(Shr(dati_grezzi And &FF000000&, 24))
 
 
   
 
   
   Return bb
+
   st.Close
 
   
 
   
 
  '''End'''
 
  '''End'''

Versione delle 20:06, 17 set 2022

Per fondere (mischiare) due file audio di formato WAV con le sole funzioni di Gambas, bisognerà prestare cura ad almeno i seguenti aspetti:

  • i due file da fondere devono avere uguale frequenza e risoluzione di campionamento ed uguale numero di canali;
  • eliminare (via codice Gambas) l'intero primo blocco di intestazione al file avente dimensione inferiore;
  • impostare (via codice Gambas) i nuovi corretti valori che indicano le dimensioni del file wav, presenti nei byte n. 4, 5, 6, 7 e nei byte n. 40, 41, 42, 43 dell'header del file wav finale.

Di seguito un possibile semplice codice supponendo che i due file wav siano a 2 canali e a 16bit:

Public Sub Main()

 Dim fileWAV_1, fileWAV_2 As String
 Dim fl As File
 Dim ss1, ss2, ss3 As Short[]
 Dim i As Integer
 Dim he As Byte[]

 fileWav_1 = "/percorso/del/primo/file.wav"

 fileWAV_2 = "/percorso/del/secondo/file.wav"

' Individua la dimensione maggiore tra i due file wav:
 i = Max(Stat(fileWAV_1).Size, Stat(fileWAV_2).Size)

' Assegna a entrambi i vettori di tipo "Short[]" la medesima dimensione di elementi pari a quella maggiore individuata tra i due file wav:
 ss1 = New Short[i - 44]
 ss2 = New Short[i - 44]

' Apre il 1° file wav e carica nel 1° vettore i soli dati audio grezzi:
 fl = Open fileWAV_1 For Read
  Seek #fl, 44
  ss1.Read(fl, 0, (Lof(fl) - 44) / SizeOf(gb.Short))
 fl.Close
 
' Apre il 2° file wav e carica nel 2° vettore i soli dati audio grezzi:
 fl = Open fileWAV_2 For Read
  Seek #fl, 44
  ss2.Read(fl, 0, (Lof(fl) - 44) / SizeOf(gb.Short))
 fl.Close
 
' Crea un terzo vettore (destinato a contenere i dati del file wav finale) assegnandogli la medesima dimensione di elementi pari a quella maggiore individuata tra i due file wav + 44 singoli byte del blocco d'intestazione del nuovo file wav:
 ss3 = New Short[ss1.Count + 44]

' Passa "per Indirizzo" alla funzione il 3° vettore, al fine di creare il blocco di intestazione del futuro file wav:
 CreaBloccoIntestazione(ss3)

 For i = 0 To (ss3.Max - 44) / SizeOf(gb.Short))
' Somma le due onde e carica ciascun dato nel 3° vettore creato al byte d'indice 44, individuandolo tenuto conto della risoluzione a 16-bit del file wav:
   ss3[i + (44 / SizeOf(gb.Short)] = CShort((CInt(ss1[i]) + CInt(ss2[i])) / SizeOf(gb.Short))
 Next

 fl = Open "/tmp/nuovo.wav" For Create
' Crea il nuovo file wav:
 ss3.Write(fl, 0, ss3.Count / SizeOf(gb.Short))
 fl.Close

End

Private Function CreaBloccoIntestazione(vettore As Short[])

 Dim st As Stream

' Per scrivere i dati del blocco d'intestazione del nuovo file wav, usa la risorsa "Memory Stream" operando nella'area di memoria restituita dalla proprietà ".Data" del 3° vettore: 
 st = Memory vettore.Data For Write

 Write #st, "RIFF"
' Imposta il valore dimensionale di 4 byte a partire dal 5° byte del futuro file: 
 Write #st, vettore.Count - 8 As Integer
 Write #st, "WAVEfmt "
 Write #st, 16 As Integer
 Write #st, 1 As Short
 Write #st, 2 As Short
 Write #st, 44100 As Integer
 Write #st, 176400 As Integer
 Write #st, 4 As Short
 Write #st, 16 As Short
 Write #st, "data"
' Imposta il valore dimensionale di 4 byte a partire dal 41° byte del futuro file e relativo alla dimensione dei dati audio grezzi:
 Write #st, vettore.Count - 44 As Integer

 st.Close

End