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()': differenze tra le versioni

Da Gambas-it.org - Wikipedia.
Vai alla navigazione Vai alla ricerca
Nessun oggetto della modifica
Nessun oggetto della modifica
 
(22 versioni intermedie di uno stesso utente non sono mostrate)
Riga 1: Riga 1:
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''.
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''.
<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 condivisa: "''libgstreamer-1.0.so.0.2606.0'' ".


Mostriamo di seguito un semplice esempio:
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"
  Library "libgstreamer-1.0:0.2606.0"
   
   
  Public Struct GValueArray
  Public Struct GValueArray
Riga 76: Riga 77:
   
   
   
   
  '''Public''' Sub Main()
  Public Sub Main()
    
    
   Dim lp, lev, bs As Pointer
   Dim lp, lev, bs As Pointer
   Dim fileaudio As String
   Dim fileaudio As String
    
    
  fileaudio = <FONT Color=gray>''/percorso/del/file.wav''</font>
  fileaudio = "<FONT Color=darkgreen>''/percorso/del/file.wav''</font>"
      
      
  gst_init(0, 0)
  gst_init(0, 0)
    
    
  lp = g_main_loop_new(0, False)
  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</font> ! audio/x-raw,channels=2 ! fakesink", 0)
  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)
  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 97: 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)
  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)
  g_main_loop_run(lp)
    
    
  '''End'''
  End
   
   
   
   
  '''Public''' Function Gestione_messaggio_bus(bus As Pointer, msg As Pointer, data As Pointer) As Boolean
  Public Function Gestione_messaggio_bus(bus As Pointer, msg As Pointer, data As Pointer) As Boolean
    
    
   Dim gst, GValue As Pointer
   Dim gst, GValue As Pointer
Riga 113: Riga 117:
   Dim endtime As Long
   Dim endtime As Long
    
    
  Select Case Int@(msg + 64)        <FONT Color=gray>' ''GstMessage->type''</font>
  Select Case Int@(msg + 64)        <FONT Color=gray>' ''GstMessage->type''</font>
    Case GST_MESSAGE_ELEMENT
    Case GST_MESSAGE_ELEMENT
      gst = gst_message_get_structure(msg)
      gst = gst_message_get_structure(msg)
      If gst_structure_get_name(gst) = "level" Then
      If gst_structure_get_name(gst) = "level" Then
      rms_arr = g_value_get_boxed(gst_structure_get_value(gst, "rms"))
        rms_arr = g_value_get_boxed(gst_structure_get_value(gst, "rms"))
      peak_arr = g_value_get_boxed(gst_structure_get_value(gst, "peak"))
        peak_arr = g_value_get_boxed(gst_structure_get_value(gst, "peak"))
      decay_arr = g_value_get_boxed(gst_structure_get_value(gst, "decay"))
        decay_arr = g_value_get_boxed(gst_structure_get_value(gst, "decay"))
      channels = rms_arr.n_values
        channels = rms_arr.n_values
       
        Print "\e[1mNumero canali audio: "; channels
        
        
      Print "Numero canali audio: "; channels
        For i = 0 To channels - 1
     
          Print "\e[0m\e[5mCanale: "; i
      For i = 0 To channels - 1
          GValue = g_value_array_get_nth(rms_arr, i)
        Print "Canale: "; i
          rms_dB = g_value_get_double(GValue)
        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"
            
            
        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"
       
  <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))
          rms = (10 ^ (rms_dB / 20))
        Print "    Valore rms normalizzato: "; rms
          Print "    Valore rms normalizzato: "; rms
       
         
        If gst_structure_get_clock_time(gst, "endtime", VarPtr(endtime)) = False Then
          If gst_structure_get_clock_time(gst, "endtime", VarPtr(endtime)) = False Then
          Print "Attenzione: impossibile analizzare 'endtime' !"
            Print "Attenzione: impossibile analizzare 'endtime' !"
        Else
          Else
          Print "endtime: "; CStr(Date(0, 0, 0, 0, 0, 0, CInt(endtime / 1000000)))
            Print "endtime: "; CStr(Time(0, 0, 0, CInt(endtime / 1000000)))
        Endif
          Endif
        Wait 0.001
          Wait 0.01
        Print
          Print
      Next
        Next
      Endif
      Endif
    Case GST_MESSAGE_ERROR
    Case GST_MESSAGE_ERROR
      Print "Errore durante l'analisi del file audio !"
      Print "Errore durante l'analisi del file audio !"
  End Select
  End Select
    
    
  Return True
  Return True
    
    
  '''End'''
  End
 





Versione attuale delle 12:02, 8 ott 2025

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 condivisa: "libgstreamer-1.0.so.0.2606.0 ".

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:0.2606.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


Riferimenti