Generare un'onda sinusoidale con le sole funzioni di Gambas

Da Gambas-it.org - Wikipedia.

E' possibile generare un'onda sinusoidale con le sole risorse di Gambas.


Mostriamo un esempio (tratto da analogo codice scritto in C da Fabrice Bellard e convertito qui in Gambas con modifiche ed integrazioni), al termine del quale verrà creato un file di tipo WAV contenente i dati audio e che consentirà di eseguire l'onda sinusidale campionata:

Private Const RISOL_BIT As Integer = 16
Private Const COST_TAB_VAL As Integer = 7
Private FRAZIONE As Integer = 1 * CInt(2 ^ RISOL_BIT)
Private CSHIFT As Integer = RISOL_BIT - COST_TAB_VAL - 2
Private Tabella_Valori As Integer[] = [&8000&, &7ffe, &7ff6, &7fea, &7fd9, &7fc2, &7fa7, &7f87,
                                       &7f62, &7f38, &7f0a, &7ed6, &7e9d, &7e60, &7e1e, &7dd6,
                                       &7d8a, &7d3a, &7ce4, &7c89, &7c2a, &7bc6, &7b5d, &7aef,
                                       &7a7d, &7a06, &798a, &790a, &7885, &77fb, &776c, &76d9,
                                       &7642, &75a6, &7505, &7460, &73b6, &7308, &7255, &719e,
                                       &70e3, &7023, &6f5f, &6e97, &6dca, &6cf9, &6c24, &6b4b,
                                       &6a6e, &698c, &68a7, &67bd, &66d0, &65de, &64e9, &63ef,
                                       &62f2, &61f1, &60ec, &5fe4, &5ed7, &5dc8, &5cb4, &5b9d,
                                       &5a82, &5964, &5843, &571e, &55f6, &54ca, &539b, &5269,
                                       &5134, &4ffb, &4ec0, &4d81, &4c40, &4afb, &49b4, &486a,
                                       &471d, &45cd, &447b, &4326, &41ce, &4074, &3f17, &3db8,
                                       &3c57, &3af3, &398d, &3825, &36ba, &354e, &33df, &326e,
                                       &30fc, &2f87, &2e11, &2c99, &2b1f, &29a4, &2827, &26a8,
                                       &2528, &23a7, &2224, &209f, &1f1a, &1d93, &1c0c, &1a83,
                                       &18f9, &176e, &15e2, &1455, &12c8, &113a, &0fab, &0e1c,
                                       &0c8c, &0afb, &096b, &07d9, &0648, &04b6, &0324, &0192,
                                       &0000, &0000]


Public Sub Main()

 Dim fl As File
 Dim filegrezzo As String
 Dim i, a, v, j As Integer
 Dim campionamento, canali, frequenza, volume As Integer
 Dim durata As Single
 
  filegrezzo = "/tmp/datigrezzi"    ' File contenente i dati audio grezzi dell'onda
   
  campionamento = 44100   ' Frequenza di campionamento dell'onda
  canali = 2              ' Numero canali del file WAV
  frequenza = 440         ' Frequenza dell'onda
  durata = 3.0            ' Durata in secondi
  volume = 10000          ' Volume audio dell'onda
   
  fl = Open filegrezzo For Create
  If IsNull(fl) Then Error.Raise("Impossibile creare il file dei dati audio grezzi !")

' Genera 3 secondi di un'onda sinusoidale alla frequenza di Hz 440:
  For i = 0 To (durata * campionamento) - 1
    v = (int_cos(a) * volume) \ CInt(2 ^ RISOL_BIT)
    For j = 0 To canali - 1
      Scrivi_File(fl, v)
    Next
    a += (frequenza * FRAZIONE) / campionamento
  Next
   
  Crea_File_WAV(fl)

  fl.Close
   
  Print "Fine creazione dell'onda."

End


Private Function Int_Cos(a As Integer) As Integer

 Dim neg, v, f As Integer
 Dim p As Integer[]

  a = a And (FRAZIONE - 1)
  If a >= (FRAZIONE / 2) Then a = FRAZIONE - a
  neg = 0
  If a > (FRAZIONE / 4) Then
    neg = -1
    a = (FRAZIONE / 2) - a
  Endif

  p = Tabella_Valori.Copy(a \ CInt(2 ^ CSHIFT), Tabella_Valori.Count - a \ CInt(2 ^ CSHIFT))

' Interpolazione lineare:
  f = a And ((1 * CInt(2 ^ CSHIFT)) - 1)

  v = p[0] + (((p[1] - p[0]) * f + (1 * CInt(2 ^ (CSHIFT - 1)))) / CInt(2 ^ CSHIFT))

  v = (v Xor neg) - neg

  v = v * CInt(2 ^ (RISOL_BIT - 15))

  Return v

End


Private Procedure Scrivi_File(sf As File, v As Integer)
 
 Write #sf, CByte(v And &ff) As Byte
 
 Write #sf, CByte((v \ CInt(2 ^ 8)) And &ff) As Byte

End


Private Procedure Crea_File_WAV(cf As File)

 Dim int As File
 Dim bb As Byte[] = [&52, &49, &46, &46, &00, &00, &00, &00, &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]
     
' Scrive innanzitutto il blocco di intestazione del file WAV:
  int = Open "/tmp/blocco_header" For Create
  bb.Write(int, 0, 4)
  Write #int, Lof(dg) + 36 As Integer
  bb.Write(int, 8, 32)
  Write #int, Lof(dg) As Integer
  int.Close
   
' Unisce il blocco di intestazione del file WAV ai dati audio grezzi presenti nel file "datigrezzi"
' (in questo esempio il file WAV finale viene scritto nella cartella "/tmp"):
  File.Save("/tmp/onda.wav", File.Load("/tmp/blocco_header") & File.Load("/tmp/datigrezzi"))
 
End