Generare un'onda sinusoidale con il componente gb.openal
Da Gambas-it.org - Wikipedia.
Utilizzando le risorse della Classe Alc del Componente gb.openal di Gambas, è possibile eseguire un'onda sinusoidale, i cui dati saranno realizzati mediante apposita formula matematica.
Vediamo un esempio pratico:
Private Const AMPIEZZA As Byte = 127 Private Const FREQUENZA As Short = 880 Private Const CAMPIONAMENTO As Integer = 44100 Private Const DURATA As Single = 4.0 Public Sub Main() Dim disp As AlcDevice Dim cont As AlcContext Dim src, buffer As Integer[] Dim err As Boolean Dim dati As New Byte[] ' Configura il dispositivo audio con la Classe "Alc": disp = Alc.OpenDevice(Null) If IsNull(disp) Then Error.Raise("Impossibile configurare il dispositivo audio !") ' Configura il contesto audio con la Classe "Alc": cont = Alc.CreateContext(disp) If IsNull(cont) Then Error.Raise("Impossibile configurare il contesto audio !") err = cont.MakeCurrent() If err = False Then Error.Raise("Impossibile creare il contesto audio !") src = Al.GenSources(1) If IsNull(src) Then Error.Raise("Errore !") ' Configura il buffer audio: buffer = Al.GenBuffers(1) If IsNull(buffer) Then Error.Raise("Errore !") Onda(dati) ' I dati audio sono caricati nel buffer audio: Al.BufferData(buffer[0], al.FORMAT_MONO8, dati.Data, dati.Count, CAMPIONAMENTO) ' Connette il buffer audio al sorgente audio: Al.Sourcei(src[0], Al.BUFFER, buffer[0]) ' Esegue il sorgente audio: Al.SourcePlay(src[0]) ' Consente l'esecuzione per l'intera durata dell'onda sonora: Wait DURATA Al.SourceStop(src[0]) ' Libera la memoria: Al.DeleteBuffers(buffer) Al.DeleteSources(src) Alc.DestroyContext(cont) Alc.CloseDevice(disp) End Private Function Onda(bb As Byte[]) ' Crea i dati dell'onda sinusoidale Dim i As Integer For i = 0 To (DURATA * CAMPIONAMENTO) - 1 bb.Push(CByte(128 + AMPIEZZA * Sin(CFloat(i / CAMPIONAMENTO * FREQUENZA * (2 * Pi))))) Next End
In quest'altro codice, simile al precedente, applicheremo ai dati dell'onda sinusoidale l'effetto della Funzione Finestra di Hamming:
Private Const AMPIEZZA As Byte = 127 Private Const FREQUENZA As Short = 440 Private Const CAMPIONAMENTO As Integer = 44100 Private Const DURATA As Single = 20.0 Private Const AMP_HAMM As Single = 0.95 Private Const TEMPO_DISCRETO As Integer = 16384 Public Sub Main() Dim disp As AlcDevice Dim cont As AlcContext Dim src, buffer As Integer[] Dim err As Boolean Dim dati As New Byte[] ' Configura il dispositivo audio con la Classe "Alc": disp = Alc.OpenDevice(Null) If IsNull(disp) Then Error.Raise("Impossibile configurare il dispositivo audio !") ' Configura il contesto audio con la Classe "Alc": cont = Alc.CreateContext(disp) If IsNull(cont) Then Error.Raise("Impossibile configurare il contesto audio !") err = cont.MakeCurrent() If err = False Then Error.Raise("Impossibile creare il contesto audio !") src = Al.GenSources(1) If IsNull(src) Then Error.Raise("Errore !") ' Configura il buffer audio: buffer = Al.GenBuffers(1) If IsNull(buffer) Then Error.Raise("Errore !") Onda(dati) ' I dati audio sono caricati nel buffer audio: Al.BufferData(buffer[0], al.FORMAT_MONO8, dati.Data, dati.Count, CAMPIONAMENTO) ' Connette il buffer audio al sorgente audio: Al.Sourcei(src[0], Al.BUFFER, buffer[0]) ' Esegue il sorgente audio: Al.SourcePlay(src[0]) ' Consente l'esecuzione per l'intera durata dell'onda sonora: Wait DURATA Al.SourceStop(src[0]) ' Libera la memoria: Al.DeleteBuffers(buffer) Al.DeleteSources(src) Alc.DestroyContext(cont) Alc.CloseDevice(disp) End Private Function Onda(bb As Byte[]) ' Crea i dati dell'onda sinusoidale Dim i As Integer For i = 0 To (DURATA * CAMPIONAMENTO) - 1 bb.Push(CByte(128 + AMPIEZZA * Sin(CFloat(i / CAMPIONAMENTO * FREQUENZA * (2 * Pi))))) ' Applica la Funzione Finestra di Hamming: bb[i] *= AMP_HAMM * (0.54 - 0.46 * Cos(2.0 * Pi * i / (TEMPO_DISCRETO - 1))) Next End
In questo codice utilizzeremo un'altra formula per generare i dati dell'onda sinusoidale, i quali in questo caso avranno una definizione a 16-bit. Inoltre al termine dell'esecuzione audio dell'onda sinusoidale, i dati audio grezzi saranno salvati in un file.
Private Const AMPIEZZA As Byte = 128 Private Const CAMPIONAMENTO As Integer = 44100 Private Const FREQUENZA As Short = 440 Private Const DURATA As Single = 10.0 Private Const AMP_HAMM As Single = 32.0 Private Const TEMPO_DISCRETO As Integer = 32768 Public Sub Main() Dim disp As AlcDevice Dim cont As AlcContext Dim src, buffer As Integer[] Dim err As Boolean Dim dati As New Short[] disp = Alc.OpenDevice(Null) If IsNull(disp) Then Error.Raise("Impossibile configurare il dispositivo audio !") cont = Alc.CreateContext(disp) If IsNull(cont) Then Error.Raise("Impossibile configurare il contesto audio !") err = cont.MakeCurrent() If err = False Then Error.Raise("Impossibile creare il contesto audio !") src = Al.GenSources(1) If IsNull(src) Then Error.Raise("Errore !") buffer = Al.GenBuffers(1) If IsNull(buffer) Then Error.Raise("Errore !") Onda(dati) Al.BufferData(buffer[0], al.FORMAT_MONO16, dati.Data, dati.Count, CAMPIONAMENTO) Al.Sourcei(src[0], Al.BUFFER, buffer[0]) Al.SourcePlay(src[0]) Wait DURATA Al.SourceStop(src[0]) ' Libera la memoria: Al.DeleteBuffers(buffer) Al.DeleteSources(src) Alc.DestroyContext(cont) Alc.CloseDevice(disp) ' Va a generare il file contenente i dati audio grezzi: CreaFileDatiGrezzi(dati) End Private Function Onda(data As Short[]) ' Crea i dati dell'onda sinusoidale Dim k As Integer For k = 0 To (DURATA * CAMPIONAMENTO) - 1 data.Push(AMPIEZZA * Sin(2.0 * k * Pi * 1.0 / 64.0 + 0.4)) ' Applica la Funzione Finestra di Hamming: data[k] *= AMP_HAMM * (0.54 - 0.46 * Cos(2.0 * Pi * k / (TEMPO_DISCRETO - 1))) Next End Private Procedure CreaFileDatiGrezzi(grezzi As Short[]) Dim fl As File fl = Open "/tmp/dati_audio" For Create ' Salva i dati audio grezzi nel file: grezzi.Write(fl, 0, grezzi.Count) fl.Close End