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()'
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.
E' possibile impostare il valore dell'intervallo di tempo riferito ai dati da analizzare. L'impostazione predefinita è 1/10 di secondo.
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 sà 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) ' 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) ' Poiché l'elemento "level" inserisce i propri risultati nel puntatore "GstBus", è necessario estrapolarlo dalla pipeline: bs = gst_pipeline_get_bus(lev) ' 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 "Numero canali audio: "; channels For i = 0 To channels - 1 Print "Canale: "; 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 " 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(Date(0, 0, 0, 0, 0, 0, CInt(endtime / 1000000))) Endif Sleep 0.01 Print Next Endif Case GST_MESSAGE_ERROR Print "Errore durante l'analisi del file audio !" End Select Return True End