[vlc-commits] [Git][videolan/vlc][3.0.x] 3 commits: spectrogram: fix FFT result scaling factor

Steve Lhomme (@robUx4) gitlab at videolan.org
Fri Jul 19 05:34:19 UTC 2024



Steve Lhomme pushed to branch 3.0.x at VideoLAN / VLC


Commits:
d63ebcbb by Maxime Even at 2024-07-15T15:41:13+02:00
spectrogram: fix FFT result scaling factor

This function is just a scaling operation that passes a value between 0 and
FFT_SCALING_VALUE to a value between 0 and 2^16-1.

It is therefore a power that must be applied here and not a xor.

Moreover, the initial formula was quite wrong since it was assuming that the max_input
value, which is a signed int 16, was 2^15 = 32768 where it is in fact 2^15-1=32767.

Moreover, the initial formula wasn't taking into account that, since the
output of the fft_perform is the sum of two variables which have for max value
(FFT_BUFFER_SIZE / 2 * INT16_MAX)^2, then we need to multiply the final max
value by 2.

Corrects the following compiler warnings:
	visualization/glspectrum.c:528:43: warning: result of ‘2^16’ is 18; did you mean ‘1 << 16’ (65536)? [-Wxor-used-as-pow]
	visualization/visual/effects.c:216:40: warning: result of ‘2^16’ is 18; did you mean ‘1 << 16’ (65536)? [-Wxor-used-as-pow]

Fixes #28506

Co-authored-by: Disha Baghel <bagheldisha708 at gmail.com>

(cherry picked from commit 77a08a60f72bda081d144119e4d0a57a9c3c72f6)

- - - - -
6b961756 by Maxime Even at 2024-07-15T15:41:18+02:00
spectrogram: convert int16 to unsigned for correct range

p_dest is used to set the height of the column, and it is used
as a variable defined from zero to 2^16 - 1. It is therefore
considered in the rest of the program as an unsigned int 16.
Moreover, the value that we put inside are a sum of two squared
real value, so they are necessarily positive.

(cherry picked from commit 94a8d152eadd53073305c95d221eca7623b4ed6c)

- - - - -
56d0aca2 by Maxime Even at 2024-07-15T15:41:24+02:00
spectrogram: allows better visualization of low frequencies

In some cases, Y which represents the height of a column was equal to 1
and therefore when passed through the log, the output displayed was
zero, by adding this 0.1, this allows you to see a column when y = 1
without really changing the height of each column

(cherry picked from commit c347fed91e76bd31387171e1ff67224c21194362)

- - - - -


3 changed files:

- modules/visualization/glspectrum.c
- modules/visualization/visual/effects.c
- modules/visualization/visual/fft.h


Changes:

=====================================
modules/visualization/glspectrum.c
=====================================
@@ -58,6 +58,8 @@ static void Close(vlc_object_t *);
 #define HEIGHT_TEXT N_("Video height")
 #define HEIGHT_LONGTEXT N_("The height of the visualization window, in pixels.")
 
+#define LOG_OFFSET 0.1
+
 vlc_module_begin()
     set_shortname(N_("glSpectrum"))
     set_description(N_("3D OpenGL spectrum visualization"))
@@ -381,7 +383,7 @@ static void *Thread( void *p_data )
         float p_output[FFT_BUFFER_SIZE];           /* Raw FFT Result  */
         int16_t p_buffer1[FFT_BUFFER_SIZE];        /* Buffer on which we perform
                                                       the FFT (first channel) */
-        int16_t p_dest[FFT_BUFFER_SIZE];           /* Adapted FFT result */
+        uint16_t p_dest[FFT_BUFFER_SIZE];          /* Adapted FFT result */
         float *p_buffl = (float*)block->p_buffer;  /* Original buffer */
 
         int16_t  *p_buffs;                         /* int16_t converted buffer */
@@ -445,9 +447,11 @@ static void *Thread( void *p_data )
         window_scale_in_place (p_buffer1, &wind_ctx);
         fft_perform (p_buffer1, p_output, p_state);
 
-        for (i = 0; i< FFT_BUFFER_SIZE; ++i)
-            p_dest[i] = p_output[i] *  (2 ^ 16)
-                        / ((FFT_BUFFER_SIZE / 2 * 32768) ^ 2);
+        for( i = 0; i< FFT_BUFFER_SIZE ; i++ )
+        {
+            /* Scale the output between 0 and UINT16MAX */
+            p_dest[i] = p_output[i] * UINT16_MAX / FFT_SCALING_VALUE;
+        }
 
         for (i = 0 ; i < NB_BANDS; i++)
         {
@@ -464,8 +468,9 @@ static void *Thread( void *p_data )
                 if (p_dest[j] > y)
                      y = p_dest[j];
             }
-            /* Calculate the height of the bar */
-            float new_height = y != 0 ? logf(y) * 0.4f : 0;
+            /* Calculate the height of the bar
+               This log_offset makes it possible to display low values */
+            float new_height = y != 0 ? logf( y + LOG_OFFSET ) * 0.4f : 0;
             height[i] = new_height > height[i]
                         ? new_height : height[i];
         }


=====================================
modules/visualization/visual/effects.c
=====================================
@@ -46,6 +46,8 @@
 #define GRAD_ANGLE_MAX 0.5
 #define GRAD_INCR 0.01
 
+#define LOG_OFFSET 0.1
+
 /*****************************************************************************
  * dummy_Run
  *****************************************************************************/
@@ -109,7 +111,7 @@ static int spectrum_Run(visual_effect_t * p_effect, vlc_object_t *p_aout,
 
     int i , j , y , k;
     int i_line;
-    int16_t p_dest[FFT_BUFFER_SIZE];      /* Adapted FFT result */
+    uint16_t p_dest[FFT_BUFFER_SIZE];     /* Adapted FFT result */
     int16_t p_buffer1[FFT_BUFFER_SIZE];   /* Buffer on which we perform
                                              the FFT (first channel) */
 
@@ -214,7 +216,10 @@ static int spectrum_Run(visual_effect_t * p_effect, vlc_object_t *p_aout,
     window_scale_in_place( p_buffer1, &wind_ctx );
     fft_perform( p_buffer1, p_output, p_state);
     for( i = 0; i< FFT_BUFFER_SIZE ; i++ )
-        p_dest[i] = p_output[i] *  ( 2 ^ 16 ) / ( ( FFT_BUFFER_SIZE / 2 * 32768 ) ^ 2 );
+    {
+        /* Scale the output between 0 and UINT16MAX */
+        p_dest[i] = p_output[i] * UINT16_MAX / FFT_SCALING_VALUE;
+    }
 
     /* Compute the horizontal position of the first band */
     i_band_width = floor( p_effect->i_width / i_nb_bands);
@@ -228,10 +233,11 @@ static int spectrum_Run(visual_effect_t * p_effect, vlc_object_t *p_aout,
             if ( p_dest[j] > y )
                  y = p_dest[j];
         }
-        /* Calculate the height of the bar */
+        /* Calculate the height of the bar
+           This log_offset makes it possible to display low values */
         if( y != 0 )
         {
-            height[i] = log( y ) * 30;
+            height[i] = log( y + LOG_OFFSET ) * 30;
             if( height[i] > 380 )
                 height[i] = 380;
         }
@@ -447,7 +453,7 @@ static int spectrometer_Run(visual_effect_t * p_effect, vlc_object_t *p_aout,
 
     int i , j , k;
     int i_line = 0;
-    int16_t p_dest[FFT_BUFFER_SIZE];      /* Adapted FFT result */
+    uint16_t p_dest[FFT_BUFFER_SIZE];     /* Adapted FFT result */
     int16_t p_buffer1[FFT_BUFFER_SIZE];   /* Buffer on which we perform
                                              the FFT (first channel) */
     float *p_buffl =                     /* Original buffer */


=====================================
modules/visualization/visual/fft.h
=====================================
@@ -29,6 +29,10 @@
 
 #define FFT_BUFFER_SIZE (1 << FFT_BUFFER_SIZE_LOG)
 
+#define FFT_MAX_VALUE_OUTPUT ((uint64_t)(FFT_BUFFER_SIZE/2 * INT16_MAX))
+
+#define FFT_SCALING_VALUE (FFT_MAX_VALUE_OUTPUT * FFT_MAX_VALUE_OUTPUT * 2)
+
 /* sound sample - should be an signed 16 bit value */
 typedef short int sound_sample;
 



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/b54c0adce71e36f9ae003115b7a87f3ca7122472...56d0aca2566775ca572c61a725cfbce373cf6d97

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/b54c0adce71e36f9ae003115b7a87f3ca7122472...56d0aca2566775ca572c61a725cfbce373cf6d97
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