1 /*****************************************************************************
2 * effects.c : Effects for the visualization system
3 *****************************************************************************
4 * Copyright (C) 2002-2009 VLC authors and VideoLAN
5 * $Id: 10e0130bb6e89b9fe4d9db8d3e0d0ff32a32ec46 $
6 *
7 * Authors: Clément Stenac <zorglub@via.ecp.fr>
8 * Adrien Maglo <magsoft@videolan.org>
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2.1 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this program; if not, write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
24
25 /*****************************************************************************
26 * Preamble
27 *****************************************************************************/
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <vlc_common.h>
33 #include <vlc_picture.h>
34 #include <vlc_block.h>
35
36 #include "visual.h"
37 #include <math.h>
38
39 #include "fft.h"
40 #include "window.h"
41
42 #define PEAK_SPEED 1
43 #define BAR_DECREASE_SPEED 5
44
45 #define GRAD_ANGLE_MIN 0.2
46 #define GRAD_ANGLE_MAX 0.5
47 #define GRAD_INCR 0.01
48
49 /*****************************************************************************
50 * dummy_Run
51 *****************************************************************************/
dummy_Run(visual_effect_t * p_effect,vlc_object_t * p_aout,const block_t * p_buffer,picture_t * p_picture)52 static int dummy_Run( visual_effect_t * p_effect, vlc_object_t *p_aout,
53 const block_t * p_buffer , picture_t * p_picture)
54 {
55 VLC_UNUSED(p_effect); VLC_UNUSED(p_aout); VLC_UNUSED(p_buffer);
56 VLC_UNUSED(p_picture);
57 return 0;
58 }
59
dummy_Free(void * data)60 static void dummy_Free( void *data )
61 {
62 VLC_UNUSED(data);
63 }
64
65
66 /*****************************************************************************
67 * spectrum_Run: spectrum analyser
68 *****************************************************************************/
69 typedef struct spectrum_data
70 {
71 int *peaks;
72 int *prev_heights;
73
74 unsigned i_prev_nb_samples;
75 int16_t *p_prev_s16_buff;
76
77 window_param wind_param;
78 } spectrum_data;
79
spectrum_Run(visual_effect_t * p_effect,vlc_object_t * p_aout,const block_t * p_buffer,picture_t * p_picture)80 static int spectrum_Run(visual_effect_t * p_effect, vlc_object_t *p_aout,
81 const block_t * p_buffer , picture_t * p_picture)
82 {
83 spectrum_data *p_data = p_effect->p_data;
84 float p_output[FFT_BUFFER_SIZE]; /* Raw FFT Result */
85 int *height; /* Bar heights */
86 int *peaks; /* Peaks */
87 int *prev_heights; /* Previous bar heights */
88 int i_80_bands; /* number of bands : 80 if true else 20 */
89 int i_nb_bands; /* number of bands : 80 or 20 */
90 int i_band_width; /* width of bands */
91 int i_start; /* first band horizontal position */
92 int i_peak; /* Should we draw peaks ? */
93
94 /* Horizontal scale for 20-band equalizer */
95 const int xscale1[]={0,1,2,3,4,5,6,7,8,11,15,20,27,
96 36,47,62,82,107,141,184,255};
97
98 /* Horizontal scale for 80-band equalizer */
99 const int xscale2[] =
100 {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,
101 19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,
102 35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,
103 52,53,54,55,56,57,58,59,61,63,67,72,77,82,87,93,99,105,
104 110,115,121,130,141,152,163,174,185,200,255};
105 const int *xscale;
106
107 fft_state *p_state; /* internal FFT data */
108 DEFINE_WIND_CONTEXT( wind_ctx ); /* internal window data */
109
110 int i , j , y , k;
111 int i_line;
112 int16_t p_dest[FFT_BUFFER_SIZE]; /* Adapted FFT result */
113 int16_t p_buffer1[FFT_BUFFER_SIZE]; /* Buffer on which we perform
114 the FFT (first channel) */
115
116 float *p_buffl = /* Original buffer */
117 (float*)p_buffer->p_buffer;
118
119 int16_t *p_buffs; /* int16_t converted buffer */
120 int16_t *p_s16_buff; /* int16_t converted buffer */
121
122 if (!p_buffer->i_nb_samples) {
123 msg_Err(p_aout, "no samples yet");
124 return -1;
125 }
126
127 /* Create p_data if needed */
128 if( !p_data )
129 {
130 p_effect->p_data = p_data = malloc( sizeof( spectrum_data ) );
131 if( !p_data )
132 return -1;
133
134 p_data->peaks = calloc( 80, sizeof(int) );
135 p_data->prev_heights = calloc( 80, sizeof(int) );
136
137 p_data->i_prev_nb_samples = 0;
138 p_data->p_prev_s16_buff = NULL;
139
140 window_get_param( p_aout, &p_data->wind_param );
141 }
142 peaks = (int *)p_data->peaks;
143 prev_heights = (int *)p_data->prev_heights;
144
145 /* Allocate the buffer only if the number of samples change */
146 if( p_buffer->i_nb_samples != p_data->i_prev_nb_samples )
147 {
148 free( p_data->p_prev_s16_buff );
149 p_data->p_prev_s16_buff = vlc_alloc( p_buffer->i_nb_samples *
150 p_effect->i_nb_chans,
151 sizeof(int16_t));
152 p_data->i_prev_nb_samples = p_buffer->i_nb_samples;
153 if( !p_data->p_prev_s16_buff )
154 return -1;
155 }
156 p_buffs = p_s16_buff = p_data->p_prev_s16_buff;
157
158 i_80_bands = var_InheritInteger( p_aout, "visual-80-bands" );
159 i_peak = var_InheritInteger( p_aout, "visual-peaks" );
160
161 if( i_80_bands != 0)
162 {
163 xscale = xscale2;
164 i_nb_bands = 80;
165 }
166 else
167 {
168 xscale = xscale1;
169 i_nb_bands = 20;
170 }
171
172 height = vlc_alloc( i_nb_bands, sizeof(int) );
173 if( !height )
174 {
175 return -1;
176 }
177 /* Convert the buffer to int16_t */
178 /* Pasted from float32tos16.c */
179 for (i = p_buffer->i_nb_samples * p_effect->i_nb_chans; i--; )
180 {
181 union { float f; int32_t i; } u;
182 u.f = *p_buffl + 384.0;
183 if(u.i > 0x43c07fff ) * p_buffs = 32767;
184 else if ( u.i < 0x43bf8000 ) *p_buffs = -32768;
185 else *p_buffs = u.i - 0x43c00000;
186
187 p_buffl++ ; p_buffs++ ;
188 }
189 p_state = visual_fft_init();
190 if( !p_state)
191 {
192 free( height );
193 msg_Err(p_aout,"unable to initialize FFT transform");
194 return -1;
195 }
196 if( !window_init( FFT_BUFFER_SIZE, &p_data->wind_param, &wind_ctx ) )
197 {
198 fft_close( p_state );
199 free( height );
200 msg_Err(p_aout,"unable to initialize FFT window");
201 return -1;
202 }
203 p_buffs = p_s16_buff;
204 for ( i = 0 ; i < FFT_BUFFER_SIZE ; i++)
205 {
206 p_output[i] = 0;
207 p_buffer1[i] = *p_buffs;
208
209 p_buffs += p_effect->i_nb_chans;
210 if( p_buffs >= &p_s16_buff[p_buffer->i_nb_samples * p_effect->i_nb_chans] )
211 p_buffs = p_s16_buff;
212
213 }
214 window_scale_in_place( p_buffer1, &wind_ctx );
215 fft_perform( p_buffer1, p_output, p_state);
216 for( i = 0; i< FFT_BUFFER_SIZE ; i++ )
217 p_dest[i] = p_output[i] * ( 2 ^ 16 ) / ( ( FFT_BUFFER_SIZE / 2 * 32768 ) ^ 2 );
218
219 /* Compute the horizontal position of the first band */
220 i_band_width = floor( p_effect->i_width / i_nb_bands);
221 i_start = ( p_effect->i_width - i_band_width * i_nb_bands ) / 2;
222
223 for ( i = 0 ; i < i_nb_bands ;i++)
224 {
225 /* We search the maximum on one scale */
226 for( j = xscale[i], y = 0; j< xscale[ i + 1 ]; j++ )
227 {
228 if ( p_dest[j] > y )
229 y = p_dest[j];
230 }
231 /* Calculate the height of the bar */
232 if( y != 0 )
233 {
234 height[i] = log( y ) * 30;
235 if( height[i] > 380 )
236 height[i] = 380;
237 }
238 else
239 height[ i ] = 0;
240
241 /* Draw the bar now */
242
243 if( height[i] > peaks[i] )
244 {
245 peaks[i] = height[i];
246 }
247 else if( peaks[i] > 0 )
248 {
249 peaks[i] -= PEAK_SPEED;
250 if( peaks[i] < height[i] )
251 {
252 peaks[i] = height[i];
253 }
254 if( peaks[i] < 0 )
255 {
256 peaks[i] = 0;
257 }
258 }
259
260 /* Decrease the bars if needed */
261 if( height[i] <= prev_heights[i] - BAR_DECREASE_SPEED )
262 {
263 height[i] = prev_heights[i];
264 height[i] -= BAR_DECREASE_SPEED;
265 }
266 prev_heights[i] = height[i];
267
268 if( peaks[i] > 0 && i_peak )
269 {
270 if( peaks[i] >= p_effect->i_height )
271 peaks[i] = p_effect->i_height - 2;
272 i_line = peaks[i];
273
274 for( j = 0; j < i_band_width - 1; j++ )
275 {
276 for( k = 0; k < 3; k ++ )
277 {
278 /* Draw the peak */
279 *(p_picture->p[0].p_pixels +
280 ( p_effect->i_height - i_line -1 -k ) *
281 p_picture->p[0].i_pitch +
282 ( i_start + i_band_width*i + j ) )
283 = 0xff;
284
285 *(p_picture->p[1].p_pixels +
286 ( ( p_effect->i_height - i_line ) / 2 - 1 -k/2 ) *
287 p_picture->p[1].i_pitch +
288 ( ( i_start + i_band_width * i + j ) /2 ) )
289 = 0x00;
290
291 if( i_line + k - 0x0f > 0 )
292 {
293 if ( i_line + k - 0x0f < 0xff )
294 *(p_picture->p[2].p_pixels +
295 ( ( p_effect->i_height - i_line ) / 2 - 1 -k/2 ) *
296 p_picture->p[2].i_pitch +
297 ( ( i_start + i_band_width * i + j ) /2 ) )
298 = ( i_line + k ) - 0x0f;
299 else
300 *(p_picture->p[2].p_pixels +
301 ( ( p_effect->i_height - i_line ) / 2 - 1 -k/2 ) *
302 p_picture->p[2].i_pitch +
303 ( ( i_start + i_band_width * i + j ) /2 ) )
304 = 0xff;
305 }
306 else
307 {
308 *(p_picture->p[2].p_pixels +
309 ( ( p_effect->i_height - i_line ) / 2 - 1 -k/2 ) *
310 p_picture->p[2].i_pitch +
311 ( ( i_start + i_band_width * i + j ) /2 ) )
312 = 0x10 ;
313 }
314 }
315 }
316 }
317
318 if(height[i] > p_effect->i_height)
319 height[i] = floor(p_effect->i_height );
320
321 for( i_line = 0; i_line < height[i]; i_line++ )
322 {
323 for( j = 0 ; j < i_band_width - 1; j++)
324 {
325 *(p_picture->p[0].p_pixels +
326 (p_effect->i_height - i_line - 1) *
327 p_picture->p[0].i_pitch +
328 ( i_start + i_band_width*i + j ) ) = 0xff;
329
330 *(p_picture->p[1].p_pixels +
331 ( ( p_effect->i_height - i_line ) / 2 - 1) *
332 p_picture->p[1].i_pitch +
333 ( ( i_start + i_band_width * i + j ) /2 ) ) = 0x00;
334
335 if( i_line - 0x0f > 0 )
336 {
337 if( i_line - 0x0f < 0xff )
338 *(p_picture->p[2].p_pixels +
339 ( ( p_effect->i_height - i_line ) / 2 - 1) *
340 p_picture->p[2].i_pitch +
341 ( ( i_start + i_band_width * i + j ) /2 ) ) =
342 i_line - 0x0f;
343 else
344 *(p_picture->p[2].p_pixels +
345 ( ( p_effect->i_height - i_line ) / 2 - 1) *
346 p_picture->p[2].i_pitch +
347 ( ( i_start + i_band_width * i + j ) /2 ) ) =
348 0xff;
349 }
350 else
351 {
352 *(p_picture->p[2].p_pixels +
353 ( ( p_effect->i_height - i_line ) / 2 - 1) *
354 p_picture->p[2].i_pitch +
355 ( ( i_start + i_band_width * i + j ) /2 ) ) =
356 0x10;
357 }
358 }
359 }
360 }
361
362 window_close( &wind_ctx );
363
364 fft_close( p_state );
365
366 free( height );
367
368 return 0;
369 }
370
spectrum_Free(void * data)371 static void spectrum_Free( void *data )
372 {
373 spectrum_data *p_data = data;
374
375 if( p_data != NULL )
376 {
377 free( p_data->peaks );
378 free( p_data->prev_heights );
379 free( p_data->p_prev_s16_buff );
380 free( p_data );
381 }
382 }
383
384
385 /*****************************************************************************
386 * spectrometer_Run: derivative spectrum analysis
387 *****************************************************************************/
388 typedef struct
389 {
390 int *peaks;
391
392 unsigned i_prev_nb_samples;
393 int16_t *p_prev_s16_buff;
394
395 window_param wind_param;
396 } spectrometer_data;
397
spectrometer_Run(visual_effect_t * p_effect,vlc_object_t * p_aout,const block_t * p_buffer,picture_t * p_picture)398 static int spectrometer_Run(visual_effect_t * p_effect, vlc_object_t *p_aout,
399 const block_t * p_buffer , picture_t * p_picture)
400 {
401 #define Y(R,G,B) ((uint8_t)( (R * .299) + (G * .587) + (B * .114) ))
402 #define U(R,G,B) ((uint8_t)( (R * -.169) + (G * -.332) + (B * .500) + 128 ))
403 #define V(R,G,B) ((uint8_t)( (R * .500) + (G * -.419) + (B * -.0813) + 128 ))
404 float p_output[FFT_BUFFER_SIZE]; /* Raw FFT Result */
405 int *height; /* Bar heights */
406 int *peaks; /* Peaks */
407 int i_80_bands; /* number of bands : 80 if true else 20 */
408 int i_nb_bands; /* number of bands : 80 or 20 */
409 int i_band_width; /* width of bands */
410 int i_separ; /* Should we let blanks ? */
411 int i_amp; /* Vertical amplification */
412 int i_peak; /* Should we draw peaks ? */
413
414 int i_original; /* original spectrum graphic routine */
415 int i_rad; /* radius of circle of base of bands */
416 int i_sections; /* sections of spectranalysis */
417 int i_extra_width; /* extra width on peak */
418 int i_peak_height; /* height of peak */
419 int c; /* sentinel container of total spectral sections */
420 double band_sep_angle; /* angled separation between beginning of each band */
421 double section_sep_angle;/* " " ' " ' " " spectrum section */
422 int max_band_length; /* try not to go out of screen */
423 int i_show_base; /* Should we draw base of circle ? */
424 int i_show_bands; /* Should we draw bands ? */
425 //int i_invert_bands; /* do the bands point inward ? */
426 double a; /* for various misc angle situations in radians */
427 int x,y,xx,yy; /* various misc x/y */
428 char color1; /* V slide on a YUV color cube */
429 //char color2; /* U slide.. ? color2 fade color ? */
430
431 /* Horizontal scale for 20-band equalizer */
432 const int xscale1[]={0,1,2,3,4,5,6,7,8,11,15,20,27,
433 36,47,62,82,107,141,184,255};
434
435 /* Horizontal scale for 80-band equalizer */
436 const int xscale2[] =
437 {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,
438 19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,
439 35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,
440 52,53,54,55,56,57,58,59,61,63,67,72,77,82,87,93,99,105,
441 110,115,121,130,141,152,163,174,185,200,255};
442 const int *xscale;
443 const double y_scale = 3.60673760222; /* (log 256) */
444
445 fft_state *p_state; /* internal FFT data */
446 DEFINE_WIND_CONTEXT( wind_ctx ); /* internal window data */
447
448 int i , j , k;
449 int i_line = 0;
450 int16_t p_dest[FFT_BUFFER_SIZE]; /* Adapted FFT result */
451 int16_t p_buffer1[FFT_BUFFER_SIZE]; /* Buffer on which we perform
452 the FFT (first channel) */
453 float *p_buffl = /* Original buffer */
454 (float*)p_buffer->p_buffer;
455
456 int16_t *p_buffs; /* int16_t converted buffer */
457 int16_t *p_s16_buff; /* int16_t converted buffer */
458
459 if (!p_buffer->i_nb_samples) {
460 msg_Err(p_aout, "no samples yet");
461 return -1;
462 }
463
464 /* Create the data struct if needed */
465 spectrometer_data *p_data = p_effect->p_data;
466 if( !p_data )
467 {
468 p_data = malloc( sizeof(spectrometer_data) );
469 if( !p_data )
470 return -1;
471 p_data->peaks = calloc( 80, sizeof(int) );
472 if( !p_data->peaks )
473 {
474 free( p_data );
475 return -1;
476 }
477 p_data->i_prev_nb_samples = 0;
478 p_data->p_prev_s16_buff = NULL;
479 window_get_param( p_aout, &p_data->wind_param );
480 p_effect->p_data = (void*)p_data;
481 }
482 peaks = p_data->peaks;
483
484 /* Allocate the buffer only if the number of samples change */
485 if( p_buffer->i_nb_samples != p_data->i_prev_nb_samples )
486 {
487 free( p_data->p_prev_s16_buff );
488 p_data->p_prev_s16_buff = vlc_alloc( p_buffer->i_nb_samples *
489 p_effect->i_nb_chans,
490 sizeof(int16_t));
491 p_data->i_prev_nb_samples = p_buffer->i_nb_samples;
492 if( !p_data->p_prev_s16_buff )
493 return -1;
494 }
495 p_buffs = p_s16_buff = p_data->p_prev_s16_buff;
496
497 i_original = var_InheritInteger( p_aout, "spect-show-original" );
498 i_80_bands = var_InheritInteger( p_aout, "spect-80-bands" );
499 i_separ = var_InheritInteger( p_aout, "spect-separ" );
500 i_amp = var_InheritInteger( p_aout, "spect-amp" );
501 i_peak = var_InheritInteger( p_aout, "spect-show-peaks" );
502 i_show_base = var_InheritInteger( p_aout, "spect-show-base" );
503 i_show_bands = var_InheritInteger( p_aout, "spect-show-bands" );
504 i_rad = var_InheritInteger( p_aout, "spect-radius" );
505 i_sections = var_InheritInteger( p_aout, "spect-sections" );
506 i_extra_width = var_InheritInteger( p_aout, "spect-peak-width" );
507 i_peak_height = var_InheritInteger( p_aout, "spect-peak-height" );
508 color1 = var_InheritInteger( p_aout, "spect-color" );
509
510 if( i_80_bands != 0)
511 {
512 xscale = xscale2;
513 i_nb_bands = 80;
514 }
515 else
516 {
517 xscale = xscale1;
518 i_nb_bands = 20;
519 }
520
521 height = vlc_alloc( i_nb_bands, sizeof(int) );
522 if( !height)
523 return -1;
524
525 /* Convert the buffer to int16_t */
526 /* Pasted from float32tos16.c */
527 for (i = p_buffer->i_nb_samples * p_effect->i_nb_chans; i--; )
528 {
529 union { float f; int32_t i; } u;
530 u.f = *p_buffl + 384.0;
531 if(u.i > 0x43c07fff ) * p_buffs = 32767;
532 else if ( u.i < 0x43bf8000 ) *p_buffs = -32768;
533 else *p_buffs = u.i - 0x43c00000;
534
535 p_buffl++ ; p_buffs++ ;
536 }
537 p_state = visual_fft_init();
538 if( !p_state)
539 {
540 msg_Err(p_aout,"unable to initialize FFT transform");
541 free( height );
542 return -1;
543 }
544 if( !window_init( FFT_BUFFER_SIZE, &p_data->wind_param, &wind_ctx ) )
545 {
546 fft_close( p_state );
547 free( height );
548 msg_Err(p_aout,"unable to initialize FFT window");
549 return -1;
550 }
551 p_buffs = p_s16_buff;
552 for ( i = 0 ; i < FFT_BUFFER_SIZE; i++)
553 {
554 p_output[i] = 0;
555 p_buffer1[i] = *p_buffs;
556
557 p_buffs += p_effect->i_nb_chans;
558 if( p_buffs >= &p_s16_buff[p_buffer->i_nb_samples * p_effect->i_nb_chans] )
559 p_buffs = p_s16_buff;
560 }
561 window_scale_in_place( p_buffer1, &wind_ctx );
562 fft_perform( p_buffer1, p_output, p_state);
563 for(i = 0; i < FFT_BUFFER_SIZE; i++)
564 {
565 int sqrti = sqrt(p_output[i]);
566 p_dest[i] = sqrti >> 8;
567 }
568
569 i_nb_bands *= i_sections;
570
571 for ( i = 0 ; i< i_nb_bands/i_sections ;i++)
572 {
573 /* We search the maximum on one scale */
574 for( j = xscale[i] , y=0 ; j< xscale[ i + 1 ] ; j++ )
575 {
576 if ( p_dest[j] > y )
577 y = p_dest[j];
578 }
579 /* Calculate the height of the bar */
580 y >>=7;/* remove some noise */
581 if( y != 0)
582 {
583 int logy = log(y);
584 height[i] = logy * y_scale;
585 if(height[i] > 150)
586 height[i] = 150;
587 }
588 else
589 {
590 height[i] = 0 ;
591 }
592
593 /* Draw the bar now */
594 i_band_width = floor( p_effect->i_width / (i_nb_bands/i_sections)) ;
595
596 if( i_amp * height[i] > peaks[i])
597 {
598 peaks[i] = i_amp * height[i];
599 }
600 else if (peaks[i] > 0 )
601 {
602 peaks[i] -= PEAK_SPEED;
603 if( peaks[i] < i_amp * height[i] )
604 {
605 peaks[i] = i_amp * height[i];
606 }
607 if( peaks[i] < 0 )
608 {
609 peaks[i] = 0;
610 }
611 }
612
613 if( i_original != 0 )
614 {
615 if( peaks[i] > 0 && i_peak )
616 {
617 if( peaks[i] >= p_effect->i_height )
618 peaks[i] = p_effect->i_height - 2;
619 i_line = peaks[i];
620
621 for( j = 0 ; j< i_band_width - i_separ; j++)
622 {
623 for( k = 0 ; k< 3 ; k ++)
624 {
625 //* Draw the peak
626 *(p_picture->p[0].p_pixels +
627 (p_effect->i_height - i_line -1 -k ) *
628 p_picture->p[0].i_pitch + (i_band_width*i +j) )
629 = 0xff;
630
631 *(p_picture->p[1].p_pixels +
632 ( ( p_effect->i_height - i_line ) / 2 -1 -k/2 ) *
633 p_picture->p[1].i_pitch +
634 ( ( i_band_width * i + j ) /2 ) )
635 = 0x00;
636
637 if( 0x04 * (i_line + k ) - 0x0f > 0 )
638 {
639 if ( 0x04 * (i_line + k ) -0x0f < 0xff)
640 *(p_picture->p[2].p_pixels +
641 ( ( p_effect->i_height - i_line ) / 2 - 1 -k/2 ) *
642 p_picture->p[2].i_pitch +
643 ( ( i_band_width * i + j ) /2 ) )
644 = ( 0x04 * ( i_line + k ) ) -0x0f ;
645 else
646 *(p_picture->p[2].p_pixels +
647 ( ( p_effect->i_height - i_line ) / 2 - 1 -k/2 ) *
648 p_picture->p[2].i_pitch +
649 ( ( i_band_width * i + j ) /2 ) )
650 = 0xff;
651 }
652 else
653 {
654 *(p_picture->p[2].p_pixels +
655 ( ( p_effect->i_height - i_line ) / 2 - 1 -k/2 ) *
656 p_picture->p[2].i_pitch +
657 ( ( i_band_width * i + j ) /2 ) )
658 = 0x10 ;
659 }
660 }
661 }
662 }
663 if(height[i] * i_amp > p_effect->i_height)
664 height[i] = floor(p_effect->i_height / i_amp );
665
666 for(i_line = 0 ; i_line < i_amp * height[i]; i_line ++ )
667 {
668 for( j = 0 ; j< i_band_width - i_separ ; j++)
669 {
670 *(p_picture->p[0].p_pixels +
671 (p_effect->i_height - i_line -1) *
672 p_picture->p[0].i_pitch + (i_band_width*i +j) ) = 0xff;
673
674 *(p_picture->p[1].p_pixels +
675 ( ( p_effect->i_height - i_line ) / 2 -1) *
676 p_picture->p[1].i_pitch +
677 ( ( i_band_width * i + j ) /2 ) ) = 0x00;
678
679 if( 0x04 * i_line - 0x0f > 0 )
680 {
681 if( 0x04 * i_line - 0x0f < 0xff )
682 *(p_picture->p[2].p_pixels +
683 ( ( p_effect->i_height - i_line ) / 2 - 1) *
684 p_picture->p[2].i_pitch +
685 ( ( i_band_width * i + j ) /2 ) ) =
686 ( 0x04 * i_line) -0x0f ;
687 else
688 *(p_picture->p[2].p_pixels +
689 ( ( p_effect->i_height - i_line ) / 2 - 1) *
690 p_picture->p[2].i_pitch +
691 ( ( i_band_width * i + j ) /2 ) ) =
692 0xff;
693 }
694 else
695 {
696 *(p_picture->p[2].p_pixels +
697 ( ( p_effect->i_height - i_line ) / 2 - 1) *
698 p_picture->p[2].i_pitch +
699 ( ( i_band_width * i + j ) /2 ) ) =
700 0x10 ;
701 }
702 }
703 }
704 }
705 }
706
707 band_sep_angle = 360.0 / i_nb_bands;
708 section_sep_angle = 360.0 / i_sections;
709 if( i_peak_height < 1 )
710 i_peak_height = 1;
711 max_band_length = p_effect->i_height / 2 - ( i_rad + i_peak_height + 1 );
712
713 i_band_width = floor( 360 / i_nb_bands - i_separ );
714 if( i_band_width < 1 )
715 i_band_width = 1;
716
717 for( c = 0 ; c < i_sections ; c++ )
718 for( i = 0 ; i < (i_nb_bands / i_sections) ; i++ )
719 {
720 /* DO A PEAK */
721 if( peaks[i] > 0 && i_peak )
722 {
723 if( peaks[i] >= p_effect->i_height )
724 peaks[i] = p_effect->i_height - 2;
725 i_line = peaks[i];
726
727 /* circular line pattern(so color blend is more visible) */
728 for( j = 0 ; j < i_peak_height ; j++ )
729 {
730 //x = p_picture->p[0].i_pitch / 2;
731 x = p_effect->i_width / 2;
732 y = p_effect->i_height / 2;
733 xx = x;
734 yy = y;
735 for( k = 0 ; k < (i_band_width + i_extra_width) ; k++ )
736 {
737 x = xx;
738 y = yy;
739 a = ( (i+1) * band_sep_angle + section_sep_angle * (c+1) + k )
740 * 3.141592 / 180.0;
741 x += (double)( cos(a) * (double)( i_line + j + i_rad ) );
742 y += (double)( -sin(a) * (double)( i_line + j + i_rad ) );
743
744 *(p_picture->p[0].p_pixels + x + y * p_picture->p[0].i_pitch
745 ) = 255;/* Y(R,G,B); */
746
747 x /= 2;
748 y /= 2;
749
750 *(p_picture->p[1].p_pixels + x + y * p_picture->p[1].i_pitch
751 ) = 0;/* U(R,G,B); */
752
753 if( 0x04 * (i_line + k ) - 0x0f > 0 )
754 {
755 if ( 0x04 * (i_line + k ) -0x0f < 0xff)
756 *(p_picture->p[2].p_pixels + x + y * p_picture->p[2].i_pitch
757 ) = ( 0x04 * ( i_line + k ) ) -(color1-1);/* -V(R,G,B); */
758 else
759 *(p_picture->p[2].p_pixels + x + y * p_picture->p[2].i_pitch
760 ) = 255;/* V(R,G,B); */
761 }
762 else
763 {
764 *(p_picture->p[2].p_pixels + x + y * p_picture->p[2].i_pitch
765 ) = color1;/* V(R,G,B); */
766 }
767 }
768 }
769 }
770
771 if( (height[i] * i_amp) > p_effect->i_height )
772 height[i] = floor( p_effect->i_height / i_amp );
773
774 /* DO BASE OF BAND (mostly makes a circle) */
775 if( i_show_base != 0 )
776 {
777 //x = p_picture->p[0].i_pitch / 2;
778 x = p_effect->i_width / 2;
779 y = p_effect->i_height / 2;
780
781 a = ( (i+1) * band_sep_angle + section_sep_angle * (c+1) )
782 * 3.141592 / 180.0;
783 x += (double)( cos(a) * (double)i_rad );/* newb-forceful casting */
784 y += (double)( -sin(a) * (double)i_rad );
785
786 *(p_picture->p[0].p_pixels + x + y * p_picture->p[0].i_pitch
787 ) = 255;/* Y(R,G,B); */
788
789 x /= 2;
790 y /= 2;
791
792 *(p_picture->p[1].p_pixels + x + y * p_picture->p[1].i_pitch
793 ) = 0;/* U(R,G,B); */
794
795 if( 0x04 * i_line - 0x0f > 0 )
796 {
797 if( 0x04 * i_line -0x0f < 0xff)
798 *(p_picture->p[2].p_pixels + x + y * p_picture->p[2].i_pitch
799 ) = ( 0x04 * i_line) -(color1-1);/* -V(R,G,B); */
800 else
801 *(p_picture->p[2].p_pixels + x + y * p_picture->p[2].i_pitch
802 ) = 255;/* V(R,G,B); */
803 }
804 else
805 {
806 *(p_picture->p[2].p_pixels + x + y * p_picture->p[2].i_pitch
807 ) = color1;/* V(R,G,B); */
808 }
809 }
810
811 /* DO A BAND */
812 if( i_show_bands != 0 )
813 for( j = 0 ; j < i_band_width ; j++ )
814 {
815 x = p_effect->i_width / 2;
816 y = p_effect->i_height / 2;
817 xx = x;
818 yy = y;
819 a = ( (i+1) * band_sep_angle + section_sep_angle * (c+1) + j )
820 * 3.141592/180.0;
821
822 for( k = (i_rad+1) ; k < max_band_length ; k++ )
823 {
824 if( (k-i_rad) > height[i] )
825 break;/* uhh.. */
826
827 x = xx;
828 y = yy;
829 x += (double)( cos(a) * (double)k );/* newbed! */
830 y += (double)( -sin(a) * (double)k );
831
832 *(p_picture->p[0].p_pixels + x + y * p_picture->p[0].i_pitch
833 ) = 255;
834
835 x /= 2;
836 y /= 2;
837
838 *(p_picture->p[1].p_pixels + x + y * p_picture->p[1].i_pitch
839 ) = 0;
840
841 if( 0x04 * i_line - 0x0f > 0 )
842 {
843 if ( 0x04 * i_line -0x0f < 0xff)
844 *(p_picture->p[2].p_pixels + x + y * p_picture->p[2].i_pitch
845 ) = ( 0x04 * i_line) -(color1-1);
846 else
847 *(p_picture->p[2].p_pixels + x + y * p_picture->p[2].i_pitch
848 ) = 255;
849 }
850 else
851 {
852 *(p_picture->p[2].p_pixels + x + y * p_picture->p[2].i_pitch
853 ) = color1;
854 }
855 }
856 }
857 }
858
859 window_close( &wind_ctx );
860
861 fft_close( p_state );
862
863 free( height );
864
865 return 0;
866 }
867
spectrometer_Free(void * data)868 static void spectrometer_Free( void *data )
869 {
870 spectrometer_data *p_data = data;
871
872 if( p_data != NULL )
873 {
874 free( p_data->peaks );
875 free( p_data->p_prev_s16_buff );
876 free( p_data );
877 }
878 }
879
880
881 /*****************************************************************************
882 * scope_Run: scope effect
883 *****************************************************************************/
scope_Run(visual_effect_t * p_effect,vlc_object_t * p_aout,const block_t * p_buffer,picture_t * p_picture)884 static int scope_Run(visual_effect_t * p_effect, vlc_object_t *p_aout,
885 const block_t * p_buffer , picture_t * p_picture)
886 {
887 VLC_UNUSED(p_aout);
888
889 int i_index;
890 float *p_sample ;
891 uint8_t *ppp_area[2][3];
892
893 for( i_index = 0 ; i_index < 2 ; i_index++ )
894 {
895 for( int j = 0 ; j < 3 ; j++ )
896 {
897 ppp_area[i_index][j] =
898 p_picture->p[j].p_pixels + (i_index * 2 + 1) * p_picture->p[j].i_lines
899 / 4 * p_picture->p[j].i_pitch;
900 }
901 }
902
903 for( i_index = 0, p_sample = (float *)p_buffer->p_buffer;
904 i_index < __MIN( p_effect->i_width, (int)p_buffer->i_nb_samples );
905 i_index++ )
906 {
907 int8_t i_value;
908
909 /* Left channel */
910 i_value = p_sample[p_effect->i_idx_left] * 127;
911 *(ppp_area[0][0]
912 + p_picture->p[0].i_pitch * i_index / p_effect->i_width
913 + p_picture->p[0].i_lines * i_value / 512
914 * p_picture->p[0].i_pitch) = 0xbf;
915 *(ppp_area[0][1]
916 + p_picture->p[1].i_pitch * i_index / p_effect->i_width
917 + p_picture->p[1].i_lines * i_value / 512
918 * p_picture->p[1].i_pitch) = 0xff;
919
920
921 /* Right channel */
922 i_value = p_sample[p_effect->i_idx_right] * 127;
923 *(ppp_area[1][0]
924 + p_picture->p[0].i_pitch * i_index / p_effect->i_width
925 + p_picture->p[0].i_lines * i_value / 512
926 * p_picture->p[0].i_pitch) = 0x9f;
927 *(ppp_area[1][2]
928 + p_picture->p[2].i_pitch * i_index / p_effect->i_width
929 + p_picture->p[2].i_lines * i_value / 512
930 * p_picture->p[2].i_pitch) = 0xdd;
931
932 p_sample += p_effect->i_nb_chans;
933 }
934 return 0;
935 }
936
937
938 /*****************************************************************************
939 * vuMeter_Run: vu meter effect
940 *****************************************************************************/
vuMeter_Run(visual_effect_t * p_effect,vlc_object_t * p_aout,const block_t * p_buffer,picture_t * p_picture)941 static int vuMeter_Run(visual_effect_t * p_effect, vlc_object_t *p_aout,
942 const block_t * p_buffer , picture_t * p_picture)
943 {
944 VLC_UNUSED(p_aout);
945 float i_value_l = 0;
946 float i_value_r = 0;
947
948 /* Compute the peak values */
949 for ( unsigned i = 0 ; i < p_buffer->i_nb_samples; i++ )
950 {
951 const float *p_sample = (float *)p_buffer->p_buffer;
952 float ch;
953
954 ch = p_sample[p_effect->i_idx_left] * 256;
955 if (ch > i_value_l)
956 i_value_l = ch;
957
958 ch = p_sample[p_effect->i_idx_right] * 256;
959 if (ch > i_value_r)
960 i_value_r = ch;
961
962 p_sample += p_effect->i_nb_chans;
963 }
964
965 i_value_l = fabsf(i_value_l);
966 i_value_r = fabsf(i_value_r);
967
968 /* Stay under maximum value admited */
969 if ( i_value_l > 200 * M_PI_2 )
970 i_value_l = 200 * M_PI_2;
971 if ( i_value_r > 200 * M_PI_2 )
972 i_value_r = 200 * M_PI_2;
973
974 float *i_value;
975
976 if( !p_effect->p_data )
977 {
978 /* Allocate memory to save hand positions */
979 p_effect->p_data = vlc_alloc( 2, sizeof(float) );
980 i_value = p_effect->p_data;
981 i_value[0] = i_value_l;
982 i_value[1] = i_value_r;
983 }
984 else
985 {
986 /* Make the hands go down slowly if the current values are slower
987 than the previous */
988 i_value = p_effect->p_data;
989
990 if ( i_value_l > i_value[0] - 6 )
991 i_value[0] = i_value_l;
992 else
993 i_value[0] = i_value[0] - 6;
994
995 if ( i_value_r > i_value[1] - 6 )
996 i_value[1] = i_value_r;
997 else
998 i_value[1] = i_value[1] - 6;
999 }
1000
1001 int x, y;
1002 float teta;
1003 float teta_grad;
1004
1005 int start_x = p_effect->i_width / 2 - 120; /* i_width.min = 532 (visual.c) */
1006
1007 for ( int j = 0; j < 2; j++ )
1008 {
1009 /* Draw the two scales */
1010 int k = 0;
1011 teta_grad = GRAD_ANGLE_MIN;
1012 for ( teta = -M_PI_4; teta <= M_PI_4; teta = teta + 0.003 )
1013 {
1014 for ( unsigned i = 140; i <= 150; i++ )
1015 {
1016 y = i * cos(teta) + 20;
1017 x = i * sin(teta) + start_x + 240 * j;
1018 /* Compute the last color for the gradation */
1019 if (teta >= teta_grad + GRAD_INCR && teta_grad <= GRAD_ANGLE_MAX)
1020 {
1021 teta_grad = teta_grad + GRAD_INCR;
1022 k = k + 5;
1023 }
1024 *(p_picture->p[0].p_pixels +
1025 (p_picture->p[0].i_lines - y - 1 ) * p_picture->p[0].i_pitch
1026 + x ) = 0x45;
1027 *(p_picture->p[1].p_pixels +
1028 (p_picture->p[1].i_lines - y / 2 - 1 ) * p_picture->p[1].i_pitch
1029 + x / 2 ) = 0x0;
1030 *(p_picture->p[2].p_pixels +
1031 (p_picture->p[2].i_lines - y / 2 - 1 ) * p_picture->p[2].i_pitch
1032 + x / 2 ) = 0x4D + k;
1033 }
1034 }
1035
1036 /* Draw the two hands */
1037 teta = (float)i_value[j] / 200 - M_PI_4;
1038 for ( int i = 0; i <= 150; i++ )
1039 {
1040 y = i * cos(teta) + 20;
1041 x = i * sin(teta) + start_x + 240 * j;
1042 *(p_picture->p[0].p_pixels +
1043 (p_picture->p[0].i_lines - y - 1 ) * p_picture->p[0].i_pitch
1044 + x ) = 0xAD;
1045 *(p_picture->p[1].p_pixels +
1046 (p_picture->p[1].i_lines - y / 2 - 1 ) * p_picture->p[1].i_pitch
1047 + x / 2 ) = 0xFC;
1048 *(p_picture->p[2].p_pixels +
1049 (p_picture->p[2].i_lines - y / 2 - 1 ) * p_picture->p[2].i_pitch
1050 + x / 2 ) = 0xAC;
1051 }
1052
1053 /* Draw the hand bases */
1054 for ( teta = -M_PI_2; teta <= M_PI_2 + 0.01; teta = teta + 0.003 )
1055 {
1056 for ( int i = 0; i < 10; i++ )
1057 {
1058 y = i * cos(teta) + 20;
1059 x = i * sin(teta) + start_x + 240 * j;
1060 *(p_picture->p[0].p_pixels +
1061 (p_picture->p[0].i_lines - y - 1 ) * p_picture->p[0].i_pitch
1062 + x ) = 0xFF;
1063 *(p_picture->p[1].p_pixels +
1064 (p_picture->p[1].i_lines - y / 2 - 1 ) * p_picture->p[1].i_pitch
1065 + x / 2 ) = 0x80;
1066 *(p_picture->p[2].p_pixels +
1067 (p_picture->p[2].i_lines - y / 2 - 1 ) * p_picture->p[2].i_pitch
1068 + x / 2 ) = 0x80;
1069 }
1070 }
1071
1072 }
1073
1074 return 0;
1075 }
1076
1077 /* Table of effects */
1078 const struct visual_cb_t effectv[] = {
1079 { "scope", scope_Run, dummy_Free },
1080 { "vuMeter", vuMeter_Run, dummy_Free },
1081 { "spectrum", spectrum_Run, spectrum_Free },
1082 { "spectrometer", spectrometer_Run, spectrometer_Free },
1083 { "dummy", dummy_Run, dummy_Free },
1084 };
1085 const unsigned effectc = sizeof (effectv) / sizeof (effectv[0]);
1086