Calcolare i beat per minuto (BpM) di un file audio con le funzioni esterne del API di Libaubio

Da Gambas-it.org - Wikipedia.

La libreria Libaubio è progettata per l'estrazione di particolari elementi da segnali audio.

Per poter fruire in Gambas delle risorse di LIbaubio, è necessario installare e richiamare la libreria condivisa: "libaubio.so.5.4.8 "

Mostriamo di seguito un esempio per calcolare i movimenti, ossia i beat per minuto (BpM), di un file audio.

Library "libaubio:5.4.8"

Public Struct fvec_t
  length As Integer
  data As Pointer
End Struct

' aubio_source_t * new_aubio_source(char_t * uri, uint_t samplerate, uint_t hop_size)
' Creates a new source object.
Private Extern new_aubio_source(uri As String, samplerate As Integer, hopsize As Integer) As Pointer

' uint_t aubio_source_get_samplerate(aubio_source_t * s)
' Get samplerate of source object.
Private Extern aubio_source_get_samplerate(aubio_source As Pointer) As Integer

' fvec_t * new_fvec(uint_t length)
' fvec_t buffer creation function.
Private Extern new_fvec(length As Integer) As Fvec_t

' aubio_tempo_t * new_aubio_tempo (char_t * method, uint_t buf_size, uint_t hop_size, uint_t samplerate)
' Create tempo detection object.
Private Extern new_aubio_tempo(method As String, buf_size As Integer, hopsize As Integer, samplerate As Integer) As Pointer

' void aubio_source_do(aubio_source_t * s, fvec_t * read_to, uint_t * read)
' Read monophonic vector of length hop_size from source object.
Private Extern aubio_source_do(aubio_source As Pointer, read_to As Fvec_t, readP As Pointer)

' void aubio_tempo_do (aubio_tempo_t *o, fvec_t * input, fvec_t * tempo)
' Execute tempo detection.
Private Extern aubio_tempo_do(aubio_tempo As Pointer, inputfv As Fvec_t, tempo As Fvec_t)

' smpl_t aubio_tempo_get_last_ms (aubio_tempo_t *o)
' Get the time of the latest beat detected, in milliseconds.
Private Extern aubio_tempo_get_last_ms(aubio_tempo As Pointer) As Single

' smpl_t aubio_tempo_get_last_s (aubio_tempo_t *o)
' Get the time of the latest beat detected, in seconds.
Private Extern aubio_tempo_get_last_s(aubio_tempo As Pointer) As Single

' uint_t aubio_tempo_get_last (aubio_tempo_t *o)
' Get the time of the latest beat detected, in samples.
Private Extern aubio_tempo_get_last(aubio_tempo As Pointer) As Integer

' smpl_t aubio_tempo_get_bpm(aubio_tempo_t * o)
' Get current tempo.
Private Extern aubio_tempo_get_bpm(aubio_tempo As Pointer) As Single

' smpl_t aubio_tempo_get_confidence(aubio_tempo_t * o)
' Get current tempo confidence.
Private Extern aubio_tempo_get_confidence(aubio_tempo As Pointer) As Single

' void del_aubio_tempo(aubio_tempo_t * o)
' Delete tempo detection object.
Private Extern del_aubio_tempo(aubio_tempo As Pointer)

' void del_fvec(fvec_t *s)
' fvec_t buffer deletion function.
Private Extern del_fvec(fvs As Fvec_t)

' void del_aubio_source(aubio_source_t * s)
' Close source and cleanup memory.
Private Extern del_aubio_source(aubio_source As Pointer)


Public Sub Main()

 Dim win_size, frequenza, hop_size, n_frames, letto As Integer
 Dim percorsoFile As String
 Dim source, tempus As Pointer
 Dim inp, outp As New Fvec_t

 percorsoFile = "/percorso/del/file/audio"
 win_size = 1024
 hop_size = win_size / 4
   
 source = new_aubio_source(percorsoFile, frequenza, hop_size)
 If source == 0 Then Error.Raise("Impossibile caricare il file audio !")
   
 frequenza = aubio_source_get_samplerate(source)

' Crea alcuni vettori:
 inp = new_fvec(hop_size)
 outp = new_fvec(2)
   
' Crea un oggetto Tempo:
 tempus = new_aubio_tempo("default", win_size, hop_size, frequenza)
 If tempus == 0 Then Error.Raise("Errore !")
   
 Repeat
' Inserisce nuovi dati nel vettore d'entrata:
   aubio_source_do(source, inp, VarPtr(letto))
' Esegue il tempo:
   aubio_tempo_do(tempus, inp, outp)
' Opera sui beat:
   Print "Beat a "; aubio_tempo_get_last_ms(tempus); "ms,  ", aubio_tempo_get_last_s(tempus); "s, ", "frame "; aubio_tempo_get_last(tempus); ", ", Null, aubio_tempo_get_bpm(tempus); "bpm "; Null, " con sicurezza "; aubio_tempo_get_confidence(tempus)
   n_frames += letto
 Until letto <> hop_size
   
 Print "\nLetti: "; Time(0, 0, 0, (n_frames * 1.0 / frequenza) * 1000), n_frames; " frames a "; frequenza; " Hertz ("; n_frames \ hop_size; " blocchi) dal file audio: "; percorsoFile
   
' Va in chiusura:
 del_aubio_tempo(tempus)
 del_fvec(inp)
 del_fvec(outp)
 del_aubio_source(source)
 
End


Riferimenti