Differenze tra le versioni di "Generare un'onda sinusoidale con le sole funzioni di Gambas"
Da Gambas-it.org - Wikipedia.
Riga 2: | Riga 2: | ||
Mostriamo di seguito tre esempi. | Mostriamo di seguito tre esempi. | ||
− | |||
==Creare un'onda sinusoidale e salvare i dati in un file WAV== | ==Creare un'onda sinusoidale e salvare i dati in un file WAV== | ||
Riga 17: | Riga 16: | ||
<FONT Color=gray>' ''Va a generare i dati dell'onda sinusoidale:''</font> | <FONT Color=gray>' ''Va a generare i dati dell'onda sinusoidale:''</font> | ||
− | + | dati = Onda() | |
<FONT Color=gray>' ''Va a generare il file WAV contenente l'onda sinusoidale:''</font> | <FONT Color=gray>' ''Va a generare il file WAV contenente l'onda sinusoidale:''</font> | ||
− | + | CreaFileWav(dati.ToString(0, dati.Count)) | |
'''End''' | '''End''' | ||
− | |||
'''Private''' Function Onda() As Byte[] | '''Private''' Function Onda() As Byte[] | ||
Riga 31: | Riga 29: | ||
Dim bb As New Byte[] | Dim bb As New Byte[] | ||
− | + | For i = 0 To (DURATA * 2 * CAMPIONAMENTO) - 1 | |
− | + | b = 128 + AMPIEZZA * Sin(CFloat(i / CAMPIONAMENTO * FREQUENZA * (2 * Pi))) | |
− | + | bb.Push(b) | |
− | + | Next | |
− | + | Return bb | |
'''End''' | '''End''' | ||
− | |||
'''Private''' Procedure CreaFileWav(dati_grezzi As String) | '''Private''' Procedure CreaFileWav(dati_grezzi As String) | ||
Riga 50: | Riga 47: | ||
<FONT Color=gray>' ''Vengono definiti gli elementi fondamentali del blocco d'intestazione del file wav:''</font> | <FONT Color=gray>' ''Vengono definiti gli elementi fondamentali del blocco d'intestazione del file wav:''</font> | ||
− | + | canali = 1 | |
− | + | risoluzione = 8 | |
− | + | fl = Open "/tmp/file.wav" For Create | |
− | + | ini = "RIFF" | |
− | + | bb = Byte[].FromString(ini) | |
− | + | i = Len(dati_grezzi) | |
− | + | i2 = i + 36 | |
<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.Push(i2 And &FF) | |
− | + | bb.Push(Shr(i2 And &FF00&, 8)) | |
− | + | bb.Push(Shr(i2 And &FF0000&, 16)) | |
− | + | bb.Push(Shr(i2 And &FF000000&, 24)) | |
<FONT Color=gray>' ''Vengono aggiunti: il tipo di formato di file e l'identificativo del formato del blocco dei dati audio:''</font> | <FONT Color=gray>' ''Vengono aggiunti: il tipo di formato di file e l'identificativo del formato del blocco dei dati audio:''</font> | ||
− | + | bb = bb.Insert(bh.FromString("WAVEfmt ")) | |
<FONT Color=gray>' ''Viene aggiunto il valore della lunghezza dei dati del formato (in questo caso il PCM):''</font> | <FONT Color=gray>' ''Viene aggiunto il valore della lunghezza dei dati del formato (in questo caso il PCM):''</font> | ||
− | + | bh = [&10, &00, &00, &00] | |
− | + | bb = bb.Insert(bh) | |
<FONT Color=gray>' ''Viene aggiunto il valore del formato audio (1 = PCM):''</font> | <FONT Color=gray>' ''Viene aggiunto il valore del formato audio (1 = PCM):''</font> | ||
− | + | bb = bb.Insert(bh.FromString(Chr(&01) & Chr(&00))) | |
<FONT Color=gray>' ''Viene aggiunto il numero dei canali di uscita:''</font> | <FONT Color=gray>' ''Viene aggiunto il numero dei canali di uscita:''</font> | ||
− | + | bb = bb.Insert(bh.FromString(Chr(canali) & Chr(&00))) | |
<FONT Color=gray>' ''Viene aggiunto il valore della frequenza di campionamento:''</font> | <FONT Color=gray>' ''Viene aggiunto il valore della frequenza di campionamento:''</font> | ||
− | + | bb.Push(CAMPIONAMENTO And &FF) | |
− | + | bb.Push(Shr(CAMPIONAMENTO And &FF00&, 8)) | |
− | + | bb.Push(Shr(CAMPIONAMENTO And &FF0000&, 16)) | |
− | + | bb.Push(Shr(CAMPIONAMENTO And &FF000000&, 24)) | |
<FONT Color=gray>' ''Viene aggiunto il valore del "Byte rate per secondo":''</font> | <FONT Color=gray>' ''Viene aggiunto il valore del "Byte rate per secondo":''</font> | ||
− | + | brps = CAMPIONAMENTO * canali * (risoluzione / 8) | |
− | + | bb.Push(brps And &FF) | |
− | + | bb.Push(Shr(brps And &FF00&, 8)) | |
− | + | bb.Push(Shr(brps And &FF0000&, 16)) | |
− | + | bb.Push(Shr(brps And &FF000000&, 24)) | |
− | + | ||
<FONT Color=gray>' ''Viene aggiunto il valore del "Block Align":''</font> | <FONT Color=gray>' ''Viene aggiunto il valore del "Block Align":''</font> | ||
− | + | blal = canali * risoluzione / 8 | |
− | + | bb = bb.Insert(bh.FromString(Chr(blal) & Chr(&00))) | |
<FONT Color=gray>' ''Viene aggiunto il valore della risoluzione di campionamento:''</font> | <FONT Color=gray>' ''Viene aggiunto il valore della risoluzione di campionamento:''</font> | ||
− | + | bb = bb.Insert(bh.FromString(Chr(risoluzione) & Chr(&00))) | |
<FONT Color=gray>' ''Viene aggiunto l'identificativo del Blocco dei dati audio grezzi:''</font> | <FONT Color=gray>' ''Viene aggiunto l'identificativo del Blocco dei dati audio grezzi:''</font> | ||
− | + | bb = bb.Insert(bh.FromString("data")) | |
− | <FONT Color=gray>' ''Imposta il valore dimensionale di 4 byte a partire dal 41° byte del futuro file | + | <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.Push(i And &FF) | |
− | + | bb.Push(Shr(i And &FF00&, 8)) | |
− | + | bb.Push(Shr(i And &FF0000&, 16)) | |
− | + | bb.Push(Shr(i And &FF000000&, 24)) | |
− | |||
− | + | bb = bb.Insert(Byte[].FromString(dati_grezzi)) | |
<FONT Color=gray>' ''Crea il nuovo file wav:''</font> | <FONT Color=gray>' ''Crea il nuovo file wav:''</font> | ||
− | + | bb.Write(fl, 0, bb.Count) | |
− | + | fl.Close | |
'''End''' | '''End''' | ||
− | |||
Riga 156: | Riga 151: | ||
Dim durata As Single | Dim durata As Single | ||
− | + | filegrezzo = "/tmp/datigrezzi" <FONT Color=gray>' ''File contenente i dati audio grezzi dell'onda''</font> | |
− | + | campionamento = 44100 <FONT Color=gray>' ''Frequenza di campionamento dell'onda''</font> | |
− | + | canali = 2 <FONT Color=gray>' ''Numero canali del file WAV''</font> | |
− | + | frequenza = 440 <FONT Color=gray>' ''Frequenza dell'onda''</font> | |
− | + | durata = 3.0 <FONT Color=gray>' ''Durata in secondi''</font> | |
− | + | volume = 10000 <FONT Color=gray>' ''Volume audio dell'onda''</font> | |
− | + | fl = Open filegrezzo For Create | |
− | + | If IsNull(fl) Then Error.Raise("Impossibile creare il file dei dati audio grezzi !") | |
<FONT Color=gray>' ''Genera 3 secondi di un'onda sinusoidale alla frequenza di Hz 440:''</font> | <FONT Color=gray>' ''Genera 3 secondi di un'onda sinusoidale alla frequenza di Hz 440:''</font> | ||
− | + | 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''' | '''End''' | ||
− | |||
'''Private''' Function Int_Cos(a As Integer) As Integer | '''Private''' Function Int_Cos(a As Integer) As Integer | ||
Riga 190: | Riga 184: | ||
Dim p 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)) | |
<FONT Color=gray>' ''Interpolazione lineare:''</font> | <FONT Color=gray>' ''Interpolazione lineare:''</font> | ||
− | + | 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''' | '''End''' | ||
− | |||
'''Private''' Procedure Scrivi_File(sf As File, v As Integer) | '''Private''' Procedure Scrivi_File(sf As File, v As Integer) | ||
Riga 221: | Riga 214: | ||
'''End''' | '''End''' | ||
− | |||
'''Private''' Procedure Crea_File_WAV(dg As File) | '''Private''' Procedure Crea_File_WAV(dg As File) | ||
Riga 232: | Riga 224: | ||
<FONT Color=gray>' ''Scrive innanzitutto il blocco di intestazione del file WAV:''</font> | <FONT Color=gray>' ''Scrive innanzitutto il blocco di intestazione del file WAV:''</font> | ||
− | + | intes = Open "/tmp/blocco_header" For Create | |
− | + | bb.Write(intes, 0, 4) | |
− | + | Write #intes, Lof(dg) + 36 As Integer | |
− | + | bb.Write(intes, 8, 32) | |
− | + | Write #intes, Lof(dg) As Integer | |
− | + | intes.Close | |
− | <FONT Color=gray>' ''Unisce il blocco di intestazione del file WAV ai dati audio grezzi presenti nel file "datigrezzi" | + | <FONT Color=gray>' ''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"):''</font> |
− | + | File.Save("/tmp/onda.wav", File.Load("/tmp/blocco_header") & File.Load("/tmp/datigrezzi")) | |
− | |||
'''End''' | '''End''' | ||
Riga 259: | Riga 250: | ||
Dim dati_grezzi As Short[] | Dim dati_grezzi As Short[] | ||
− | + | filegrezzo = "/tmp/datigrezzi" <FONT Color=gray>' ''Percorso del file che conterrà i dati audio grezzi dell'onda''</font> | |
− | + | campionamento = 44100 <FONT Color=gray>' ''Frequenza di campionamento dell'onda''</font> | |
− | + | NotaMidi = 60 <FONT Color=gray>' ''Numero della nota Midi''</font> | |
− | + | durata = 300000 <FONT Color=gray>' ''Durata''</font> | |
− | + | volume = 10000 <FONT Color=gray>' ''Volume audio dell'onda''</font> | |
− | + | fl = Open filegrezzo For Create | |
− | + | If IsNull(fl) Then Error.Raise("Impossibile creare il file dei dati audio grezzi !") | |
<FONT Color=gray>' ''Genera i dati audio grezzi:''</font> | <FONT Color=gray>' ''Genera i dati audio grezzi:''</font> | ||
− | + | dati_grezzi = CreaDatiAudio(NotaMidi, durata, volume, campionamento) | |
− | + | dati_grezzi.Write(fl, 0, dati_grezzi.Count) | |
<FONT Color=gray>' ''Crea il file wav finale:''</font> | <FONT Color=gray>' ''Crea il file wav finale:''</font> | ||
− | + | CreaFileWAV(fl) | |
− | + | fl.Close | |
− | + | Print "Fine creazione dell'onda e del file wav." | |
'''End''' | '''End''' | ||
− | + | ||
− | |||
'''Private''' Function CreaDatiAudio(nota As Byte, dur As Integer, ampiezza As Integer, freq_camp As Integer) As Short[] | '''Private''' Function CreaDatiAudio(nota As Byte, dur As Integer, ampiezza As Integer, freq_camp As Integer) As Short[] | ||
Riga 292: | Riga 282: | ||
<FONT Color=gray>' ''Ciclo per ciascun dato campione audio:''</font> | <FONT Color=gray>' ''Ciclo per ciascun dato campione audio:''</font> | ||
− | + | For ciclo = 1 To dur | |
<FONT Color=gray>' ''Calcola la frequenza della nota Midi:''</font> | <FONT Color=gray>' ''Calcola la frequenza della nota Midi:''</font> | ||
− | + | frequenza = CalcolaFrequenza(nota) | |
<FONT Color=gray>' ''Calcola il dato del campione audio:''</font> | <FONT Color=gray>' ''Calcola il dato del campione audio:''</font> | ||
− | + | campione = ampiezza * Sin(2 * Pi * ciclo * frequenza / freq_camp) | |
− | + | dati_audio.Push(campione) | |
− | + | Next | |
− | + | Return dati_audio | |
'''End''' | '''End''' | ||
− | |||
'''Private''' Function CalcolaFrequenza(numero_nota As Byte) As Float | '''Private''' Function CalcolaFrequenza(numero_nota As Byte) As Float | ||
Riga 309: | Riga 298: | ||
<FONT Color=gray>' ''Converte la nota Midi nella corrispondente frequenza sonora.'' | <FONT Color=gray>' ''Converte la nota Midi nella corrispondente frequenza sonora.'' | ||
' ''La nota di riferimento è il "Do centrale" (hz 261,63 -- nota Midi: 60).''</font> | ' ''La nota di riferimento è il "Do centrale" (hz 261,63 -- nota Midi: 60).''</font> | ||
− | + | Return 261.63 * (2 ^ (1 / 12)) ^ (numero_nota - 60) | |
'''End''' | '''End''' | ||
− | |||
'''Private''' Procedure CreaFileWAV(wav As File) | '''Private''' Procedure CreaFileWAV(wav As File) | ||
Riga 323: | Riga 311: | ||
<FONT Color=gray>' ''Scrive innanzitutto il blocco di intestazione del file WAV:''</font> | <FONT Color=gray>' ''Scrive innanzitutto il blocco di intestazione del file WAV:''</font> | ||
− | + | intes = Open "/tmp/blocco_header" For Create | |
− | + | If IsNull(intes) Then Error.Raise("Impossibile scrivere il blocco d'intestazione !") | |
− | + | bi.Write(intes, 0, 4) | |
<FONT Color=gray>' ''Scrive la quantità dei dati audio grezzi + 36 byte del blocco di intestazione del futuro file WAV:''</font> | <FONT Color=gray>' ''Scrive la quantità dei dati audio grezzi + 36 byte del blocco di intestazione del futuro file WAV:''</font> | ||
− | + | Write #intes, Lof(wav) + 36 As Integer | |
− | + | bi.Write(intes, 8, 32) | |
<FONT Color=gray>' ''Scrive la sola quantità dei dati audio grezzi del futuro file WAV:''</font> | <FONT Color=gray>' ''Scrive la sola quantità dei dati audio grezzi del futuro file WAV:''</font> | ||
− | + | Write #intes, Lof(wav) As Integer | |
− | + | intes.Close | |
− | <FONT Color=gray>' ''Unisce il blocco di intestazione del file WAV ai dati audio grezzi presenti nel file "datigrezzi" | + | <FONT Color=gray>' ''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"):''</font> |
− | + | File.Save("/tmp/onda.wav", File.Load("/tmp/blocco_header") & File.Load("/tmp/datigrezzi")) | |
− | |||
'''End''' | '''End''' |
Versione delle 16:59, 10 dic 2021
E' possibile generare un'onda sinusoidale con le sole risorse di Gambas.
Mostriamo di seguito tre esempi.
Creare un'onda sinusoidale e salvare i dati in un file WAV
Creiamo un'onda sinusoidale da 8000 hertz, 8-bit, 1 canale:
Private Const AMPIEZZA As Integer = 127 Private Const FREQUENZA As Integer = 110 Private Const CAMPIONAMENTO As Integer = 8000 Private Const DURATA As Integer = 10 Public Sub Main() Dim dati As Byte[] ' Va a generare i dati dell'onda sinusoidale: dati = Onda() ' Va a generare il file WAV contenente l'onda sinusoidale: CreaFileWav(dati.ToString(0, dati.Count)) End Private Function Onda() As Byte[] Dim i As Integer Dim b As Byte Dim bb As New Byte[] For i = 0 To (DURATA * 2 * CAMPIONAMENTO) - 1 b = 128 + AMPIEZZA * Sin(CFloat(i / CAMPIONAMENTO * FREQUENZA * (2 * Pi))) bb.Push(b) Next Return bb End Private Procedure CreaFileWav(dati_grezzi As String) Dim fl As File Dim ini As String Dim bh, bb As New Byte[] Dim canali, risoluzione, blal As Byte Dim i, i2, brps As Integer ' Vengono definiti gli elementi fondamentali del blocco d'intestazione del file wav: canali = 1 risoluzione = 8 fl = Open "/tmp/file.wav" For Create ini = "RIFF" bb = Byte[].FromString(ini) i = Len(dati_grezzi) i2 = i + 36 ' Imposta il valore dimensionale di 4 byte a partire dal 5° byte del futuro file: bb.Push(i2 And &FF) bb.Push(Shr(i2 And &FF00&, 8)) bb.Push(Shr(i2 And &FF0000&, 16)) bb.Push(Shr(i2 And &FF000000&, 24)) ' Vengono aggiunti: il tipo di formato di file e l'identificativo del formato del blocco dei dati audio: bb = bb.Insert(bh.FromString("WAVEfmt ")) ' Viene aggiunto il valore della lunghezza dei dati del formato (in questo caso il PCM): bh = [&10, &00, &00, &00] bb = bb.Insert(bh) ' Viene aggiunto il valore del formato audio (1 = PCM): bb = bb.Insert(bh.FromString(Chr(&01) & Chr(&00))) ' Viene aggiunto il numero dei canali di uscita: bb = bb.Insert(bh.FromString(Chr(canali) & Chr(&00))) ' Viene aggiunto il valore della frequenza di campionamento: bb.Push(CAMPIONAMENTO And &FF) bb.Push(Shr(CAMPIONAMENTO And &FF00&, 8)) bb.Push(Shr(CAMPIONAMENTO And &FF0000&, 16)) bb.Push(Shr(CAMPIONAMENTO And &FF000000&, 24)) ' Viene aggiunto il valore del "Byte rate per secondo": brps = CAMPIONAMENTO * canali * (risoluzione / 8) bb.Push(brps And &FF) bb.Push(Shr(brps And &FF00&, 8)) bb.Push(Shr(brps And &FF0000&, 16)) bb.Push(Shr(brps And &FF000000&, 24)) ' Viene aggiunto il valore del "Block Align": blal = canali * risoluzione / 8 bb = bb.Insert(bh.FromString(Chr(blal) & Chr(&00))) ' Viene aggiunto il valore della risoluzione di campionamento: bb = bb.Insert(bh.FromString(Chr(risoluzione) & Chr(&00))) ' Viene aggiunto l'identificativo del Blocco dei dati audio grezzi: bb = bb.Insert(bh.FromString("data")) ' Imposta il valore dimensionale di 4 byte a partire dal 41° byte del futuro file e relativo alla dimensione dei dati audio grezzi: bb.Push(i And &FF) bb.Push(Shr(i And &FF00&, 8)) bb.Push(Shr(i And &FF0000&, 16)) bb.Push(Shr(i And &FF000000&, 24)) bb = bb.Insert(Byte[].FromString(dati_grezzi)) ' Crea il nuovo file wav: bb.Write(fl, 0, bb.Count) fl.Close End
Ricavare un'onda sinusoidale da un insieme di dati audio grezzi predefiniti in un vettore
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 sinusoidale 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(dg As File) Dim intes 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: intes = Open "/tmp/blocco_header" For Create bb.Write(intes, 0, 4) Write #intes, Lof(dg) + 36 As Integer bb.Write(intes, 8, 32) Write #intes, Lof(dg) As Integer intes.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
Ricavare un'onda sinusoidale convertendo una nota Midi nella corrispondente frequenza sonora
Quest'altra modalità prevede il calcolo della frequenza sonora da una nota Midi. Come si sa, il sistema Midi numera le note da 0 a 127.
Verrà, dunque, calcolata la frequenza di una nota Midi e dai risultanti dati audio grezzi verrà creato un file wav:
Public Sub Main() Dim fl As File Dim filegrezzo As String Dim campionamento, durata, volume As Integer Dim NotaMidi As Byte Dim dati_grezzi As Short[] filegrezzo = "/tmp/datigrezzi" ' Percorso del file che conterrà i dati audio grezzi dell'onda campionamento = 44100 ' Frequenza di campionamento dell'onda NotaMidi = 60 ' Numero della nota Midi durata = 300000 ' Durata 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 i dati audio grezzi: dati_grezzi = CreaDatiAudio(NotaMidi, durata, volume, campionamento) dati_grezzi.Write(fl, 0, dati_grezzi.Count) ' Crea il file wav finale: CreaFileWAV(fl) fl.Close Print "Fine creazione dell'onda e del file wav." End Private Function CreaDatiAudio(nota As Byte, dur As Integer, ampiezza As Integer, freq_camp As Integer) As Short[] Dim campione As Short Dim frequenza As Float Dim ciclo As Integer Dim dati_audio As New Short[] ' Ciclo per ciascun dato campione audio: For ciclo = 1 To dur ' Calcola la frequenza della nota Midi: frequenza = CalcolaFrequenza(nota) ' Calcola il dato del campione audio: campione = ampiezza * Sin(2 * Pi * ciclo * frequenza / freq_camp) dati_audio.Push(campione) Next Return dati_audio End Private Function CalcolaFrequenza(numero_nota As Byte) As Float ' Converte la nota Midi nella corrispondente frequenza sonora. ' La nota di riferimento è il "Do centrale" (hz 261,63 -- nota Midi: 60). Return 261.63 * (2 ^ (1 / 12)) ^ (numero_nota - 60) End Private Procedure CreaFileWAV(wav As File) Dim intes As File Dim bi 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: intes = Open "/tmp/blocco_header" For Create If IsNull(intes) Then Error.Raise("Impossibile scrivere il blocco d'intestazione !") bi.Write(intes, 0, 4) ' Scrive la quantità dei dati audio grezzi + 36 byte del blocco di intestazione del futuro file WAV: Write #intes, Lof(wav) + 36 As Integer bi.Write(intes, 8, 32) ' Scrive la sola quantità dei dati audio grezzi del futuro file WAV: Write #intes, Lof(wav) As Integer intes.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