effects.c 34.9 KB
Newer Older
1
2
3
/*****************************************************************************
 * effects.c : Effects for the visualization system
 *****************************************************************************
4
 * Copyright (C) 2002-2009 the VideoLAN team
5
 * $Id$
6
 *
7
 * Authors: Clément Stenac <zorglub@via.ecp.fr>
8
 *          Adrien Maglo <magsoft@videolan.org>
9
10
11
12
13
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
Sam Hocevar's avatar
Sam Hocevar committed
14
 *
15
16
17
18
19
20
21
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
dionoea's avatar
dionoea committed
22
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23
24
25
26
27
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
28
29
30
31
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

32
#include <vlc_common.h>
zorglub's avatar
zorglub committed
33
34
#include <vlc_vout.h>
#include <vlc_aout.h>
Laurent Aimar's avatar
Laurent Aimar committed
35

36
37
38
#include "visual.h"
#include <math.h>

zorglub's avatar
zorglub committed
39
#include "fft.h"
40

zorglub's avatar
zorglub committed
41
#define PEAK_SPEED 1
42
#define BAR_DECREASE_SPEED 5
43

Adrien Maglo's avatar
Adrien Maglo committed
44
45
46
47
#define GRAD_ANGLE_MIN 0.2
#define GRAD_ANGLE_MAX 0.5
#define GRAD_INCR 0.01

48
49
50
51
52
53
/*****************************************************************************
 * dummy_Run
 *****************************************************************************/
int dummy_Run( visual_effect_t * p_effect, aout_instance_t *p_aout,
               aout_buffer_t * p_buffer , picture_t * p_picture)
{
54
55
    VLC_UNUSED(p_effect); VLC_UNUSED(p_aout); VLC_UNUSED(p_buffer);
    VLC_UNUSED(p_picture);
56
57
58
59
60
61
62
63
64
    return 0;
}

/*****************************************************************************
 * spectrum_Run: spectrum analyser
 *****************************************************************************/
int spectrum_Run(visual_effect_t * p_effect, aout_instance_t *p_aout,
                 aout_buffer_t * p_buffer , picture_t * p_picture)
{
65
    spectrum_data *p_data = p_effect->p_data;
zorglub's avatar
zorglub committed
66
67
68
    float p_output[FFT_BUFFER_SIZE];  /* Raw FFT Result  */
    int *height;                      /* Bar heights */
    int *peaks;                       /* Peaks */
69
70
71
    int *prev_heights;                /* Previous bar heights */
    int i_80_bands;                   /* number of bands : 80 if true else 20 */
    int i_nb_bands;                   /* number of bands : 80 or 20 */
zorglub's avatar
zorglub committed
72
    int i_band_width;                 /* width of bands */
73
    int i_start;                      /* first band horizontal position */
zorglub's avatar
zorglub committed
74
    int i_peak;                       /* Should we draw peaks ? */
zorglub's avatar
zorglub committed
75

zorglub's avatar
zorglub committed
76
77
78
    /* Horizontal scale for 20-band equalizer */
    const int xscale1[]={0,1,2,3,4,5,6,7,8,11,15,20,27,
                        36,47,62,82,107,141,184,255};
zorglub's avatar
zorglub committed
79

zorglub's avatar
zorglub committed
80
    /* Horizontal scale for 80-band equalizer */
zorglub's avatar
zorglub committed
81
    const int xscale2[] =
zorglub's avatar
zorglub committed
82
83
84
85
    {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,
     19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,
     35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,
     52,53,54,55,56,57,58,59,61,63,67,72,77,82,87,93,99,105,
86
     110,115,121,130,141,152,163,174,185,200,255};
zorglub's avatar
zorglub committed
87
    const int *xscale;
zorglub's avatar
zorglub committed
88

zorglub's avatar
zorglub committed
89
    fft_state *p_state;                 /* internal FFT data */
zorglub's avatar
zorglub committed
90

zorglub's avatar
zorglub committed
91
92
    int i , j , y , k;
    int i_line;
93
94
    int16_t p_dest[FFT_BUFFER_SIZE];      /* Adapted FFT result */
    int16_t p_buffer1[FFT_BUFFER_SIZE];   /* Buffer on which we perform
zorglub's avatar
zorglub committed
95
96
97
98
99
                                             the FFT (first channel) */

    float *p_buffl =                     /* Original buffer */
            (float*)p_buffer->p_buffer;

100
    int16_t  *p_buffs;                    /* int16_t converted buffer */
101
    int16_t  *p_s16_buff;                 /* int16_t converted buffer */
zorglub's avatar
zorglub committed
102

103
    p_s16_buff = malloc( p_buffer->i_nb_samples * p_effect->i_nb_chans * sizeof(int16_t));
zorglub's avatar
zorglub committed
104
105
    if( !p_s16_buff )
        return -1;
zorglub's avatar
zorglub committed
106

zorglub's avatar
zorglub committed
107
    p_buffs = p_s16_buff;
108
    i_80_bands = config_GetInt ( p_aout, "visual-80-bands" );
109
    i_peak     = config_GetInt ( p_aout, "visual-peaks" );
zorglub's avatar
zorglub committed
110

111
    if( i_80_bands != 0)
zorglub's avatar
zorglub committed
112
    {
113
114
        xscale = xscale2;
        i_nb_bands = 80;
zorglub's avatar
zorglub committed
115
116
117
    }
    else
    {
118
119
        xscale = xscale1;
        i_nb_bands = 20;
zorglub's avatar
zorglub committed
120
    }
zorglub's avatar
zorglub committed
121

122
    if( !p_data )
zorglub's avatar
zorglub committed
123
    {
124
        p_effect->p_data = p_data = malloc( sizeof( spectrum_data ) );
125
        if( !p_data )
zorglub's avatar
zorglub committed
126
        {
127
            free( p_s16_buff );
zorglub's avatar
zorglub committed
128
129
            return -1;
        }
130
131
132
133

        p_data->peaks = calloc( 80, sizeof(int) );
        p_data->prev_heights = calloc( 80, sizeof(int) );

134
135
        peaks = ( int * )p_data->peaks;
        prev_heights = ( int * )p_data->prev_heights;
zorglub's avatar
zorglub committed
136
137
138
    }
    else
    {
139
140
        peaks = (int *)p_data->peaks;
        prev_heights = (int *)p_data->prev_heights;
zorglub's avatar
zorglub committed
141
    }
zorglub's avatar
zorglub committed
142
143


144
145
    height = malloc( i_nb_bands * sizeof(int) );
    if( !height )
zorglub's avatar
zorglub committed
146
    {
147
        free( p_s16_buff );
zorglub's avatar
zorglub committed
148
149
        return -1;
    }
150
    /* Convert the buffer to int16_t  */
zorglub's avatar
zorglub committed
151
152
153
    /* Pasted from float32tos16.c */
    for (i = p_buffer->i_nb_samples * p_effect->i_nb_chans; i--; )
    {
154
155
156
157
158
        union { float f; int32_t i; } u;
        u.f = *p_buffl + 384.0;
        if(u.i >  0x43c07fff ) * p_buffs = 32767;
        else if ( u.i < 0x43bf8000 ) *p_buffs = -32768;
        else *p_buffs = u.i - 0x43c00000;
zorglub's avatar
zorglub committed
159

zorglub's avatar
zorglub committed
160
161
        p_buffl++ ; p_buffs++ ;
    }
162
    p_state  = visual_fft_init();
zorglub's avatar
zorglub committed
163
164
    if( !p_state)
    {
165
166
        free( height );
        free( p_s16_buff );
Christophe Mutricy's avatar
Christophe Mutricy committed
167
        msg_Err(p_aout,"unable to initialize FFT transform");
zorglub's avatar
zorglub committed
168
169
170
171
172
        return -1;
    }
    p_buffs = p_s16_buff;
    for ( i = 0 ; i < FFT_BUFFER_SIZE ; i++)
    {
173
        p_output[i]  = 0;
zorglub's avatar
zorglub committed
174
        p_buffer1[i] = *p_buffs;
175
176
177
178
179

        p_buffs += p_effect->i_nb_chans;
        if( p_buffs >= &p_s16_buff[p_buffer->i_nb_samples * p_effect->i_nb_chans] )
            p_buffs = p_s16_buff;

zorglub's avatar
zorglub committed
180
    }
zorglub's avatar
zorglub committed
181
    fft_perform( p_buffer1, p_output, p_state);
182
183
    for( i = 0; i< FFT_BUFFER_SIZE ; i++ )
        p_dest[i] = p_output[i] *  ( 2 ^ 16 ) / ( ( FFT_BUFFER_SIZE / 2 * 32768 ) ^ 2 );
zorglub's avatar
zorglub committed
184

185
186
187
188
189
    /* Compute the horizontal position of the first band */
    i_band_width = floor( p_effect->i_width / i_nb_bands);
    i_start = ( p_effect->i_width - i_band_width * i_nb_bands ) / 2;

    for ( i = 0 ; i < i_nb_bands ;i++)
zorglub's avatar
zorglub committed
190
191
    {
        /* We search the maximum on one scale */
192
        for( j = xscale[i], y = 0; j< xscale[ i + 1 ]; j++ )
zorglub's avatar
zorglub committed
193
194
195
196
197
        {
            if ( p_dest[j] > y )
                 y = p_dest[j];
        }
        /* Calculate the height of the bar */
198
        if( y != 0 )
zorglub's avatar
zorglub committed
199
        {
200
201
202
            height[i] = log( y ) * 30;
            if( height[i] > 380 )
                height[i] = 380;
zorglub's avatar
zorglub committed
203
204
        }
        else
205
            height[ i ] = 0;
zorglub's avatar
zorglub committed
206

zorglub's avatar
zorglub committed
207
208
        /* Draw the bar now */

209
        if( height[i] > peaks[i] )
zorglub's avatar
zorglub committed
210
        {
211
            peaks[i] = height[i];
zorglub's avatar
zorglub committed
212
        }
213
        else if( peaks[i] > 0 )
zorglub's avatar
zorglub committed
214
215
        {
            peaks[i] -= PEAK_SPEED;
216
            if( peaks[i] < height[i] )
zorglub's avatar
zorglub committed
217
            {
218
                peaks[i] = height[i];
zorglub's avatar
zorglub committed
219
220
221
222
223
224
225
            }
            if( peaks[i] < 0 )
            {
                peaks[i] = 0;
            }
        }

226
227
228
229
230
231
232
233
        /* Decrease the bars if needed */
        if( height[i] <= prev_heights[i] - BAR_DECREASE_SPEED )
        {
            height[i] = prev_heights[i];
            height[i] -= BAR_DECREASE_SPEED;
        }
        prev_heights[i] = height[i];

zorglub's avatar
zorglub committed
234
235
        if( peaks[i] > 0 && i_peak )
        {
zorglub's avatar
zorglub committed
236
            if( peaks[i] >= p_effect->i_height )
zorglub's avatar
zorglub committed
237
238
                peaks[i] = p_effect->i_height - 2;
            i_line = peaks[i];
zorglub's avatar
zorglub committed
239

240
            for( j = 0; j < i_band_width - 1; j++ )
zorglub's avatar
zorglub committed
241
            {
242
               for( k = 0; k < 3; k ++ )
zorglub's avatar
zorglub committed
243
244
               {
                   /* Draw the peak */
245
246
247
248
                   *(p_picture->p[0].p_pixels +
                    ( p_effect->i_height - i_line -1 -k ) *
                     p_picture->p[0].i_pitch +
                     ( i_start + i_band_width*i + j ) )
zorglub's avatar
zorglub committed
249
250
                                    = 0xff;

251
252
                   *(p_picture->p[1].p_pixels +
                    ( ( p_effect->i_height - i_line ) / 2 - 1 -k/2 ) *
zorglub's avatar
zorglub committed
253
                     p_picture->p[1].i_pitch +
254
                     ( ( i_start + i_band_width * i + j ) /2  ) )
zorglub's avatar
zorglub committed
255
                                    = 0x00;
zorglub's avatar
zorglub committed
256

257
                   if( i_line + k - 0x0f > 0 )
zorglub's avatar
zorglub committed
258
                   {
259
                       if ( i_line + k - 0x0f < 0xff )
zorglub's avatar
zorglub committed
260
                           *(p_picture->p[2].p_pixels  +
261
                            ( ( p_effect->i_height - i_line ) / 2 - 1 -k/2 ) *
zorglub's avatar
zorglub committed
262
                             p_picture->p[2].i_pitch +
263
264
                             ( ( i_start + i_band_width * i + j ) /2  ) )
                                    = ( i_line + k ) - 0x0f;
zorglub's avatar
zorglub committed
265
266
                       else
                           *(p_picture->p[2].p_pixels  +
267
                            ( ( p_effect->i_height - i_line ) / 2 - 1 -k/2 ) *
zorglub's avatar
zorglub committed
268
                             p_picture->p[2].i_pitch +
269
                             ( ( i_start + i_band_width * i + j ) /2  ) )
Sam Hocevar's avatar
Sam Hocevar committed
270
                                    = 0xff;
zorglub's avatar
zorglub committed
271
272
273
274
                   }
                   else
                   {
                        *(p_picture->p[2].p_pixels  +
275
                         ( ( p_effect->i_height - i_line ) / 2 - 1 -k/2 ) *
Sam Hocevar's avatar
Sam Hocevar committed
276
                         p_picture->p[2].i_pitch +
277
                         ( ( i_start + i_band_width * i + j ) /2  ) )
zorglub's avatar
zorglub committed
278
279
280
                               = 0x10 ;
                   }
               }
Sam Hocevar's avatar
Sam Hocevar committed
281
            }
zorglub's avatar
zorglub committed
282
        }
Sam Hocevar's avatar
Sam Hocevar committed
283

284
285
        if(height[i] > p_effect->i_height)
            height[i] = floor(p_effect->i_height );
zorglub's avatar
zorglub committed
286

287
        for( i_line = 0; i_line < height[i]; i_line++ )
zorglub's avatar
zorglub committed
288
        {
289
            for( j = 0 ; j < i_band_width - 1; j++)
zorglub's avatar
zorglub committed
290
            {
zorglub's avatar
zorglub committed
291
               *(p_picture->p[0].p_pixels +
292
293
294
                 (p_effect->i_height - i_line - 1) *
                  p_picture->p[0].i_pitch +
                  ( i_start + i_band_width*i + j ) ) = 0xff;
zorglub's avatar
zorglub committed
295

296
297
               *(p_picture->p[1].p_pixels +
                 ( ( p_effect->i_height - i_line ) / 2 - 1) *
zorglub's avatar
zorglub committed
298
                 p_picture->p[1].i_pitch +
299
                 ( ( i_start + i_band_width * i + j ) /2  ) ) = 0x00;
zorglub's avatar
zorglub committed
300

301
               if( i_line - 0x0f > 0 )
zorglub's avatar
zorglub committed
302
               {
303
                    if( i_line - 0x0f < 0xff )
zorglub's avatar
zorglub committed
304
                         *(p_picture->p[2].p_pixels  +
305
                           ( ( p_effect->i_height - i_line ) / 2 - 1) *
Sam Hocevar's avatar
Sam Hocevar committed
306
                           p_picture->p[2].i_pitch +
307
308
                           ( ( i_start + i_band_width * i + j ) /2  ) ) =
                               i_line - 0x0f;
zorglub's avatar
zorglub committed
309
310
                    else
                         *(p_picture->p[2].p_pixels  +
311
                           ( ( p_effect->i_height - i_line ) / 2  - 1) *
Sam Hocevar's avatar
Sam Hocevar committed
312
                           p_picture->p[2].i_pitch +
313
                           ( ( i_start + i_band_width * i + j ) /2  ) ) =
zorglub's avatar
zorglub committed
314
315
316
317
318
                                       0xff;
               }
               else
               {
                    *(p_picture->p[2].p_pixels  +
319
320
321
322
                      ( ( p_effect->i_height - i_line ) / 2  - 1) *
                      p_picture->p[2].i_pitch +
                      ( ( i_start + i_band_width * i + j ) /2  ) ) =
                            0x10;
zorglub's avatar
zorglub committed
323
324
325
326
               }
            }
        }
    }
Sam Hocevar's avatar
Sam Hocevar committed
327

zorglub's avatar
zorglub committed
328
    fft_close( p_state );
Sam Hocevar's avatar
Sam Hocevar committed
329

ivoire's avatar
ivoire committed
330
331
    free( p_s16_buff );
    free( height );
Sam Hocevar's avatar
Sam Hocevar committed
332

zorglub's avatar
zorglub committed
333
    return 0;
334
335
}

Sam Hocevar's avatar
Sam Hocevar committed
336

337
338
339
340
341
342
343
344
345
346
347
348
/*****************************************************************************
 * spectrometer_Run: derivative spectrum analysis
 *****************************************************************************/
int spectrometer_Run(visual_effect_t * p_effect, aout_instance_t *p_aout,
                 aout_buffer_t * p_buffer , picture_t * p_picture)
{
#define Y(R,G,B) ((uint8_t)( (R * .299) + (G * .587) + (B * .114) ))
#define U(R,G,B) ((uint8_t)( (R * -.169) + (G * -.332) + (B * .500) + 128 ))
#define V(R,G,B) ((uint8_t)( (R * .500) + (G * -.419) + (B * -.0813) + 128 ))
    float p_output[FFT_BUFFER_SIZE];  /* Raw FFT Result  */
    int *height;                      /* Bar heights */
    int *peaks;                       /* Peaks */
349
350
    int i_80_bands;                   /* number of bands : 80 if true else 20 */
    int i_nb_bands;                   /* number of bands : 80 or 20 */
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
    int i_band_width;                 /* width of bands */
    int i_separ;                      /* Should we let blanks ? */
    int i_amp;                        /* Vertical amplification */
    int i_peak;                       /* Should we draw peaks ? */

    int i_original;          /* original spectrum graphic routine */
    int i_rad;               /* radius of circle of base of bands */
    int i_sections;          /* sections of spectranalysis */
    int i_extra_width;       /* extra width on peak */
    int i_peak_height;       /* height of peak */
    int c;                   /* sentinel container of total spectral sections */
    double band_sep_angle;   /* angled separation between beginning of each band */
    double section_sep_angle;/* "   "    '     "    '    "     "    spectrum section */
    int max_band_length;     /* try not to go out of screen */
    int i_show_base;         /* Should we draw base of circle ? */
    int i_show_bands;        /* Should we draw bands ? */
    //int i_invert_bands;      /* do the bands point inward ? */
    double a;                /* for various misc angle situations in radians */
    int x,y,xx,yy;           /* various misc x/y */
    char color1;             /* V slide on a YUV color cube */
    //char color2;             /* U slide.. ?  color2 fade color ? */

    /* Horizontal scale for 20-band equalizer */
    const int xscale1[]={0,1,2,3,4,5,6,7,8,11,15,20,27,
                        36,47,62,82,107,141,184,255};

    /* Horizontal scale for 80-band equalizer */
    const int xscale2[] =
    {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,
     19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,
     35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,
     52,53,54,55,56,57,58,59,61,63,67,72,77,82,87,93,99,105,
     110,115,121,130,141,152,163,174,185,200,255};
    const int *xscale;
    const double y_scale =  3.60673760222;  /* (log 256) */

    fft_state *p_state;                 /* internal FFT data */

    int i , j , k;
    int i_line;
    int16_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 */
            (float*)p_buffer->p_buffer;

    int16_t  *p_buffs;                    /* int16_t converted buffer */
398
    int16_t  *p_s16_buff;                /* int16_t converted buffer */
399

Eric Petit's avatar
Eric Petit committed
400
401
    i_line = 0;

402
    p_s16_buff = malloc( p_buffer->i_nb_samples * p_effect->i_nb_chans * sizeof(int16_t) );
403
404
405
406
407
    if( !p_s16_buff )
        return -1;

    p_buffs = p_s16_buff;
    i_original     = config_GetInt ( p_aout, "spect-show-original" );
408
    i_80_bands     = config_GetInt ( p_aout, "spect-80-bands" );
409
410
411
412
413
414
415
416
417
418
419
    i_separ        = config_GetInt ( p_aout, "spect-separ" );
    i_amp          = config_GetInt ( p_aout, "spect-amp" );
    i_peak         = config_GetInt ( p_aout, "spect-show-peaks" );
    i_show_base    = config_GetInt ( p_aout, "spect-show-base" );
    i_show_bands   = config_GetInt ( p_aout, "spect-show-bands" );
    i_rad          = config_GetInt ( p_aout, "spect-radius" );
    i_sections     = config_GetInt ( p_aout, "spect-sections" );
    i_extra_width  = config_GetInt ( p_aout, "spect-peak-width" );
    i_peak_height  = config_GetInt ( p_aout, "spect-peak-height" );
    color1         = config_GetInt ( p_aout, "spect-color" );

420
    if( i_80_bands != 0)
421
    {
422
423
        xscale = xscale2;
        i_nb_bands = 80;
424
425
426
    }
    else
    {
427
428
        xscale = xscale1;
        i_nb_bands = 20;
429
430
431
432
    }

    if( !p_effect->p_data )
    {
433
        p_effect->p_data=(void *)malloc( 80 * sizeof(int) );
ivoire's avatar
ivoire committed
434
        if( !p_effect->p_data )
435
        {
ivoire's avatar
ivoire committed
436
            free( p_s16_buff );
437
438
439
            return -1;
        }
        peaks = (int *)p_effect->p_data;
ivoire's avatar
ivoire committed
440
        for( i = 0 ; i < i_nb_bands ; i++ )
441
442
443
444
445
446
447
448
449
450
451
452
        {
           peaks[i] = 0;
        }
    }
    else
    {
        peaks =(int *)p_effect->p_data;
    }

    height = (int *)malloc( i_nb_bands * sizeof(int) );
    if( !height)
    {
ivoire's avatar
ivoire committed
453
454
        free( p_effect->p_data );
        free( p_s16_buff );
455
456
        return -1;
    }
457

458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
    /* Convert the buffer to int16_t  */
    /* Pasted from float32tos16.c */
    for (i = p_buffer->i_nb_samples * p_effect->i_nb_chans; i--; )
    {
        union { float f; int32_t i; } u;
        u.f = *p_buffl + 384.0;
        if(u.i >  0x43c07fff ) * p_buffs = 32767;
        else if ( u.i < 0x43bf8000 ) *p_buffs = -32768;
        else *p_buffs = u.i - 0x43c00000;

        p_buffl++ ; p_buffs++ ;
    }
    p_state  = visual_fft_init();
    if( !p_state)
    {
Christophe Mutricy's avatar
Christophe Mutricy committed
473
        msg_Err(p_aout,"unable to initialize FFT transform");
ivoire's avatar
ivoire committed
474
475
476
        free( height );
        free( p_effect->p_data );
        free( p_s16_buff );
477
478
479
        return -1;
    }
    p_buffs = p_s16_buff;
480
    for ( i = 0 ; i < FFT_BUFFER_SIZE; i++)
481
482
483
    {
        p_output[i]    = 0;
        p_buffer1[i] = *p_buffs;
484
485
486
487

        p_buffs += p_effect->i_nb_chans;
        if( p_buffs >= &p_s16_buff[p_buffer->i_nb_samples * p_effect->i_nb_chans] )
            p_buffs = p_s16_buff;
488
489
    }
    fft_perform( p_buffer1, p_output, p_state);
490
491
492
493
494
    for(i = 0; i < FFT_BUFFER_SIZE; i++)
    {
        int sqrti = sqrt(p_output[i]);
        p_dest[i] = sqrti >> 8;
    }
495

496
497
    i_nb_bands *= i_sections;

498
499
500
501
502
503
504
505
506
507
508
509
    for ( i = 0 ; i< i_nb_bands/i_sections ;i++)
    {
        /* We search the maximum on one scale */
        for( j = xscale[i] , y=0 ; j< xscale[ i + 1 ] ; j++ )
        {
            if ( p_dest[j] > y )
                 y = p_dest[j];
        }
        /* Calculate the height of the bar */
        y >>=7;/* remove some noise */
        if( y != 0)
        {
510
511
512
513
            int logy = log(y);
            height[i] = logy * y_scale;
            if(height[i] > 150)
                height[i] = 150;
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
        }
        else
        {
            height[i] = 0 ;
        }

        /* Draw the bar now */
        i_band_width = floor( p_effect->i_width / (i_nb_bands/i_sections)) ;

        if( i_amp * height[i] > peaks[i])
        {
            peaks[i] = i_amp * height[i];
        }
        else if (peaks[i] > 0 )
        {
            peaks[i] -= PEAK_SPEED;
            if( peaks[i] < i_amp * height[i] )
            {
                peaks[i] = i_amp * height[i];
            }
            if( peaks[i] < 0 )
            {
                peaks[i] = 0;
            }
        }

        if( i_original != 0 )
        {
        if( peaks[i] > 0 && i_peak )
        {
            if( peaks[i] >= p_effect->i_height )
                peaks[i] = p_effect->i_height - 2;
            i_line = peaks[i];

            for( j = 0 ; j< i_band_width - i_separ; j++)
            {
               for( k = 0 ; k< 3 ; k ++)
               {
552
                   //* Draw the peak
553
                     *(p_picture->p[0].p_pixels +
554
                    (p_effect->i_height - i_line -1 -k ) *
555
556
557
558
                     p_picture->p[0].i_pitch + (i_band_width*i +j) )
                                    = 0xff;

                    *(p_picture->p[1].p_pixels +
559
                     ( ( p_effect->i_height - i_line ) / 2 -1 -k/2 ) *
560
561
562
563
564
565
566
567
                     p_picture->p[1].i_pitch +
                    ( ( i_band_width * i + j ) /2  ) )
                                    = 0x00;

                   if( 0x04 * (i_line + k ) - 0x0f > 0 )
                   {
                       if ( 0x04 * (i_line + k ) -0x0f < 0xff)
                           *(p_picture->p[2].p_pixels  +
568
                            ( ( p_effect->i_height - i_line ) / 2 - 1 -k/2 ) *
569
570
571
572
573
                             p_picture->p[2].i_pitch +
                             ( ( i_band_width * i + j ) /2  ) )
                                    = ( 0x04 * ( i_line + k ) ) -0x0f ;
                       else
                           *(p_picture->p[2].p_pixels  +
574
                            ( ( p_effect->i_height - i_line ) / 2 - 1 -k/2 ) *
575
576
577
578
579
580
581
                             p_picture->p[2].i_pitch +
                             ( ( i_band_width * i + j ) /2  ) )
                                    = 0xff;
                   }
                   else
                   {
                        *(p_picture->p[2].p_pixels  +
582
                         ( ( p_effect->i_height - i_line ) / 2 - 1 -k/2 ) *
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
                         p_picture->p[2].i_pitch +
                         ( ( i_band_width * i + j ) /2  ) )
                               = 0x10 ;
                   }
               }
            }
        }
        if(height[i] * i_amp > p_effect->i_height)
            height[i] = floor(p_effect->i_height / i_amp );

        for(i_line = 0 ; i_line < i_amp * height[i]; i_line ++ )
        {
            for( j = 0 ; j< i_band_width - i_separ ; j++)
            {
               *(p_picture->p[0].p_pixels +
598
                 (p_effect->i_height - i_line -1) *
599
600
601
                  p_picture->p[0].i_pitch + (i_band_width*i +j) ) = 0xff;

                *(p_picture->p[1].p_pixels +
602
                 ( ( p_effect->i_height - i_line ) / 2 -1) *
603
604
605
606
607
608
609
                 p_picture->p[1].i_pitch +
                 ( ( i_band_width * i + j ) /2  ) ) = 0x00;

               if( 0x04 * i_line - 0x0f > 0 )
               {
                    if( 0x04 * i_line - 0x0f < 0xff )
                         *(p_picture->p[2].p_pixels  +
610
                          ( ( p_effect->i_height - i_line ) / 2 - 1) *
611
612
613
614
615
                           p_picture->p[2].i_pitch +
                           ( ( i_band_width * i + j ) /2  ) ) =
                               ( 0x04 * i_line) -0x0f ;
                    else
                         *(p_picture->p[2].p_pixels  +
616
                          ( ( p_effect->i_height - i_line ) / 2 - 1) *
617
618
619
620
621
622
623
                           p_picture->p[2].i_pitch +
                           ( ( i_band_width * i + j ) /2  ) ) =
                                       0xff;
               }
               else
               {
                    *(p_picture->p[2].p_pixels  +
624
                     ( ( p_effect->i_height - i_line ) / 2 - 1) *
625
626
627
628
629
630
631
632
633
634
635
636
637
                     p_picture->p[2].i_pitch +
                     ( ( i_band_width * i + j ) /2  ) ) =
                            0x10 ;
               }
            }
        }
        }
    }

    band_sep_angle = 360.0 / i_nb_bands;
    section_sep_angle = 360.0 / i_sections;
    if( i_peak_height < 1 )
        i_peak_height = 1;
638
    max_band_length = p_effect->i_height / 2 - ( i_rad + i_peak_height + 1 );
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656

    i_band_width = floor( 360 / i_nb_bands - i_separ );
    if( i_band_width < 1 )
        i_band_width = 1;

    for( c = 0 ; c < i_sections ; c++ )
    for( i = 0 ; i < (i_nb_bands / i_sections) ; i++ )
    {
        /* DO A PEAK */
        if( peaks[i] > 0 && i_peak )
        {
            if( peaks[i] >= p_effect->i_height )
                peaks[i] = p_effect->i_height - 2;
            i_line = peaks[i];

            /* circular line pattern(so color blend is more visible) */
            for( j = 0 ; j < i_peak_height ; j++ )
            {
657
658
659
                //x = p_picture->p[0].i_pitch / 2;
                x = p_effect->i_width / 2;
                y = p_effect->i_height / 2;
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
                xx = x;
                yy = y;
                for( k = 0 ; k < (i_band_width + i_extra_width) ; k++ )
                {
                    x = xx;
                    y = yy;
                    a = ( (i+1) * band_sep_angle + section_sep_angle * (c+1) + k )
                        * 3.141592 / 180.0;
                    x += (double)( cos(a) * (double)( i_line + j + i_rad ) );
                    y += (double)( -sin(a) * (double)( i_line + j + i_rad ) );

                    *(p_picture->p[0].p_pixels + x + y * p_picture->p[0].i_pitch
                    ) = 255;/* Y(R,G,B); */

                    x /= 2;
                    y /= 2;

                    *(p_picture->p[1].p_pixels + x + y * p_picture->p[1].i_pitch
                    ) = 0;/* U(R,G,B); */

                    if( 0x04 * (i_line + k ) - 0x0f > 0 )
                    {
                        if ( 0x04 * (i_line + k ) -0x0f < 0xff)
                            *(p_picture->p[2].p_pixels + x + y * p_picture->p[2].i_pitch
                            ) = ( 0x04 * ( i_line + k ) ) -(color1-1);/* -V(R,G,B); */
                        else
                            *(p_picture->p[2].p_pixels + x + y * p_picture->p[2].i_pitch
                            ) = 255;/* V(R,G,B); */
                    }
                    else
                    {
                        *(p_picture->p[2].p_pixels + x + y * p_picture->p[2].i_pitch
                        ) = color1;/* V(R,G,B); */
                    }
                }
            }
        }

        if( (height[i] * i_amp) > p_effect->i_height )
            height[i] = floor( p_effect->i_height / i_amp );

        /* DO BASE OF BAND (mostly makes a circle) */
        if( i_show_base != 0 )
        {
704
705
706
            //x = p_picture->p[0].i_pitch / 2;
            x = p_effect->i_width / 2;
            y = p_effect->i_height / 2;
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741

            a =  ( (i+1) * band_sep_angle + section_sep_angle * (c+1) )
                * 3.141592 / 180.0;
            x += (double)( cos(a) * (double)i_rad );/* newb-forceful casting */
            y += (double)( -sin(a) * (double)i_rad );

            *(p_picture->p[0].p_pixels + x + y * p_picture->p[0].i_pitch
            ) = 255;/* Y(R,G,B); */

            x /= 2;
            y /= 2;

            *(p_picture->p[1].p_pixels + x + y * p_picture->p[1].i_pitch
            ) = 0;/* U(R,G,B); */

            if( 0x04 * i_line - 0x0f > 0 )
            {
                if( 0x04 * i_line -0x0f < 0xff)
                    *(p_picture->p[2].p_pixels + x + y * p_picture->p[2].i_pitch
                    ) = ( 0x04 * i_line) -(color1-1);/* -V(R,G,B); */
                else
                    *(p_picture->p[2].p_pixels + x + y * p_picture->p[2].i_pitch
                    ) = 255;/* V(R,G,B); */
            }
            else
            {
                *(p_picture->p[2].p_pixels + x + y * p_picture->p[2].i_pitch
                ) = color1;/* V(R,G,B); */
            }
        }

        /* DO A BAND */
        if( i_show_bands != 0 )
        for( j = 0 ; j < i_band_width ; j++ )
        {
742
743
            x = p_effect->i_width / 2;
            y = p_effect->i_height / 2;
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
            xx = x;
            yy = y;
            a = ( (i+1) * band_sep_angle + section_sep_angle * (c+1) + j )
                * 3.141592/180.0;

            for( k = (i_rad+1) ; k < max_band_length ; k++ )
            {
                if( (k-i_rad) > height[i] )
                    break;/* uhh.. */

                x = xx;
                y = yy;
                x += (double)( cos(a) * (double)k );/* newbed! */
                y += (double)( -sin(a) * (double)k );

                *(p_picture->p[0].p_pixels + x + y * p_picture->p[0].i_pitch
                ) = 255;

                x /= 2;
                y /= 2;

                *(p_picture->p[1].p_pixels + x + y * p_picture->p[1].i_pitch
                ) = 0;

                if( 0x04 * i_line - 0x0f > 0 )
                {
                    if ( 0x04 * i_line -0x0f < 0xff)
                        *(p_picture->p[2].p_pixels + x + y * p_picture->p[2].i_pitch
                        ) = ( 0x04 * i_line) -(color1-1);
                    else
                        *(p_picture->p[2].p_pixels + x + y * p_picture->p[2].i_pitch
                        ) = 255;
                }
                else
                {
                    *(p_picture->p[2].p_pixels + x + y * p_picture->p[2].i_pitch
                    ) = color1;
                }
            }
        }
    }

    fft_close( p_state );

ivoire's avatar
ivoire committed
788
789
    free( p_s16_buff );
    free( height );
790
791
792
793
794

    return 0;
}


795
796
797
798
799
800
/*****************************************************************************
 * scope_Run: scope effect
 *****************************************************************************/
int scope_Run(visual_effect_t * p_effect, aout_instance_t *p_aout,
              aout_buffer_t * p_buffer , picture_t * p_picture)
{
801
    VLC_UNUSED(p_aout);
802

803
804
    int i_index;
    float *p_sample ;
805
    uint8_t *ppp_area[2][3];
zorglub's avatar
zorglub committed
806

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
807
808
    for( i_index = 0 ; i_index < 2 ; i_index++ )
    {
809
        for( int j = 0 ; j < 3 ; j++ )
810
        {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
811
812
813
            ppp_area[i_index][j] =
                p_picture->p[j].p_pixels + i_index * p_picture->p[j].i_lines
                / 2 * p_picture->p[j].i_pitch;
814
        }
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
815
    }
816

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
817
    for( i_index = 0, p_sample = (float *)p_buffer->p_buffer;
818
            i_index < __MIN( p_effect->i_width, (int)p_buffer->i_nb_samples );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
819
820
821
822
823
824
825
826
827
828
829
            i_index++ )
    {
        uint8_t i_value;

        /* Left channel */
        i_value =  p_sample[p_effect->i_idx_left] * 127;
        *(ppp_area[0][0]
                + p_picture->p[0].i_pitch * i_index / p_effect->i_width
                + p_picture->p[0].i_lines * i_value / 512
                * p_picture->p[0].i_pitch) = 0xbf;
        *(ppp_area[0][1]
830
831
                + p_picture->p[1].i_pitch * i_index / p_effect->i_width
                + p_picture->p[1].i_lines * i_value / 512
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
832
833
834
835
836
837
838
839
840
841
842
843
                * p_picture->p[1].i_pitch) = 0xff;


        /* Right channel */
        i_value = p_sample[p_effect->i_idx_right] * 127;
        *(ppp_area[1][0]
                + p_picture->p[0].i_pitch * i_index / p_effect->i_width
                + p_picture->p[0].i_lines * i_value / 512
                * p_picture->p[0].i_pitch) = 0x9f;
        *(ppp_area[1][2]
                + p_picture->p[2].i_pitch * i_index / p_effect->i_width
                + p_picture->p[2].i_lines * i_value / 512
844
                * p_picture->p[2].i_pitch) = 0xdd;
845

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
846
847
848
        p_sample += p_effect->i_nb_chans;
    }
    return 0;
849
}
Adrien Maglo's avatar
Adrien Maglo committed
850
851
852


/*****************************************************************************
853
 * vuMeter_Run: vu meter effect
Adrien Maglo's avatar
Adrien Maglo committed
854
855
856
857
858
 *****************************************************************************/
int vuMeter_Run(visual_effect_t * p_effect, aout_instance_t *p_aout,
              aout_buffer_t * p_buffer , picture_t * p_picture)
{
        VLC_UNUSED(p_aout);
859
        int j;
Adrien Maglo's avatar
Adrien Maglo committed
860
861
862
863
        float i_value_l = 0;
        float i_value_r = 0;

        /* Compute the peack values */
864
        for ( unsigned i = 0 ; i < p_buffer->i_nb_samples; i++ )
Adrien Maglo's avatar
Adrien Maglo committed
865
        {
866
867
868
869
                const float *p_sample = (float *)p_buffer->p_buffer;
                float ch;

                ch = p_sample[p_effect->i_idx_left] * 256;
Adrien Maglo's avatar
Adrien Maglo committed
870
871
872
                if (ch > i_value_l)
                        i_value_l = ch;

873
                ch = p_sample[p_effect->i_idx_right] * 256;
Adrien Maglo's avatar
Adrien Maglo committed
874
875
                if (ch > i_value_r)
                        i_value_r = ch;
876
877

                p_sample += p_effect->i_nb_chans;
Adrien Maglo's avatar
Adrien Maglo committed
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
        }

        i_value_l = abs(i_value_l);
        i_value_r = abs(i_value_r);

        /* Stay under maximum value admited */
        if ( i_value_l > 200 * M_PI_2 )
                i_value_l = 200 * M_PI_2;
        if ( i_value_r > 200 * M_PI_2 )
                i_value_r = 200 * M_PI_2;

        float *i_value;

        if( !p_effect->p_data )
        {
                /* Allocate memory to save hand positions */
                p_effect->p_data = (void *)malloc( 2 * sizeof(float) );
                i_value = p_effect->p_data;
                i_value[0] = i_value_l;
                i_value[1] = i_value_r;
        }
        else
        {
                /* Make the hands go down slowly if the current values are slower
                than the previous */
                i_value = p_effect->p_data;

                if ( i_value_l > i_value[0] - 6 )
                        i_value[0] = i_value_l;
                else
                        i_value[0] = i_value[0] - 6;

                if ( i_value_r > i_value[1] - 6 )
                        i_value[1] = i_value_r;
                else
                        i_value[1] = i_value[1] - 6;
        }

        int x, y, k;
        float teta;
        float teta_grad;

        for ( j = 0; j < 2; j++ )
        {
                /* Draw the two scales */
                k = 0;
                teta_grad = GRAD_ANGLE_MIN;
925
                for ( teta = -M_PI_4; teta <= M_PI_4; teta = teta + 0.003 )
Adrien Maglo's avatar
Adrien Maglo committed
926
                {
927
                        for ( unsigned i = 140; i <= 150; i++ )
Adrien Maglo's avatar
Adrien Maglo committed
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
                        {
                                y = i * cos(teta) + 20;
                                x = i * sin(teta) + 150 + 240 * j;
                                /* Compute the last color for the gradation */
                                if (teta >= teta_grad + GRAD_INCR && teta_grad <= GRAD_ANGLE_MAX)
                                {
                                        teta_grad = teta_grad + GRAD_INCR;
                                        k = k + 5;
                                }
                                *(p_picture->p[0].p_pixels +
                                 (p_picture->p[0].i_lines - y - 1 ) * p_picture->p[0].i_pitch
                                 + x ) = 0x45;
                                *(p_picture->p[1].p_pixels +
                                 (p_picture->p[1].i_lines - y / 2 - 1 ) * p_picture->p[1].i_pitch
                                 + x / 2 ) = 0x0;
                                *(p_picture->p[2].p_pixels +
                                 (p_picture->p[2].i_lines - y / 2 - 1 ) * p_picture->p[2].i_pitch
                                 + x / 2 ) = 0x4D + k;
                        }
                }

                /* Draw the two hands */
                teta = (float)i_value[j] / 200 - M_PI_4;
951
                for ( int i = 0; i <= 150; i++ )
Adrien Maglo's avatar
Adrien Maglo committed
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
                {
                        y = i * cos(teta) + 20;
                        x = i * sin(teta) + 150 + 240 * j;
                        *(p_picture->p[0].p_pixels +
                         (p_picture->p[0].i_lines - y - 1 ) * p_picture->p[0].i_pitch
                         + x ) = 0xAD;
                        *(p_picture->p[1].p_pixels +
                         (p_picture->p[1].i_lines - y / 2 - 1 ) * p_picture->p[1].i_pitch
                         + x / 2 ) = 0xFC;
                        *(p_picture->p[2].p_pixels +
                         (p_picture->p[2].i_lines - y / 2 - 1 ) * p_picture->p[2].i_pitch
                         + x / 2 ) = 0xAC;
                }

                /* Draw the hand bases */
967
                for ( teta = -M_PI_2; teta <= M_PI_2 + 0.01; teta = teta + 0.003 )
Adrien Maglo's avatar
Adrien Maglo committed
968
                {
969
                        for ( int i = 0; i < 10; i++ )
Adrien Maglo's avatar
Adrien Maglo committed
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
                        {
                                y = i * cos(teta) + 20;
                                x = i * sin(teta) + 150 + 240 * j;
                                *(p_picture->p[0].p_pixels +
                                 (p_picture->p[0].i_lines - y - 1 ) * p_picture->p[0].i_pitch
                                 + x ) = 0xFF;
                                *(p_picture->p[1].p_pixels +
                                 (p_picture->p[1].i_lines - y / 2 - 1 ) * p_picture->p[1].i_pitch
                                 + x / 2 ) = 0x80;
                                *(p_picture->p[2].p_pixels +
                                 (p_picture->p[2].i_lines - y / 2 - 1 ) * p_picture->p[2].i_pitch
                                 + x / 2 ) = 0x80;
                        }
                }

        }

        return 0;
}