Commit eba02c65 authored by Clément Stenac's avatar Clément Stenac

* effects.c :

  - added a spectrum analyser
  options are:
	-nb :  number of bands , 20 or 80 (80 is default)
	-separ : how many blank pixels between bands (1 default)
	-amp : vertical amplification ( 3 default)
	-peaks: draw peaks ? (default 1)

  - improved options parsing

* fft.c, fft.h :
	FFT code mainly taken from XMMS (adapted coding style)

* visual.c:
	Sanity checks (users aren't stupid, are they ? )

* LIST: updated the list
parent e5fe2b34
List of vlc plugins (221)
$Id: LIST,v 1.10 2003/08/10 12:45:52 zorglub Exp $
$Id: LIST,v 1.11 2003/08/29 16:56:43 zorglub Exp $
* a52: A/52 basic parser
......@@ -91,6 +91,8 @@ $Id: LIST,v 1.10 2003/08/10 12:45:52 zorglub Exp $
* downmixsse: SSE accelerated version of downmix.
* dshow: DirectShow access plugin for encoding cards under Windows
* dts: DTS basic parser
* dtstospdif: Audio converter that encapsulates DTS into S/PDIF
......@@ -157,6 +159,8 @@ $Id: LIST,v 1.10 2003/08/10 12:45:52 zorglub Exp $
* gnome_main: Gtk+ wrapper for gtk_main
* goom: visualisation plugin based on goom
* gtk2: interface using the Gtk2 widget set.
* gtk2_main: Gtk+ wrapper for gtk_main
......@@ -290,6 +294,8 @@ $Id: LIST,v 1.10 2003/08/10 12:45:52 zorglub Exp $
* ncurses: interface module using the ncurses library.
* ntservice: run VLC as a NT service
* ogg: input module for OGG decapsulation.
* oss: audio output module using the OSS /dev/dsp interface.
......@@ -413,6 +419,8 @@ $Id: LIST,v 1.10 2003/08/10 12:45:52 zorglub Exp $
* vcd: input module for accessing Video CDs.
* visual: visualisation system
* vorbis: a vorbis audio decoder using the libvorbis library.
* vout_directx: video output module using the DirectX API.
......@@ -433,8 +441,6 @@ $Id: LIST,v 1.10 2003/08/10 12:45:52 zorglub Exp $
* x11: video output module using the X11 API.
* xmga: X11 MGA video_output plugin
* xosd: X On Screen Display interface
* xvid: Decoder for the Xvid codec, using libxvidcore
......
SOURCES_visual = visual.c \
effects.c
effects.c \
fft.c
This diff is collapsed.
/*****************************************************************************
* fft.c: Iterative implementation of a FFT
*****************************************************************************
* $Id: fft.c,v 1.1 2003/08/29 16:56:43 zorglub Exp $
*
* Mainly taken from XMMS's code
*
* Authors: Richard Boulton <richard@tartarus.org>
* Ralph Loader <suckfish@ihug.co.nz>
*
* 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.
*
* 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
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
#include "fft.h"
#include <stdlib.h>
#include <math.h>
#ifndef PI
#ifdef M_PI
#define PI M_PI
#else
#define PI 3.14159265358979323846 /* pi */
#endif
#endif
/******************************************************************************
* Local prototypes
*****************************************************************************/
static void fft_prepare(const sound_sample *input, float * re, float * im);
static void fft_calculate(float * re, float * im);
static void fft_output(const float *re, const float *im, float *output);
static int reverseBits(unsigned int initial);
/* Table to speed up bit reverse copy */
static unsigned int bitReverse[FFT_BUFFER_SIZE];
/* The next two tables could be made to use less space in memory, since they
* overlap hugely, but hey. */
static float sintable[FFT_BUFFER_SIZE / 2];
static float costable[FFT_BUFFER_SIZE / 2];
/*****************************************************************************
* These functions are the ones called externally
*****************************************************************************/
/*
* Initialisation routine - sets up tables and space to work in.
* Returns a pointer to internal state, to be used when performing calls.
* On error, returns NULL.
* The pointer should be freed when it is finished with, by fft_close().
*/
fft_state *fft_init(void)
{
fft_state *p_state;
unsigned int i;
p_state = (fft_state *) malloc (sizeof(fft_state));
if(! p_state )
return NULL;
for(i = 0; i < FFT_BUFFER_SIZE; i++)
{
bitReverse[i] = reverseBits(i);
}
for(i = 0; i < FFT_BUFFER_SIZE / 2; i++)
{
float j = 2 * PI * i / FFT_BUFFER_SIZE;
costable[i] = cos(j);
sintable[i] = sin(j);
}
return p_state;
}
/*
* Do all the steps of the FFT, taking as input sound data (as described in
* sound.h) and returning the intensities of each frequency as floats in the
* range 0 to ((FFT_BUFFER_SIZE / 2) * 32768) ^ 2
*
* The input array is assumed to have FFT_BUFFER_SIZE elements,
* and the output array is assumed to have (FFT_BUFFER_SIZE / 2 + 1) elements.
* state is a (non-NULL) pointer returned by fft_init.
*/
void fft_perform(const sound_sample *input, float *output, fft_state *state) {
/* Convert data from sound format to be ready for FFT */
fft_prepare(input, state->real, state->imag);
/* Do the actual FFT */
fft_calculate(state->real, state->imag);
/* Convert the FFT output into intensities */
fft_output(state->real, state->imag, output);
}
/*
* Free the state.
*/
void fft_close(fft_state *state) {
if(state) free(state);
}
/*****************************************************************************
* These functions are called from the other ones
*****************************************************************************/
/*
* Prepare data to perform an FFT on
*/
static void fft_prepare(const sound_sample *input, float * re, float * im) {
unsigned int i;
float *p_real = re;
float *p_imag = im;
/* Get input, in reverse bit order */
for(i = 0; i < FFT_BUFFER_SIZE; i++)
{
*p_real++ = input[bitReverse[i]];
*p_imag++ = 0;
}
}
/*
* Take result of an FFT and calculate the intensities of each frequency
* Note: only produces half as many data points as the input had.
*/
static void fft_output(const float * re, const float * im, float *output)
{
float *p_output = output;
const float *p_real = re;
const float *p_imag = im;
float *p_end = output + FFT_BUFFER_SIZE / 2;
while(p_output <= p_end)
{
*p_output = (*p_real * *p_real) + (*p_imag * *p_imag);
p_output++; p_real++; p_imag++;
}
/* Do divisions to keep the constant and highest frequency terms in scale
* with the other terms. */
*output /= 4;
*p_end /= 4;
}
/*
* Actually perform the FFT
*/
static void fft_calculate(float * re, float * im)
{
unsigned int i, j, k;
unsigned int exchanges;
float fact_real, fact_imag;
float tmp_real, tmp_imag;
unsigned int factfact;
/* Set up some variables to reduce calculation in the loops */
exchanges = 1;
factfact = FFT_BUFFER_SIZE / 2;
/* Loop through the divide and conquer steps */
for(i = FFT_BUFFER_SIZE_LOG; i != 0; i--) {
/* In this step, we have 2 ^ (i - 1) exchange groups, each with
* 2 ^ (FFT_BUFFER_SIZE_LOG - i) exchanges
*/
/* Loop through the exchanges in a group */
for(j = 0; j != exchanges; j++) {
/* Work out factor for this exchange
* factor ^ (exchanges) = -1
* So, real = cos(j * PI / exchanges),
* imag = sin(j * PI / exchanges)
*/
fact_real = costable[j * factfact];
fact_imag = sintable[j * factfact];
/* Loop through all the exchange groups */
for(k = j; k < FFT_BUFFER_SIZE; k += exchanges << 1) {
int k1 = k + exchanges;
tmp_real = fact_real * re[k1] - fact_imag * im[k1];
tmp_imag = fact_real * im[k1] + fact_imag * re[k1];
re[k1] = re[k] - tmp_real;
im[k1] = im[k] - tmp_imag;
re[k] += tmp_real;
im[k] += tmp_imag;
}
}
exchanges <<= 1;
factfact >>= 1;
}
}
static int reverseBits(unsigned int initial)
{
unsigned int reversed = 0, loop;
for(loop = 0; loop < FFT_BUFFER_SIZE_LOG; loop++) {
reversed <<= 1;
reversed += (initial & 1);
initial >>= 1;
}
return reversed;
}
/*****************************************************************************
* fft.h: Headers for iterative implementation of a FFT
*****************************************************************************
* $Id: fft.h,v 1.1 2003/08/29 16:56:43 zorglub Exp $
*
* Mainly taken from XMMS's code
*
* Authors: Richard Boulton <richard@tartarus.org>
*
* 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.
*
* 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
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
#ifndef _FFT_H_
#define _FFT_H_
#define FFT_BUFFER_SIZE_LOG 9
#define FFT_BUFFER_SIZE (1 << FFT_BUFFER_SIZE_LOG)
/* sound sample - should be an signed 16 bit value */
typedef short int sound_sample;
struct _struct_fft_state {
/* Temporary data stores to perform FFT in. */
float real[FFT_BUFFER_SIZE];
float imag[FFT_BUFFER_SIZE];
};
/* FFT prototypes */
typedef struct _struct_fft_state fft_state;
fft_state *fft_init (void);
void fft_perform (const sound_sample *input, float *output, fft_state *state);
void fft_close (fft_state *state);
#endif /* _FFT_H_ */
......@@ -2,7 +2,7 @@
* visual.c : Visualisation system
*****************************************************************************
* Copyright (C) 2002 VideoLAN
* $Id: visual.c,v 1.1 2003/08/19 21:20:00 zorglub Exp $
* $Id: visual.c,v 1.2 2003/08/29 16:56:43 zorglub Exp $
*
* Authors: Clment Stenac <zorglub@via.ecp.fr>
*
......@@ -99,6 +99,17 @@ static int Open( vlc_object_t *p_this )
p_filter->p_sys->i_height = config_GetInt( p_filter , "effect-height");
p_filter->p_sys->i_width = config_GetInt( p_filter , "effect-width");
if ( p_filter->p_sys->i_height < 20 )
p_filter->p_sys->i_height = 20;
if ( p_filter->p_sys->i_width < 20 )
p_filter->p_sys->i_width = 20;
if( (p_filter->p_sys->i_height % 2 ) != 0 )
p_filter->p_sys->i_height --;
if( (p_filter->p_sys->i_width % 2 ) != 0 )
p_filter->p_sys->i_width --;
/* Parse the effect list */
psz_effects = config_GetPsz( p_filter, "effect-list" );
msg_Dbg( p_filter , "Building list of effects" );
......@@ -113,40 +124,6 @@ static int Open( vlc_object_t *p_this )
p_current_effect = p_filter->p_sys->p_first_effect;
p_current_effect->p_next = NULL;
#define SEARCH(name , function ) \
if(!strncmp( psz_effects , name, strlen(name) ) ) \
{ \
p_current_effect->p_next = \
(visual_effect_t *)malloc( sizeof( visual_effect_t ) ); \
if( !p_current_effect ) \
{ \
msg_Err( p_filter, "Out of memory" ); \
} \
p_current_effect = p_current_effect -> p_next; \
p_current_effect->pf_run = NULL; \
p_current_effect->p_next = NULL; \
p_current_effect->i_width = p_filter->p_sys->i_width; \
p_current_effect->i_height = p_filter->p_sys->i_height; \
p_current_effect->pf_run = function ; \
p_current_effect->psz_args = NULL; \
psz_boa = strchr( psz_effects, '{' ); \
if( psz_boa ) \
{ \
psz_eoa = strchr( psz_effects, '}'); \
if( ! psz_eoa ) \
{ \
msg_Err( p_filter, "Unable to parse effect list. Aborting"); \
return -1; \
} \
*psz_eoa = '\0'; \
p_current_effect->psz_args = strdup(++psz_boa); \
psz_effects = psz_eoa; \
} \
msg_Dbg(p_filter, "Adding filter: %s ( %s )",name, \
p_current_effect->psz_args); \
}
while(1)
{
psz_eof = strchr( psz_effects , ';' );
......@@ -160,25 +137,61 @@ static int Open( vlc_object_t *p_this )
*psz_eof = '\0';
}
SEARCH("dummy",dummy_Run);
SEARCH("scope",scope_Run);
SEARCH("random",random_Run);
SEARCH("spectrum",spectrum_Run);
p_current_effect->p_next =
(visual_effect_t *)malloc( sizeof( visual_effect_t ) );
if( !p_current_effect )
{
msg_Err( p_filter, "Out of memory" );
}
p_current_effect = p_current_effect -> p_next;
p_current_effect->pf_run = NULL;
p_current_effect->p_next = NULL;
p_current_effect->i_width = p_filter->p_sys->i_width;
p_current_effect->i_height = p_filter->p_sys->i_height;
p_current_effect->p_data = NULL;
if(! strncasecmp(psz_effects,"dummy",5))
p_current_effect->pf_run = dummy_Run;
else if(! strncasecmp(psz_effects,"scope",5) )
p_current_effect->pf_run = scope_Run;
else if(! strncasecmp(psz_effects,"spectrum",8) )
p_current_effect->pf_run = spectrum_Run;
else if(! strncasecmp(psz_effects,"random",6) )
p_current_effect->pf_run = random_Run;
#if 0
else if(! strncasecmp(psz_effects,"blur",4) )
p_current_effect->pf_run = blur_Run;
#endif
p_current_effect->psz_args = NULL;
p_current_effect->i_nb_chans =
aout_FormatNbChannels( &p_filter->input);
psz_boa = strchr( psz_effects, '{' );
if( psz_boa )
{
psz_eoa = strchr( psz_effects, '}');
if( ! psz_eoa )
{
msg_Err( p_filter, "Unable to parse effect list. Aborting");
return -1;
}
*psz_eoa = '\0';
p_current_effect->psz_args = strdup(++psz_boa);
psz_effects = psz_eoa;
}
psz_effects = psz_eof;
psz_effects ++;
if( !* psz_effects || b_end == VLC_TRUE )
if( b_end == VLC_TRUE )
break;
}
p_filter->pf_do_work = DoWork;
p_filter->b_in_place= 0;
p_filter->b_in_place= 1;
/* Open the video output */
p_filter->p_sys->p_vout =
vout_Create( p_filter, p_filter->p_sys->i_width,
vout_Request( p_filter, NULL,
p_filter->p_sys->i_width,
p_filter->p_sys->i_height,
VLC_FOURCC('I','4','2','0'),
VOUT_ASPECT_FACTOR * p_filter->p_sys->i_width/
......@@ -315,6 +328,8 @@ static void DoWork( aout_instance_t *p_aout, aout_filter_t *p_filter,
while( p_current_effect )
{
#if 1
/* FIXME: Find why it segfaults when we directly call
* p_current_effect->pf_run(....)
* (segfault in errno() ) */
......@@ -334,7 +349,15 @@ static void DoWork( aout_instance_t *p_aout, aout_filter_t *p_filter,
{
spectrum_Run(p_current_effect, p_aout, p_out_buf , p_outpic );
}
#if 0
else if (p_current_effect->pf_run == blur_Run )
{
blur_Run(p_current_effect, p_aout, p_out_buf , p_outpic );
}
#endif
#else
p_current_effect->pf_run(p_current_effect, p_aout, p_out_buf , p_outpic );
#endif
p_current_effect = p_current_effect->p_next;
}
......@@ -343,7 +366,6 @@ static void DoWork( aout_instance_t *p_aout, aout_filter_t *p_filter,
vout_DisplayPicture ( p_filter->p_sys->p_vout, p_outpic );
}
/*****************************************************************************
......@@ -353,12 +375,23 @@ static void Close( vlc_object_t *p_this )
{
aout_filter_t * p_filter = (aout_filter_t *)p_this;
visual_effect_t *p_old;
visual_effect_t *p_cur = p_filter->p_sys->p_first_effect;
if( p_filter->p_sys->p_vout )
{
vlc_object_detach( p_filter->p_sys->p_vout) ;
vout_Destroy( p_filter->p_sys->p_vout );
}
/* Free the list */
while( p_cur )
{
p_old = p_cur;
p_cur = p_cur->p_next;
if( p_old ) free( p_old );
}
if( p_filter->p_sys != NULL )
free( p_filter->p_sys);
}
......@@ -2,7 +2,7 @@
* visual.h : Header for the visualisation system
*****************************************************************************
* Copyright (C) 2002 VideoLAN
* $Id: visual.h,v 1.1 2003/08/19 21:20:00 zorglub Exp $
* $Id: visual.h,v 1.2 2003/08/29 16:56:43 zorglub Exp $
*
* Authors: Clment Stenac <zorglub@via.ecp.fr>
*
......@@ -51,6 +51,7 @@ typedef struct visual_effect_t
int i_width;
int i_height;
char * psz_args;
int i_nb_chans;
} visual_effect_t ;
......@@ -71,7 +72,10 @@ int random_Run
(visual_effect_t * , aout_instance_t *, aout_buffer_t *, picture_t *);
int spectrum_Run
(visual_effect_t * , aout_instance_t *, aout_buffer_t *, picture_t *);
#if 0
int blur_Run
(visual_effect_t * , aout_instance_t *, aout_buffer_t *, picture_t *);
#endif
/* Default vout size */
#define VOUT_WIDTH 320
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment