Generare un'onda sinusoidale con le funzioni esterne della libreria Sndfile

Da Gambas-it.org - Wikipedia.

Mostriamo di seguito un semplice esempio per generare un file WAV contenente i dati audio di un'onda sinusoidale a doppio canale, e pertanto può essere formata da due frequenze diverse.

E' necessario avere installata nel sistema e richiamare in Gambas la libreria condivisa: "libsndfile.so.1.0.37 ".

Private Const FREQUENZA As Integer = 44100
Private Const DURATA As Integer = 176400         ' (FREQUENZA * 4 secondi)
Private Const AMPIEZZA As Float = 2130706432.00  ' (1,0 * &h7F000000)
Private Const LEFT_FREQ As Float = 0.009977324   ' (hz 329,6 / FREQUENZA)
Private Const RIGHT_FREQ As Float = 0.007473923  ' (hz 440,0 / FREQUENZA)


Library "libsndfile:1.0.37"

Public Struct SF_INFO
  frames As Long
  samplerate As Integer
  channels As Integer
  format_ As Integer
  sections As Integer
  seekable As Integer
End Struct

Private Const SF_FORMAT_WAV As Integer = &010000
Private Const SF_FORMAT_PCM_16 As Integer = &0002
Private Const SFM_WRITE As Integer = &20

' SNDFILE * sf_open (const char *path, int mode, SF_INFO *sfinfo)
' Open the specified file for read, write or both.
Private Extern sf_open(path As String, mode As Integer, sfinfo As SF_INFO) As Pointer

' sf_count_t sf_write_int (SNDFILE *sndfile, const int *ptr, sf_count_t items)
' Function for writing the data chunk in terms of items.
Private Extern sf_write_int(sndfile As Pointer, ptr As Pointer, items As Long) As Long

' const char* sf_strerror (SNDFILE *sndfile)
' Returns to the caller a pointer to the current error message for the given SNDFILE.
Private Extern sf_strerror(sndfile As Pointer) As String

' int sf_close (SNDFILE *sndfile)
' Close the SNDFILE and clean up all memory allocations associated with this file.
Private Extern sf_close(sndfile As Pointer) As Integer


Public Sub Main()
 
 Dim sfi As New SF_INFO
 Dim buffer As New Integer[2 * DURATA * SizeOf(gb.Integer)]
 Dim fl As Pointer
 Dim k As Integer
 Dim l As Long
 
 With sfi
   .samplerate = FREQUENZA
   .frames = DURATA
   .channels = 2
   .format_ = SF_FORMAT_WAV Or SF_FORMAT_PCM_16
 End With
 
' Si imposta il file WAV, dove verranno salvati i dati audio dell'onda sinusoidale:
 fl = sf_open("/percorso/del/file.wav", SFM_WRITE, sfi)
 If fl == 0 Then Error.Raise("Errore !")
 
' Genera i dati audio grezzi dei 2 canali dell'onda sinusoidale:
 For k = 0 To DURATA - 1
   buffer[2 * k] = AMPIEZZA * Sin(LEFT_FREQ * 2 * k * Pi)
   buffer[2 * k + 1] = AMPIEZZA * Sin(RIGHT_FREQ * 2 * k * Pi)
 Next
 
' Genera il file WAV contenente i dati dell'onda sinusoidale:
 l = sf_write_int(fl, buffer.Data, CLong(sfi.channels * DURATA))
 If l <> CLong(sfi.channels * DURATA) Then Error.Raise("Errore: " & sf_strerror(fl))
 
 sf_close(fl)
 
End