[vlc-commits] [Git][videolan/vlc][master] jack: fix volume/mute application delay

Steve Lhomme (@robUx4) gitlab at videolan.org
Fri Jun 23 19:40:13 UTC 2023



Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
0c8d3173 by Zipdox at 2023-06-23T19:21:45+00:00
jack: fix volume/mute application delay

- - - - -


1 changed file:

- modules/audio_output/jack.c


Changes:

=====================================
modules/audio_output/jack.c
=====================================
@@ -1,10 +1,11 @@
 /*****************************************************************************
  * jack.c : JACK audio output module
  *****************************************************************************
- * Copyright (C) 2006 VLC authors and VideoLAN
+ * Copyright (C) 2006-2023 VLC authors and VideoLAN
  *
  * Authors: Cyril Deguet <asmax _at_ videolan.org>
  *          Jon Griffiths <jon_p_griffiths _At_ yahoo _DOT_ com>
+ *          Zipdox <zipdox _at_ zipdox.net>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as published by
@@ -35,6 +36,7 @@
 #include <vlc_common.h>
 #include <vlc_plugin.h>
 #include <vlc_aout.h>
+#include <vlc_configuration.h>
 
 #include <jack/jack.h>
 #include <jack/ringbuffer.h>
@@ -56,6 +58,7 @@ typedef struct
     jack_client_t  *p_jack_client;
     jack_port_t   **p_jack_ports;
     jack_sample_t **p_jack_buffers;
+    jack_sample_t *read_buffer;
     unsigned int    i_channels;
     unsigned int    i_rate;
     jack_nframes_t latency;
@@ -74,10 +77,9 @@ static void Pause        ( audio_output_t *aout, bool paused, vlc_tick_t date );
 static void Flush        ( audio_output_t *p_aout );
 static int  TimeGet      ( audio_output_t *, vlc_tick_t * );
 static int  Process      ( jack_nframes_t i_frames, void *p_arg );
+static int  Buffer_ch    ( jack_nframes_t nframes, void *p_arg );
 static int  GraphChange  ( void *p_arg );
 
-#include "audio_output/volume.h"
-
 #define AUTO_CONNECT_OPTION "jack-auto-connect"
 #define AUTO_CONNECT_TEXT N_("Automatically connect to writable clients")
 #define AUTO_CONNECT_LONGTEXT N_( \
@@ -106,7 +108,10 @@ vlc_module_begin ()
                 CONNECT_REGEX_LONGTEXT )
     add_string( "jack-name", "", JACK_NAME_TEXT, NULL)
 
-    add_sw_gain( )
+    add_float("jack-gain", 1., N_("Software gain"),
+    N_("This linear gain will be applied in software."))
+        change_float_range(0., 8.)
+
     set_callbacks( Open, Close )
 vlc_module_end ()
 
@@ -150,14 +155,13 @@ static int Start( audio_output_t *p_aout, audio_sample_format_t *restrict fmt )
 
     /* JACK only supports fl32 format */
     fmt->i_format = VLC_CODEC_FL32;
-    // TODO add buffer size callback
+
     p_sys->i_rate = fmt->i_rate = jack_get_sample_rate( p_sys->p_jack_client );
 
     p_aout->play = Play;
     p_aout->pause = Pause;
     p_aout->flush = Flush;
     p_aout->time_get = TimeGet;
-    aout_SoftVolumeStart( p_aout );
 
     p_sys->i_channels = aout_FormatNbChannels( fmt );
     aout_FormatPrepare(fmt);
@@ -176,6 +180,22 @@ static int Start( audio_output_t *p_aout, audio_sample_format_t *restrict fmt )
         goto error_out;
     }
 
+    jack_nframes_t jack_buf_size = jack_get_buffer_size( p_sys->p_jack_client );
+    p_sys->read_buffer = vlc_alloc( p_sys->i_channels * jack_buf_size, sizeof(jack_sample_t) );
+    if( p_sys->read_buffer == NULL )
+    {
+        status = VLC_ENOMEM;
+        goto error_out;
+    }
+
+    int buf_cb_set = jack_set_buffer_size_callback( p_sys->p_jack_client, Buffer_ch, p_sys );
+    if( buf_cb_set != 0 )
+    {
+        msg_Err( p_aout, "jack_set_buffer_size_callback failed");
+        status = VLC_EGENERIC;
+        goto error_out;
+    }
+
     const size_t buf_sz =
         samples_from_vlc_tick(AOUT_MAX_ADVANCE_TIME, fmt->i_rate * fmt->i_bytes_per_frame);
     p_sys->p_jack_ringbuffer = jack_ringbuffer_create( buf_sz );
@@ -274,6 +294,7 @@ error_out:
 
         free( p_sys->p_jack_ports );
         free( p_sys->p_jack_buffers );
+        free( p_sys->read_buffer );
     }
     free( psz_name );
     return status;
@@ -334,6 +355,24 @@ static void Flush(audio_output_t *p_aout)
     jack_ringbuffer_reset(rb);
 }
 
+static int VolumeSet(audio_output_t *p_aout, float vol)
+{
+    aout_sys_t * p_sys = p_aout->sys;
+    p_sys->soft_gain = vol * vol * vol;
+    aout_VolumeReport(p_aout, vol);
+    if (var_InheritBool(p_aout, "volume-save"))
+        config_PutFloat("jack-gain", p_sys->soft_gain);
+    return 0;
+}
+
+static int MuteSet(audio_output_t *p_aout, bool mute)
+{
+    aout_sys_t * p_sys = p_aout->sys;
+    p_sys->soft_mute = mute;
+    aout_MuteReport(p_aout, mute);
+    return 0;
+}
+
 static int TimeGet(audio_output_t *p_aout, vlc_tick_t *delay)
 {
     aout_sys_t * p_sys = p_aout->sys;
@@ -352,42 +391,40 @@ static int TimeGet(audio_output_t *p_aout, vlc_tick_t *delay)
  *****************************************************************************/
 int Process( jack_nframes_t i_frames, void *p_arg )
 {
-    unsigned int i, j, frames_from_rb = 0;
-    size_t bytes_read = 0;
+    unsigned int i, ch, frames_from_rb = 0;
+    size_t bytes_read;
     size_t frames_read;
     audio_output_t *p_aout = (audio_output_t*) p_arg;
     aout_sys_t *p_sys = p_aout->sys;
+    float gain = p_sys->soft_gain;
 
     /* Get the next audio data buffer unless paused */
 
     if( p_sys->paused == VLC_TICK_INVALID )
         frames_from_rb = i_frames;
 
-    /* Get the JACK buffers to write to */
-    for( i = 0; i < p_sys->i_channels; i++ )
-    {
-        p_sys->p_jack_buffers[i] = jack_port_get_buffer( p_sys->p_jack_ports[i],
-                                                         i_frames );
-    }
+    /* Read audio data from buffer */
+    jack_sample_t *samples = p_sys->read_buffer;
+    bytes_read = jack_ringbuffer_read( p_sys->p_jack_ringbuffer,
+                    (char *) samples,
+                    p_sys->i_channels * sizeof(jack_sample_t) * frames_from_rb );
+    frames_read = p_sys->soft_mute ? 0 : bytes_read / sizeof(jack_sample_t) / p_sys->i_channels;
 
     /* Copy in the audio data */
-    for( j = 0; j < frames_from_rb; j++ )
+    for( ch = 0; ch < p_sys->i_channels; ch++ )
     {
-        for( i = 0; i < p_sys->i_channels; i++ )
+        p_sys->p_jack_buffers[ch] = jack_port_get_buffer( p_sys->p_jack_ports[ch],
+                                                         i_frames );
+        /* De-interleave */
+        for( i = 0; i < frames_read; i++ )
         {
-            jack_sample_t *p_dst = p_sys->p_jack_buffers[i] + j;
-            bytes_read += jack_ringbuffer_read( p_sys->p_jack_ringbuffer,
-                    (char *) p_dst, sizeof(jack_sample_t) );
+            p_sys->p_jack_buffers[ch][i] = gain * samples[p_sys->i_channels * i + ch];
         }
-    }
 
-    /* Fill any remaining buffer with silence */
-    frames_read = (bytes_read / sizeof(jack_sample_t)) / p_sys->i_channels;
-    if( frames_read < i_frames )
-    {
-        for( i = 0; i < p_sys->i_channels; i++ )
+        /* Fill any remaining buffer with silence */
+        if (frames_read < i_frames)
         {
-            memset( p_sys->p_jack_buffers[i] + frames_read, 0,
+            memset( p_sys->p_jack_buffers[ch] + frames_read, 0,
                     sizeof( jack_sample_t ) * (i_frames - frames_read) );
         }
     }
@@ -395,6 +432,28 @@ int Process( jack_nframes_t i_frames, void *p_arg )
     return 0;
 }
 
+/*****************************************************************************
+ * Buffer_ch: callback for when the buffer size changes
+ *****************************************************************************/
+static int Buffer_ch( jack_nframes_t nframes, void *p_arg )
+{
+    audio_output_t *p_aout = (audio_output_t*) p_arg;
+    aout_sys_t *p_sys = p_aout->sys;
+
+    jack_sample_t *orig_buffer = p_sys->read_buffer;
+    p_sys->read_buffer = vlc_reallocarray( p_sys->read_buffer, p_sys->i_channels * nframes, sizeof(jack_sample_t) );
+    int status = 0;
+    if( p_sys->read_buffer == NULL )
+    {
+        msg_Err( p_aout, "failed to allocate read buffer" );
+        jack_deactivate( p_sys->p_jack_client );
+        p_sys->read_buffer = orig_buffer;
+        status = ENOMEM;
+        aout_RestartRequest(p_aout, AOUT_RESTART_OUTPUT);
+    }
+    return status;
+}
+
 /*****************************************************************************
  * GraphChange: callback when JACK reorders it's process graph.
                 We update latency information.
@@ -443,6 +502,7 @@ static void Stop( audio_output_t *p_aout )
     }
     free( p_sys->p_jack_ports );
     free( p_sys->p_jack_buffers );
+    free( p_sys->read_buffer );
     jack_ringbuffer_free( p_sys->p_jack_ringbuffer );
 }
 
@@ -453,10 +513,17 @@ static int Open(vlc_object_t *obj)
 
     if( unlikely( sys == NULL ) )
         return VLC_ENOMEM;
+
+    sys->soft_gain = var_InheritFloat(aout, "jack-gain");
+    sys->soft_mute = var_InheritBool(aout, "mute");
+    aout_VolumeReport(aout, cbrtf(sys->soft_gain));
+    aout_MuteReport(aout, sys->soft_mute);
+
     aout->sys = sys;
     aout->start = Start;
     aout->stop = Stop;
-    aout_SoftVolumeInit(aout);
+    aout->volume_set = VolumeSet;
+    aout->mute_set = MuteSet;
     return VLC_SUCCESS;
 }
 



View it on GitLab: https://code.videolan.org/videolan/vlc/-/commit/0c8d31738117b998ad7b13f252a2b5ed1c46226e

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/commit/0c8d31738117b998ad7b13f252a2b5ed1c46226e
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list