Calcolare la potenza di picco e di ampiezza di un file WAV con le funzioni esterne del API di Libaudiofile
Da Gambas-it.org - Wikipedia.
Versione del 17 giu 2024 alle 16:54 di Vuott (Discussione | contributi)
La libreria Libaudiofile consente la lettura e la scrittura di file audio in diversi formati comuni, astraendo i dettagli di formati di file e di formati di dati.
Per poter fruire in Gambas delle risorse di questa libreria, sarà necessario installare la libreria condivisa: "libaudiofile.so.1.0.0 ".
Mostriamo di seguito un esempio per calcolare la potenza di picco e di ampiezza di un file WAV:
Public Struct smooth buf As Float[] lungh As Integer start As Integer n As Integer End Struct Library "libaudiofile:1.0.0" Private Const AF_DEFAULT_TRACK As Integer = 1001 Private Const AF_SAMPFMT_DOUBLE As Integer = 404 ' AFfilehandle afOpenFile (const char *filename, const char *mode, AFfilesetup setup) ' Opens a specified audio file and creates a file handle structure. Private Extern afOpenFile(filename As String, mode As String, setup As Pointer) As Pointer ' int afGetChannels (AFfilehandle, int track) ' Get the number of interleaved track from an AFfilehandle structure for an audio track. Private Extern afGetChannels(AFfile As Pointer, track As Integer) As Integer ' double afGetRate(AFfilehandle file, int track) ' Get the track sample rate for a specified audio track from an AFfilehandle structure. Private Extern afGetRate(AFfile As Pointer, track As Integer) As Float ' AFframecount afGetFrameCount (AFfilehandle file, int track) ' Get the total sample frame count for a specified audio track from an AFfilehandle structure. Private Extern afGetFrameCount(AFfile As Pointer, track As Integer) As Long ' int afSetVirtualSampleFormat (AFfilehandle, int track, int sampleFormat, int sampleWidth) ' Set the virtual data format for a specified audio track. Private Extern afSetVirtualSampleFormat(AFfile As Pointer, track As Integer, sampleFormat As Integer, sampleWidth As Integer) As Integer ' int afReadFrames (AFfilehandle, int track, void *buffer, int frameCount) ' Read sample frames from a track in an audio file. Private Extern afReadFrames(AFfile As Pointer, track As Integer, buffer As Float[], frameCount As Integer) As Integer ' int afCloseFile (AFfilehandle file) ' Closes an open audio file, updating the file if it was opened for writing. Private Extern afCloseFile(AFfile As Pointer) As Integer Public Sub Main() Dim nomefile As String Dim fl As Pointer Dim canali, windowSize, frameCount As Integer Dim i, c, winStart, winEnd, fine As Integer Dim powsmooth As New Smooth[] Dim lastWindow As Boolean Dim frames, sums As Float[] Dim frequenza, sample, pow, maxpow, durata As Float Dim livello, picco, minSample, maxSample As Float nomefile = "/percorso/del/file.wav" minSample = 1 maxSample = -1 fl = afOpenFile(nomefile, "r", 0) If fl == 0 Then Error.Raise("Impossibile aprire il file audio !") canali = afGetChannels(fl, AF_DEFAULT_TRACK) frequenza = afGetRate(fl, AF_DEFAULT_TRACK) durata = afGetFrameCount(fl, AF_DEFAULT_TRACK) / afGetRate(fl, AF_DEFAULT_TRACK) windowSize = CInt(frequenza / 100) frameCount = CInt(afGetFrameCount(fl, AF_DEFAULT_TRACK)) afSetVirtualSampleFormat(fl, AF_DEFAULT_TRACK, AF_SAMPFMT_DOUBLE, SizeOf(gb.Float)) powsmooth = New Smooth[canali] For c = 0 To canali - 1 With powsmooth[c] = New Smooth .lungh = 100 .buf = New Float[powsmooth[c].lungh * SizeOf(gb.Float)] .start = 0 .n = 0 End With Next Repeat winEnd = winStart + windowSize If winEnd >= frameCount Then winEnd = frameCount lastWindow = True Endif frames = New Float[canali * windowSize] afReadFrames(fl, AF_DEFAULT_TRACK, frames, windowSize) sums = New Float[canali] For c = 0 To canali - 1 sums[c] = 0 For i = 0 To (winEnd - winStart) - 1 sample = frames[i * canali + c] sums[c] += sample * sample If (sample > maxSample) Then maxSample = sample If (sample < minSample) Then minSample = sample Next Next ' Calcola la potenza di ciascun canale: For c = 0 To canali - 1 pow = sums[c] / (winEnd - winStart) fine = (powsmooth[c].start + powsmooth[c].n) % powsmooth[c].lungh powsmooth[c].buf[fine] = pow If powsmooth[c].n = powsmooth[c].lungh Then powsmooth[c].start = (powsmooth[c].start + 1) % powsmooth[c].lungh pow = Dati_Attenuati(powsmooth[c]) If pow > maxpow Then maxpow = pow Else Inc powsmooth[c].n Endif Next winStart += windowSize Until lastWindow For c = 0 To canali - 1 pow = Dati_Attenuati(powsmooth[c]) If pow > maxpow Then maxpow = pow Next livello = Sqr(maxpow) afCloseFile(fl) Print "File audio: "; Null, nomefile Print "Frequenza: "; Null, "Hz ";frequenza Print "Canali: "; Null, canali Print "Durata: "; Null, Cstr(Date(0, 0, 0, 0, 0, 0, durata * 1000)) Print "Livello (dB): "; Null, 20 * Log10(livello) Print "Picco-: "; Null, minSample Print "Picco+: "; Null, maxSample picco = Abs(minSample) If picco < Abs(maxSample) Then picco = Abs(maxSample) Print "Picco (dB): "; Null, 20 * Log10(picco) End Private Function Dati_Attenuati(s As Smooth) As Float Dim i As Integer Dim attenuato As Float attenuato = 0 For i = 0 To s.n - 1 attenuato += s.buf[i] Next attenuato = attenuato / s.n Return attenuato End