Hello, below is the code for audio crossfading, it works fine despite a little noise sound in the gap, the space between 2 audio clips.<br>Am I missing some element, filter or any trick?<br><br>Thanks and regards,<br><br><br>
static void on_pad_added (GstElement *element, GstPad *pad, gpointer  data)<br>{<br>  GstPad *sinkpad = NULL;<br>  GstElement * queue = (GstElement *) data;<br><br>  /* Ahora linkeo el pad de comp con sink pad */<br>  g_print (&quot;Dynamic pad created, linking queue\n&quot;);<br>
  sinkpad = gst_element_get_static_pad (queue, &quot;sink&quot;);<br><br>  gst_pad_link (pad, sinkpad);<br><br>  gst_object_unref (sinkpad);<br><br>}<br><br>GstElement * getBin(const gchar * nomBin, GstElement * &amp;v1, GstElement *&amp;v2, GstElement * &amp;aconv1, GstElement * &amp;aconv2, GstElement * &amp;mixer)<br>
{<br><br>  GstElement * bin = gst_bin_new(nomBin);<br><br>  if (!bin)<br>  {<br>      g_printerr (&quot;No se pudo crear el bin. Saliendo\n&quot;);<br>     return NULL;<br>  }<br><br>  v1   = gst_element_factory_make (&quot;volume&quot;,&quot;vol1&quot;);<br>
  v2  = gst_element_factory_make (&quot;volume&quot;,&quot;vol2&quot;);<br>  aconv1   = gst_element_factory_make (&quot;audioconvert&quot;,&quot;aconv1&quot;);<br>  aconv2  = gst_element_factory_make (&quot;audioconvert&quot;,&quot;aconv2&quot;);<br>
<br>  mixer  = gst_element_factory_make(&quot;adder&quot;, &quot;mixer&quot;);<br><br><br>  if ((!v1) || (!v2) || (!aconv1) || (!aconv2) || (!mixer))<br>  {<br>      g_printerr (&quot;Alguno de los elementos del Bin no pudo ser creado. Saliendo\n&quot;);<br>
      return NULL;<br>  }<br><br>  // Anexamos al bin<br>  gst_bin_add_many(GST_BIN (bin),v1,v2,aconv1,aconv2,mixer, NULL);<br><br>  gst_element_link (aconv1,v1);<br>  gst_element_link (aconv2,v2);<br><br>   /* Now link volume outs to adder ins, on request */<br>
  GstPad *pad = 0;<br><br>  pad = gst_element_get_request_pad(mixer, &quot;sink%d&quot;);<br>  g_assert(pad != NULL);<br>  gst_pad_link(gst_element_get_pad(v1,&quot;src&quot;), pad);<br><br>  pad = gst_element_get_request_pad (mixer, &quot;sink%d&quot;);<br>
  g_assert(pad != NULL);<br>  gst_pad_link(gst_element_get_pad(v2, &quot;src&quot;), pad);<br><br>  g_print(&quot;hasta aqui ok!!! \n&quot;);<br><br>  return bin;<br>}<br><br>void getAndSetController(GstElement * volumen2, gdouble duracion)<br>
{<br>    GstController * ctrl = NULL;<br>    if (!(ctrl = gst_controller_new (G_OBJECT (volumen2), &quot;volume&quot;,NULL))) {<br>        cout &lt;&lt; &quot;No creo controlador..&quot; &lt;&lt; endl;<br>        GST_WARNING (&quot;No puede controlar el elemento fuente\n&quot;);<br>
        return;<br>   }<br><br>  // Todo valor GValue debe inicializarse en 0<br>  GValue val_double = { 0, };<br>  g_value_init (&amp;val_double, G_TYPE_DOUBLE);<br><br><br>  // Creo la fuente al controlador y la asocio al controlador<br>
  // Seteo modo de interpolacion<br><br>  GstInterpolationControlSource * csource = gst_interpolation_control_source_new();<br>  gst_controller_set_control_source (ctrl, &quot;volume&quot;, GST_CONTROL_SOURCE (csource));<br>
<br>  gst_interpolation_control_source_set_interpolation_mode(csource,GST_INTERPOLATE_LINEAR);<br><br>  // Seteo primer valor<br>  g_value_set_double(&amp;val_double, 0.0);<br>  gst_interpolation_control_source_set(csource,(0 * GST_MSECOND),&amp;val_double);<br>
<br>  // Seteo segundo valor<br>  g_value_set_double (&amp;val_double, 1.0);<br>  gst_interpolation_control_source_set(csource,(duracion * GST_MSECOND),&amp;val_double);<br><br><br>  g_object_unref (csource);<br><br>}<br>
<br>void addGhostPadsToBin(GstElement *aconv1, GstElement * aconv2, GstElement * mixer, GstElement* bin)<br>{<br>    /* add ghostpad */<br>  GstPad * pad1 = gst_element_get_static_pad (aconv1, &quot;sink&quot;);<br>  gst_element_add_pad(bin, gst_ghost_pad_new(&quot;alfasink1&quot;, pad1));<br>
  gst_object_unref (GST_OBJECT (pad1));<br><br>  GstPad * pad2 = gst_element_get_static_pad (aconv2, &quot;sink&quot;);<br>  gst_element_add_pad(bin, gst_ghost_pad_new(&quot;alfasink2&quot;, pad2));<br>  gst_object_unref(GST_OBJECT(pad2));<br>
<br>  GstPad * pad3 = gst_element_get_static_pad (mixer, &quot;src&quot;);<br>  gst_element_add_pad(bin, gst_ghost_pad_new(&quot;mixersrc&quot;, pad3));<br>  gst_object_unref(GST_OBJECT(pad3));<br>}<br><br>void crossTransicion(gdouble duracion, GstElement * &amp; bin,gint transicion = 1)<br>
{<br>    // devuelve el bin<br>    GstElement * volumen1, *volumen2, *aconv1,*aconv2,*mixer;<br>    volumen1 = 0;<br>    volumen2 = 0;<br>    aconv1 = 0;<br>    aconv2 = 0;<br>    mixer = 0;<br><br>    bin = getBin(&quot;bin&quot;,volumen1, volumen2,aconv1,aconv2,mixer);  // Crea el bin y los elementos<br>
<br>    getAndSetController(volumen2,duracion);<br><br>    addGhostPadsToBin(aconv1, aconv2, mixer, bin);<br><br>}<br><br>GstElement * getSetPipeline(gchar *argv[])<br>{<br>    gint dur1 = 9000; // duration (in ms) to play of first clip<br>
    gint dur2 = 8000; // duration (in ms) to play of second clip<br>    gint dur_crossfade = 500; //number of milliseconds to crossfade for<br>    GstElement *comp = 0;<br>    GstElement *pipeline, *audio1, *audio2, *op, *bin, *queue, *sink;<br>
<br>    // ejecuta 2 clips serialmente con un crosdfade entre ellos usando el elemento (GnlOlin) gnlcomposition<br>    if ((comp = gst_element_factory_make(&quot;gnlcomposition&quot;, &quot;micomposicion&quot;)) == NULL)<br>
    {<br>      printf (&quot;\n Fallo al crear gnlcomposition \n&quot;);<br>      return NULL;<br>    }<br><br>    GstCaps *caps = gst_caps_from_string(&quot;audio/x-raw-int;audio/x-raw-float&quot;);<br><br>    // Create our composition<br>
    g_object_set(G_OBJECT(comp), &quot;caps&quot;, caps, NULL);<br><br>    op = gst_element_factory_make(&quot;gnloperation&quot;, &quot;op&quot;);<br><br>    crossTransicion(dur_crossfade, bin,1);<br><br>    if (gst_bin_add (GST_BIN (op), bin) == FALSE)<br>
    {<br>      printf (&quot;\n No pudo agregar el bin a la gnloperacion op \n&quot;);<br>      return NULL;<br>    }<br><br>    g_object_set (op,&quot;start&quot;, (dur1-dur_crossfade) * GST_MSECOND,NULL);<br>    g_object_set (op,&quot;duration&quot;, dur_crossfade *  GST_MSECOND,NULL);<br>
    g_object_set (op,&quot;media-start&quot;, 0 *  GST_MSECOND,NULL);<br>    g_object_set(op,&quot;media-duration&quot;, dur_crossfade * GST_MSECOND,NULL);<br>    g_object_set(op,&quot;priority&quot;,0,NULL);<br><br>    if (gst_bin_add (GST_BIN (comp), op) == FALSE)<br>
    {<br>      printf (&quot;\n No pudo agregar la gnloperacion a la gnlcomposition \n&quot;);<br>      return NULL;<br>    }<br><br>    // configura primer clip<br><br>    if ((audio1 = gst_element_factory_make(&quot;gnlfilesource&quot;, &quot;audio1&quot;)) == NULL)<br>
    {<br>      printf (&quot;\n Falló la creacion del gnlfilesource \n&quot;);<br>      return NULL;<br>    }<br>    if (gst_bin_add (GST_BIN (comp), audio1) == FALSE)<br>    {<br>      printf (&quot;\n No pudo agregar audio1 a comp \n&quot;);<br>
      return NULL;<br>    }<br><br>    g_object_set (audio1, &quot;location&quot;, argv[1], NULL);<br>    g_object_set(audio1, &quot;uri&quot;, argv[1],NULL);<br>    g_object_set (audio1, &quot;start&quot;, 0 * GST_MSECOND, NULL);<br>
    g_object_set (audio1, &quot;duration&quot;, dur1 * GST_MSECOND, NULL);<br>    g_object_set (audio1, &quot;media-start&quot;, 0* GST_MSECOND, NULL);<br>    g_object_set (audio1, &quot;media-duration&quot;, dur1 * GST_MSECOND, NULL);<br>
    g_object_set (audio1, &quot;priority&quot;, 1,NULL);<br><br>    // crea 2º clip<br>    if ((audio2 = gst_element_factory_make(&quot;gnlfilesource&quot;, &quot;audio2&quot;)) == NULL)<br>    {<br>      printf (&quot;\n Falló la creacion del gnlfilesource \n&quot;);<br>
      return NULL;<br>    }<br><br>    if (gst_bin_add (GST_BIN (comp), audio2) == FALSE)<br>    {<br>      printf (&quot;\n No pudo agregar video2 a comp \n&quot;);<br>      return NULL;<br>    }<br><br>    g_object_set (audio2, &quot;location&quot;, argv[2], NULL);<br>
    g_object_set (audio2,&quot;uri&quot;,argv[2],NULL);<br>    g_object_set (audio2, &quot;start&quot;, (dur1-dur_crossfade) * GST_MSECOND, NULL);<br>    g_object_set (audio2, &quot;duration&quot;, dur2 * GST_MSECOND, NULL);<br>
    g_object_set (audio2, &quot;media-start&quot;, 0 * GST_MSECOND, NULL);<br>    g_object_set (audio2, &quot;media-duration&quot;, dur2 * GST_MSECOND, NULL);<br>    g_object_set (audio2, &quot;priority&quot;, 2,NULL);<br>
<br>    // setup the backend viewer<br>    queue = gst_element_factory_make(&quot;queue&quot;, &quot;queue&quot;);<br>    sink  = gst_element_factory_make(&quot;autoaudiosink&quot;, &quot;sink&quot;);<br><br>    pipeline = gst_pipeline_new (&quot;audio-player&quot;);<br>
<br>    /* Agrego elementos al pipeline */<br><br>    gst_bin_add_many (GST_BIN (pipeline),comp, queue, sink, NULL);<br><br>    g_signal_connect (comp, &quot;pad-added&quot;, G_CALLBACK (on_pad_added),queue);<br><br>    gst_element_link (queue, sink);<br>
<br>    return pipeline;<br><br>}<br><br>void startPlay(GstElement * pip)<br>{<br>    /* Set the pipeline to &quot;playing&quot; state*/<br>  gst_element_set_state (pip, GST_STATE_PLAYING);<br><br>}<br><br><br>int main(gint argc, gchar *argv[])<br>
{<br>    GMainLoop *loop = NULL;<br><br>    /* init GStreamer */<br>    gst_init (&amp;argc, &amp;argv);<br>    gst_controller_init (&amp;argc, &amp;argv);<br><br>    loop = g_main_loop_new (NULL, FALSE);<br><br>    /* chequeamos sintaxis */<br>
    if (argc != 3)<br>    {<br>        g_print (&quot;Uso: %s &lt;URI1&gt;  &lt;URI2&gt;\n&quot;, argv[0]);<br>        return -1;<br>    }<br><br>    GstElement * play = getSetPipeline(argv);<br><br><br>    GstBus *bus2 = gst_pipeline_get_bus (GST_PIPELINE (play));<br>
    gst_bus_add_watch (bus2, bus_call, loop);<br>    gst_object_unref (bus2);<br><br>    cout &lt;&lt; &quot;...PLAY&quot; &lt;&lt; endl;<br><br>    startPlay(play);<br>    GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(play), GST_DEBUG_GRAPH_SHOW_ALL,&quot;audio2&quot;);<br>
<br>    /* now run */<br>    g_main_loop_run (loop);<br><br>    /* also clean up */<br>    gst_element_set_state (play, GST_STATE_NULL);<br>    gst_object_unref (GST_OBJECT (play));<br>    return 0;<br>}<br><br><br>