Differenze tra le versioni di "Analizzare il valore RMS, il picco e il decay dei dati audio mediante il plugin 'level'usando una linea di pipeline con la funzione 'gst parse launch()'"
Riga 2: | Riga 2: | ||
<BR>Con la proprietà "''intervall'' " del plug-in "''level''" è possibile impostare il valore dell'intervallo di tempo riferito ai dati da analizzare. L'impostazione predefinita è 1/10 di secondo. Si suggerisce di non scendere al di sotto di 1 millisecondo, pena la possibilità di un blocco del sistema ! | <BR>Con la proprietà "''intervall'' " del plug-in "''level''" è possibile impostare il valore dell'intervallo di tempo riferito ai dati da analizzare. L'impostazione predefinita è 1/10 di secondo. Si suggerisce di non scendere al di sotto di 1 millisecondo, pena la possibilità di un blocco del sistema ! | ||
− | E' necessario avere installata nel proprio sistema e richiamare nel progetto Gambas la libreria dinamica condivisa: "''libgstreamer-1.0.so''" | + | E' necessario avere installata nel proprio sistema e richiamare nel progetto Gambas la libreria dinamica condivisa: "''libgstreamer-1.0.so'' " |
Mostriamo di seguito un semplice esempio, nel quale verranno analizzati i dati audio di un file WAV. L'intervallo temporale dei dati da analizzare sarà impostato a 1 millisecondo. | Mostriamo di seguito un semplice esempio, nel quale verranno analizzati i dati audio di un file WAV. L'intervallo temporale dei dati da analizzare sarà impostato a 1 millisecondo. | ||
Riga 82: | Riga 82: | ||
Dim fileaudio As String | Dim fileaudio As String | ||
− | + | fileaudio = "<FONT Color=gray>''/percorso/del/file.wav''</font>" | |
− | + | gst_init(0, 0) | |
− | + | lp = g_main_loop_new(0, False) | |
+ | If lp == 0 Then Error.Raise("Errore !") | ||
<FONT Color=gray>' ''Imposta gli elementi necessari per l'analisi del file audio:''</font> | <FONT Color=gray>' ''Imposta gli elementi necessari per l'analisi del file audio:''</font> | ||
− | + | lev = gst_parse_launch("filesrc location=" & fileaudio & " ! wavparse ! audioconvert ! <FONT Color=#B22222>level interval=1000000</font> ! audio/x-raw,channels=2 ! fakesink", 0) | |
+ | If lev == 0 Then Error.Raise("Errore !") | ||
<FONT Color=gray>' ''Poiché l'elemento "level" inserisce i propri risultati nel puntatore "GstBus", è necessario estrapolarlo dalla pipeline:''</font> | <FONT Color=gray>' ''Poiché l'elemento "level" inserisce i propri risultati nel puntatore "GstBus", è necessario estrapolarlo dalla pipeline:''</font> | ||
− | + | bs = gst_pipeline_get_bus(lev) | |
+ | If bs == 0 Then Error.Raise("Errore !") | ||
<FONT Color=gray>' ''Resta in osservazione se è pronto un messaggio nel bus, nel qual caso invoca la funzione "Gestione_messaggio_bus()":''</font> | <FONT Color=gray>' ''Resta in osservazione se è pronto un messaggio nel bus, nel qual caso invoca la funzione "Gestione_messaggio_bus()":''</font> | ||
Riga 98: | Riga 101: | ||
<FONT Color=gray>' ''Avvia l'analisi del file audio:''</font> | <FONT Color=gray>' ''Avvia l'analisi del file audio:''</font> | ||
− | + | gst_element_set_state(lev, GST_STATE_PLAYING) | |
<FONT Color=gray>' ''Avvia un loop infinito:''</font> | <FONT Color=gray>' ''Avvia un loop infinito:''</font> | ||
− | + | g_main_loop_run(lp) | |
'''End''' | '''End''' | ||
Riga 114: | Riga 117: | ||
Dim endtime As Long | Dim endtime As Long | ||
− | + | Select Case Int@(msg + 64) <FONT Color=gray>' ''GstMessage->type''</font> | |
− | + | Case GST_MESSAGE_ELEMENT | |
− | + | gst = gst_message_get_structure(msg) | |
− | + | If gst_structure_get_name(gst) = "level" Then | |
− | + | rms_arr = g_value_get_boxed(gst_structure_get_value(gst, "rms")) | |
− | + | peak_arr = g_value_get_boxed(gst_structure_get_value(gst, "peak")) | |
− | + | decay_arr = g_value_get_boxed(gst_structure_get_value(gst, "decay")) | |
− | + | channels = rms_arr.n_values | |
− | + | Print "\e[1mNumero canali audio: "; channels | |
− | + | For i = 0 To channels - 1 | |
− | + | Print "\e[0m\e[5mCanale: "; i | |
− | + | GValue = g_value_array_get_nth(rms_arr, i) | |
− | + | rms_dB = g_value_get_double(GValue) | |
− | + | ||
− | + | GValue = g_value_array_get_nth(peak_arr, i) | |
− | + | peak_dB = g_value_get_double(GValue) | |
− | + | ||
− | + | GValue = g_value_array_get_nth(decay_arr, i) | |
− | + | decay_dB = g_value_get_double(GValue) | |
− | + | Print "\e[0m RMS: "; rms_dB; " dB, picco: "; peak_dB; " dB, decay: "; decay_dB; " dB" | |
− | + | ||
<FONT Color=gray>' ''Converte da dB a normale dando un valore compreso tra 0,0 e 1,0:''</font> | <FONT Color=gray>' ''Converte da dB a normale dando un valore compreso tra 0,0 e 1,0:''</font> | ||
− | + | rms = (10 ^ (rms_dB / 20)) | |
− | + | Print " Valore rms normalizzato: "; rms | |
− | + | ||
− | + | If gst_structure_get_clock_time(gst, "endtime", VarPtr(endtime)) = False Then | |
− | + | Print "Attenzione: impossibile analizzare 'endtime' !" | |
− | + | Else | |
− | + | Print "endtime: "; CStr(Time(0, 0, 0, CInt(endtime / 1000000))) | |
− | + | Endif | |
− | + | Wait 0.01 | |
− | + | Print | |
− | + | Next | |
− | + | Endif | |
− | + | Case GST_MESSAGE_ERROR | |
− | + | Print "Errore durante l'analisi del file audio !" | |
− | + | End Select | |
− | + | Return True | |
'''End''' | '''End''' | ||
− | |||
Versione delle 16:55, 2 dic 2021
Il plug-in Level fornito dalla libreria GStreamer analizza i buffer audio in arrivo e, se la proprietà "message" è vera, esso genera un messaggio denominato "Element", dal quale è possibile estrarre alcuni valori attinente ai dati audio medesimi, come ad esempio il valore RMS, il valore di picco e il valore di decay.
Con la proprietà "intervall " del plug-in "level" è possibile impostare il valore dell'intervallo di tempo riferito ai dati da analizzare. L'impostazione predefinita è 1/10 di secondo. Si suggerisce di non scendere al di sotto di 1 millisecondo, pena la possibilità di un blocco del sistema !
E' necessario avere installata nel proprio sistema e richiamare nel progetto Gambas la libreria dinamica condivisa: "libgstreamer-1.0.so "
Mostriamo di seguito un semplice esempio, nel quale verranno analizzati i dati audio di un file WAV. L'intervallo temporale dei dati da analizzare sarà impostato a 1 millisecondo.
Library "libgstreamer-1.0" Public Struct GValueArray n_values As Integer values As Pointer End Struct Private Enum GST_STATE_VOID_PENDING = 0, GST_STATE_NULL, GST_STATE_READY, GST_STATE_PAUSED, GST_STATE_PLAYING Private Const GST_MESSAGE_ERROR As Integer = 2 Private Const GST_MESSAGE_ELEMENT As Integer = 32768 ' gst_init (int *argc, char **argv[]) ' Initializes the GStreamer library, setting up internal path lists, registering built-in elements, and loading standard plugins. Private Extern gst_init(argc As Pointer, argv As Pointer) ' GMainLoop * g_main_loop_new (GMainContext *context, gboolean is_running) ' Creates a new GMainLoop structure. Private Extern g_main_loop_new(context As Pointer, is_running As Boolean) As Pointer ' GstElement * gst_parse_launch (const gchar *pipeline_description, GError **error) ' Create a new pipeline based on command line syntax. Private Extern gst_parse_launch(description As String, gerror As Pointer) As Pointer ' GstBus * gst_pipeline_get_bus (GstPipeline *pipeline) ' Gets the GstBus of pipeline. Private Extern gst_pipeline_get_bus(pipeline As Pointer) As Pointer ' guint gst_bus_add_watch (GstBus *bus, GstBusFunc func, gpointer user_data) ' Adds a bus watch to the default main context with the default priority. Private Extern gst_bus_add_watch(bus As Pointer, func As Pointer, user_data As Pointer) As Integer ' GstStateChangeReturn gst_element_set_state(GstElement *element, GstState state) ' Sets the state of the element. Private Extern gst_element_set_state(element As Pointer, state As Integer) As Integer ' void g_main_loop_run (GMainLoop *loop) ' Runs a main loop until g_main_loop_quit() is called on the loop. Private Extern g_main_loop_run(gloop As Pointer) ' const gchar * gst_structure_get_name (const GstStructure *structure) ' Get the name of structure as a string. Private Extern gst_structure_get_name(gstructure As Pointer) As String ' const GstStructure * gst_message_get_structure (GstMessage *message) ' Access the structure of the message. Private Extern gst_message_get_structure(message As Pointer) As Pointer ' gpointer g_value_get_boxed (const GValue *value) ' Get the contents of a G_TYPE_BOXED derived GValue. Private Extern g_value_get_boxed(value As Pointer) As Pointer ' const GValue * gst_structure_get_value (const GstStructure *structure, const gchar *fieldname) ' Get the value of the field with name fieldname. Private Extern gst_structure_get_value(gstructure As Pointer, fieldname As String) As Pointer ' GValue * g_value_array_get_nth (GValueArray *value_array, guint index_) ' Return a pointer to the value at index_ containd in value_array. Private Extern g_value_array_get_nth(value_array As GValueArray, index As Integer) As Pointer ' gdouble g_value_get_double (const GValue *value) ' Get the contents of a G_TYPE_DOUBLE GValue. Private Extern g_value_get_double(value As Pointer) As Float ' gboolean gst_structure_get_clock_time (const GstStructure *structure, const gchar *fieldname, GstClockTime *value) ' Sets the clock time pointed to by value corresponding to the clock time of the given field. Private Extern gst_structure_get_clock_time(gstructure As Pointer, fieldname As String, value As Pointer) As Boolean ' void gst_object_unref(gpointer object) ' Decrements the reference count on object. Private Extern gst_object_unref(gobject As Pointer) Public Sub Main() Dim lp, lev, bs As Pointer Dim fileaudio As String fileaudio = "/percorso/del/file.wav" gst_init(0, 0) lp = g_main_loop_new(0, False) If lp == 0 Then Error.Raise("Errore !") ' Imposta gli elementi necessari per l'analisi del file audio: lev = gst_parse_launch("filesrc location=" & fileaudio & " ! wavparse ! audioconvert ! level interval=1000000 ! audio/x-raw,channels=2 ! fakesink", 0) If lev == 0 Then Error.Raise("Errore !") ' Poiché l'elemento "level" inserisce i propri risultati nel puntatore "GstBus", è necessario estrapolarlo dalla pipeline: bs = gst_pipeline_get_bus(lev) If bs == 0 Then Error.Raise("Errore !") ' Resta in osservazione se è pronto un messaggio nel bus, nel qual caso invoca la funzione "Gestione_messaggio_bus()": Print gst_bus_add_watch(bs, Gestione_messaggio_bus, lp) ' Avvia l'analisi del file audio: gst_element_set_state(lev, GST_STATE_PLAYING) ' Avvia un loop infinito: g_main_loop_run(lp) End Public Function Gestione_messaggio_bus(bus As Pointer, msg As Pointer, data As Pointer) As Boolean Dim gst, GValue As Pointer Dim rms, rms_dB, peak_dB, decay_dB As Float Dim rms_arr, peak_arr, decay_arr As GValueArray Dim channels, i As Integer Dim endtime As Long Select Case Int@(msg + 64) ' GstMessage->type Case GST_MESSAGE_ELEMENT gst = gst_message_get_structure(msg) If gst_structure_get_name(gst) = "level" Then rms_arr = g_value_get_boxed(gst_structure_get_value(gst, "rms")) peak_arr = g_value_get_boxed(gst_structure_get_value(gst, "peak")) decay_arr = g_value_get_boxed(gst_structure_get_value(gst, "decay")) channels = rms_arr.n_values Print "\e[1mNumero canali audio: "; channels For i = 0 To channels - 1 Print "\e[0m\e[5mCanale: "; i GValue = g_value_array_get_nth(rms_arr, i) rms_dB = g_value_get_double(GValue) GValue = g_value_array_get_nth(peak_arr, i) peak_dB = g_value_get_double(GValue) GValue = g_value_array_get_nth(decay_arr, i) decay_dB = g_value_get_double(GValue) Print "\e[0m RMS: "; rms_dB; " dB, picco: "; peak_dB; " dB, decay: "; decay_dB; " dB" ' Converte da dB a normale dando un valore compreso tra 0,0 e 1,0: rms = (10 ^ (rms_dB / 20)) Print " Valore rms normalizzato: "; rms If gst_structure_get_clock_time(gst, "endtime", VarPtr(endtime)) = False Then Print "Attenzione: impossibile analizzare 'endtime' !" Else Print "endtime: "; CStr(Time(0, 0, 0, CInt(endtime / 1000000))) Endif Wait 0.01 Print Next Endif Case GST_MESSAGE_ERROR Print "Errore durante l'analisi del file audio !" End Select Return True End