Commit 217a4736 authored by Jean-Baptiste Kempf's avatar Jean-Baptiste Kempf

Delete galaktos plugin.

This hasn't work for quite some time and we have projectM module.
Moreover, noone complained.
parent cc1d1e62
...@@ -29,6 +29,7 @@ Visualisation: ...@@ -29,6 +29,7 @@ Visualisation:
Removed modules: Removed modules:
* csri * csri
* galaktos
Changes between 0.9.9a and 1.0.0: Changes between 0.9.9a and 1.0.0:
--------------------------------- ---------------------------------
......
...@@ -721,7 +721,7 @@ AC_CHECK_LIB(m,cos,[ ...@@ -721,7 +721,7 @@ AC_CHECK_LIB(m,cos,[
VLC_ADD_LIBS([adjust wave ripple psychedelic gradient a52tofloat32 dtstofloat32 x264 goom visual panoramix rotate noise grain scene],[-lm]) VLC_ADD_LIBS([adjust wave ripple psychedelic gradient a52tofloat32 dtstofloat32 x264 goom visual panoramix rotate noise grain scene],[-lm])
]) ])
AC_CHECK_LIB(m,pow,[ AC_CHECK_LIB(m,pow,[
VLC_ADD_LIBS([avcodec avformat swscale postproc ffmpegaltivec stream_out_transrate i420_rgb faad twolame equalizer spatializer param_eq libvlccore freetype mod mpc dmo quicktime realaudio realvideo galaktos opengl],[-lm]) VLC_ADD_LIBS([avcodec avformat swscale postproc ffmpegaltivec stream_out_transrate i420_rgb faad twolame equalizer spatializer param_eq libvlccore freetype mod mpc dmo quicktime realaudio realvideo opengl],[-lm])
]) ])
AC_CHECK_LIB(m,sqrt,[ AC_CHECK_LIB(m,sqrt,[
VLC_ADD_LIBS([headphone_channel_mixer normvol speex mono colorthres extract],[-lm]) VLC_ADD_LIBS([headphone_channel_mixer normvol speex mono colorthres extract],[-lm])
...@@ -4694,23 +4694,6 @@ then ...@@ -4694,23 +4694,6 @@ then
VLC_ADD_PLUGIN([visual]) VLC_ADD_PLUGIN([visual])
fi fi
dnl
dnl OpenGL visualisation plugin
dnl
AC_ARG_ENABLE(galaktos,
[ --enable-galaktos OpenGL visualisation plugin (default disabled)])
if test "${enable_galaktos}" = "yes"
then
AC_CHECK_HEADERS(GL/gl.h GL/glu.h, [
VLC_ADD_PLUGIN([galaktos])
if test "${SYS}" != "mingw32"; then
VLC_ADD_LIBS([galaktos],[${X_LIBS} -lGL -lGLU])
else
VLC_ADD_LIBS([galaktos],[-lopengl32])
fi
])
fi
dnl dnl
dnl goom visualization plugin dnl goom visualization plugin
dnl dnl
...@@ -5455,7 +5438,6 @@ AC_CONFIG_FILES([ ...@@ -5455,7 +5438,6 @@ AC_CONFIG_FILES([
modules/video_output/x11/Makefile modules/video_output/x11/Makefile
modules/visualization/Makefile modules/visualization/Makefile
modules/visualization/visual/Makefile modules/visualization/visual/Makefile
modules/visualization/galaktos/Makefile
]) ])
dnl Generate makefiles dnl Generate makefiles
......
...@@ -116,7 +116,6 @@ $Id$ ...@@ -116,7 +116,6 @@ $Id$
* folder: folder meta data and art finder * folder: folder meta data and art finder
* freetype: Utility to put text on video using freetype2 * freetype: Utility to put text on video using freetype2
* ftp : FTP input module * ftp : FTP input module
* galaktos: a visualization module that outputs OpenGL
* gapi: PocketPC Video output * gapi: PocketPC Video output
* gaussianblur: gaussian blur video filter * gaussianblur: gaussian blur video filter
* gestures: mouse gestures control plugin * gestures: mouse gestures control plugin
......
SUBDIRS = visual galaktos SUBDIRS = visual
SOURCES_goom = goom.c SOURCES_goom = goom.c
SOURCES_projectm = projectm.cpp SOURCES_projectm = projectm.cpp
SOURCES_galaktos = plugin.c plugin.h \
main.c main.h \
preset.c preset.h preset_types.h \
beat_detect.c beat_detect.h \
builtin_funcs.h common.h compare.h expr_types.h \
fatal.h idle_preset.h interface_types.h per_point_types.h \
param.c param.h param_types.h \
engine_vars.c engine_vars.h \
parser.c parser.h \
eval.c eval.h \
init_cond.c init_cond.h init_cond_types.h \
PCM.c PCM.h \
fftsg.c fftsg.h \
per_frame_eqn.c per_frame_eqn.h per_frame_eqn_types.h \
splaytree.c splaytree.h splaytree_types.h \
custom_shape.c custom_shape.h custom_shape_types.h \
func.c func.h func_types.h \
per_pixel_eqn.c per_pixel_eqn.h per_pixel_eqn_types.h \
tree_types.c tree_types.h \
custom_wave.c custom_wave.h custom_wave_types.h \
video_init.c video_init.h
/*****************************************************************************
* PCM.c:
*****************************************************************************
* Copyright (C) 2004 the VideoLAN team
* $Id$
*
* Authors: Cyril Deguet <asmax@videolan.org>
* code from projectM http://xmms-projectm.sourceforge.net
*
* 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
//PCM.c - Sound data handler
//
//by Peter Sperl
//
//Takes sound data from wherever and hands it back out.
//Returns PCM Data or spectrum data, or the derivative of the PCM data
#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
#include "fftsg.h"
double **PCMd; //data structure to store PCM data PCM[channels][maxsamples]
int maxsamples; //size of PCM buffer
int start; //where to add data next
int *ip; //working space for FFT routines
double *w; //lookup table for FFT routines
int new; //how many new samples
//initPCM(int samples)
//
//Initializes the PCM buffer to
// number of samples specified.
void initPCM(int samples)
{
int i;
//Allocate memory for PCM data buffer
PCMd = (double **)malloc(2 * sizeof(double *));
PCMd[0] = (double *)malloc(samples * sizeof(double));
PCMd[1] = (double *)malloc(samples * sizeof(double));
maxsamples=samples;
new=0;
//Initialize buffers to 0
for (i=0;i<samples;i++)
{
PCMd[0][i]=0;
PCMd[1][i]=0;
}
start=0;
//Allocate FFT workspace
w= (double *)malloc(maxsamples*sizeof(double));
ip= (int *)malloc(maxsamples*sizeof(int));
ip[0]=0;
}
//The only current addPCM function, can support more
//
//Takes in a 2x512 array of PCM samples
//and stores them
void addPCM(int16_t PCMdata[2][512])
{
int i,j;
int samples=512;
for(i=0;i<samples;i++)
{
j=i+start;
PCMd[0][j%maxsamples]=(PCMdata[0][i]/16384.0);
PCMd[1][j%maxsamples]=(PCMdata[1][i]/16384.0);
}
// printf("Added %d samples %d %d %f\n",samples,start,(start+samples)%maxsamples,PCM[0][start+10]);
start+=samples;
start=start%maxsamples;
new+=samples;
if (new>maxsamples) new=maxsamples;
}
//puts sound data requested at provided pointer
//
//samples is number of PCM samples to return
//freq = 0 gives PCM data
//freq = 1 gives FFT data
//smoothing is the smoothing coefficient
//returned values are normalized from -1 to 1
void getPCM(double *PCMdata, int samples, int channel, int freq, double smoothing, int derive)
{
int i,index;
index=start-1;
if (index<0) index=maxsamples+index;
PCMdata[0]=PCMd[channel][index];
for(i=1;i<samples;i++)
{
index=start-1-i;
if (index<0) index=maxsamples+index;
PCMdata[i]=(1-smoothing)*PCMd[channel][index]+smoothing*PCMdata[i-1];
}
//return derivative of PCM data
if(derive)
{
for(i=0;i<samples-1;i++)
{
PCMdata[i]=PCMdata[i]-PCMdata[i+1];
}
PCMdata[samples-1]=0;
}
//return frequency data instead of PCM (perform FFT)
if (freq) rdft(samples, 1, PCMdata, ip, w);
}
//getPCMnew
//
//Like getPCM except it returns all new samples in the buffer
//the actual return value is the number of samples, up to maxsamples.
//the passed pointer, PCMData, must bee able to hold up to maxsamples
int getPCMnew(double *PCMdata, int channel, int freq, double smoothing, int derive, int reset)
{
int i,index;
index=start-1;
if (index<0) index=maxsamples+index;
PCMdata[0]=PCMd[channel][index];
for(i=1;i<new;i++)
{
index=start-1-i;
if (index<0) index=maxsamples+index;
PCMdata[i]=(1-smoothing)*PCMd[channel][index]+smoothing*PCMdata[i-1];
}
//return derivative of PCM data
if(derive)
{
for(i=0;i<new-1;i++)
{
PCMdata[i]=PCMdata[i]-PCMdata[i+1];
}
PCMdata[new-1]=0;
}
//return frequency data instead of PCM (perform FFT)
// if (freq) rdft(samples, 1, PCMdata, ip, w);
i=new;
if (reset) new=0;
return i;
}
//Free stuff
void freePCM()
{
free(PCMd[0]);
free(PCMd[1]);
free(PCMd);
free(ip);
free(w);
}
void initPCM(int maxsamples);
void addPCM(int16_t [2][512]);
void getPCM(double *data, int samples, int channel, int freq, double smoothing, int derive);
void freePCM();
int getPCMnew(double *PCMdata, int channel, int freq, double smoothing, int derive,int reset);
/*****************************************************************************
* beat_detect.c: basic beat detection algorithm
*****************************************************************************
* Copyright (C) 2004 the VideoLAN team
* $Id$
*
* Authors: Cyril Deguet <asmax@videolan.org>
* code from projectM http://xmms-projectm.sourceforge.net
*
* 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
//
//by Peter Sperl
//
//Takes sound data from wherever and returns beat detection values
//Uses statistical Energy-Based methods. Very simple
//
//Some stuff was taken from Frederic Patin's beat-detection article, you'll find it online
#include <stdlib.h>
#include <stdio.h>
#include "engine_vars.h"
double beat_buffer[32][80],beat_instant[32],beat_history[32];
double *beat_val,*beat_att,*beat_variance;
int beat_buffer_pos;
double vol_buffer[80],vol_instant,vol_history;
void initBeatDetect()
{
int x,y;
vol_instant=0;
vol_history=0;
for (y=0;y<80;y++)
{
vol_buffer[y]=0;
}
beat_buffer_pos=0;
beat_val=(double *)malloc(32*sizeof(double));
beat_att=(double *)malloc(32*sizeof(double));
beat_variance=(double *)malloc(32*sizeof(double));
for (x=0;x<32;x++)
{
beat_instant[x]=0;
beat_history[x]=0;
beat_val[x]=1.0;
beat_att[x]=1.0;
beat_variance[x]=0;
for (y=0;y<80;y++)
{
beat_buffer[x][y]=0;
}
}
}
void getBeatVals(double *vdataL,double *vdataR, double *vol)
{
int linear=0;
int x,y;
vol_instant=0;
for ( x=0;x<16;x++)
{
beat_instant[x]=0;
for ( y=linear*2;y<(linear+8+x)*2;y++)
{
beat_instant[x]+=((vdataL[y]*vdataL[y])+(vdataR[y]*vdataR[y]))*(1.0/(8+x));
vol_instant+=((vdataL[y]*vdataL[y])+(vdataR[y]*vdataR[y]))*(1.0/512.0);
}
linear=y/2;
beat_history[x]-=(beat_buffer[x][beat_buffer_pos])*.0125;
beat_buffer[x][beat_buffer_pos]=beat_instant[x];
beat_history[x]+=(beat_instant[x])*.0125;
beat_val[x]=(beat_instant[x])/(beat_history[x]);
beat_att[x]+=(beat_instant[x])/(beat_history[x]);
}
vol_history-=(vol_buffer[beat_buffer_pos])*.0125;
vol_buffer[beat_buffer_pos]=vol_instant;
vol_history+=(vol_instant)*.0125;
double temp2=0;
mid=0;
for(x=1;x<10;x++)
{
mid+=(beat_instant[x]);
temp2+=(beat_history[x]);
}
mid=mid/(1.5*temp2);
temp2=0;
treb=0;
for(x=10;x<16;x++)
{
treb+=(beat_instant[x]);
temp2+=(beat_history[x]);
}
treb=treb/(1.5*temp2);
*vol=vol_instant/(1.5*vol_history);
bass=(beat_instant[0])/(1.5*beat_history[0]);
treb_att=.6 * treb_att + .4 * treb;
mid_att=.6 * mid_att + .4 * mid;
bass_att=.6 * bass_att + .4 * bass;
//printf("%f %f %f %f\n",bass,mid,treb,*vol);
// *vol=(beat_instant[3])/(beat_history[3]);
beat_buffer_pos++;
if( beat_buffer_pos>79)beat_buffer_pos=0;
}
void freeBeatDetect()
{
free(beat_att);
free(beat_val);
free(beat_variance);
}
void initBeatDetect();
void getBeatVals(double *vdataL,double *vdataR,double *vol);
void freeBeatDetect();
/*****************************************************************************
* builtin_funcs.c:
*****************************************************************************
* Copyright (C) 2004 the VideoLAN team
* $Id$
*
* Authors: Cyril Deguet <asmax@videolan.org>
* code from projectM http://xmms-projectm.sourceforge.net
*
* 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
/* Values to optimize the sigmoid function */
#define R 32767
#define RR 65534
static inline double int_wrapper(double * arg_list) {
return floor(arg_list[0]);
}
static inline double sqr_wrapper(double * arg_list) {
return pow(2, arg_list[0]);
}
static inline double sign_wrapper(double * arg_list) {
return -arg_list[0];
}
static inline double min_wrapper(double * arg_list) {
if (arg_list[0] > arg_list[1])
return arg_list[1];
return arg_list[0];
}
static inline double max_wrapper(double * arg_list) {
if (arg_list[0] > arg_list[1])
return arg_list[0];
return arg_list[1];
}
/* consult your AI book */
static inline double sigmoid_wrapper(double * arg_list) {
return (RR / (1 + exp( -(((double)(arg_list[0])) * arg_list[1]) / R) - R));
}
static inline double bor_wrapper(double * arg_list) {
return (double)((int)arg_list[0] || (int)arg_list[1]);
}
static inline double band_wrapper(double * arg_list) {
return (double)((int)arg_list[0] && (int)arg_list[1]);
}
static inline double bnot_wrapper(double * arg_list) {
return (double)(!(int)arg_list[0]);
}
static inline double if_wrapper(double * arg_list) {
if ((int)arg_list[0] == 0)
return arg_list[2];
return arg_list[1];
}
static inline double rand_wrapper(double * arg_list) {
double l;
// printf("RAND ARG:(%d)\n", (int)arg_list[0]);
l = (double)((rand()) % ((int)arg_list[0]));
//printf("VAL: %f\n", l);
return l;
}
static inline double equal_wrapper(double * arg_list) {
return (arg_list[0] == arg_list[1]);
}
static inline double above_wrapper(double * arg_list) {
return (arg_list[0] > arg_list[1]);
}
static inline double below_wrapper(double * arg_list) {
return (arg_list[0] < arg_list[1]);
}
static inline double sin_wrapper(double * arg_list) {
return (sin (arg_list[0]));
}
static inline double cos_wrapper(double * arg_list) {
return (cos (arg_list[0]));
}
static inline double tan_wrapper(double * arg_list) {
return (tan(arg_list[0]));
}
static inline double asin_wrapper(double * arg_list) {
return (asin (arg_list[0]));
}
static inline double acos_wrapper(double * arg_list) {
return (acos (arg_list[0]));
}
static inline double atan_wrapper(double * arg_list) {
return (atan (arg_list[0]));
}
static inline double atan2_wrapper(double * arg_list) {
return (atan2 (arg_list[0], arg_list[1]));
}
static inline double pow_wrapper(double * arg_list) {
return (pow (arg_list[0], arg_list[1]));
}
static inline double exp_wrapper(double * arg_list) {
return (exp(arg_list[0]));
}
static inline double abs_wrapper(double * arg_list) {
return (fabs(arg_list[0]));
}
static inline double log_wrapper(double *arg_list) {
return (log (arg_list[0]));
}
static inline double log10_wrapper(double * arg_list) {
return (log10 (arg_list[0]));
}
static inline double sqrt_wrapper(double * arg_list) {
return (sqrt (arg_list[0]));
}
static inline double nchoosek_wrapper(double * arg_list) {
unsigned long cnm = 1UL;
int i, f;
int n, m;
n = (int)arg_list[0];
m = (int)arg_list[1];
if (m*2 >n) m = n-m;
for (i=1 ; i <= m; n--, i++)
{
if ((f=n) % i == 0)
f /= i;
else cnm /= i;
cnm *= f;
}
return (double)cnm;
}
static inline double fact_wrapper(double * arg_list) {
int result = 1;
int n = (int)arg_list[0];
while (n > 1) {
result = result * n;
n--;
}
return (double)result;
}
#ifndef COMMON_H
#define COMMON_H
#define DEFAULT_FONT_PATH "/home/carm/fonts/courier1.glf"
#define MAX_TOKEN_SIZE 512
#define MAX_PATH_SIZE 4096
#define STRING_BUFFER_SIZE 1024*150
#define STRING_LINE_SIZE 1024
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#define PROJECTM_FILE_EXTENSION ".prjm"
#define MILKDROP_FILE_EXTENSION ".milk"
#define MAX_DOUBLE_SIZE 10000000.0
#define MIN_DOUBLE_SIZE -10000000.0
#define MAX_INT_SIZE 10000000
#define MIN_INT_SIZE -10000000
#define DEFAULT_DOUBLE_IV 0.0 /* default double initial value */
#define DEFAULT_DOUBLE_LB MIN_DOUBLE_SIZE /* default double lower bound */
#define DEFAULT_DOUBLE_UB MAX_DOUBLE_SIZE /* default double upper bound */
#endif
int compare_int(int * num1, int * num2);
int compare_string(char * string1, char * string2);
/*****************************************************************************
* custom_shape.c:
*****************************************************************************
* Copyright (C) 2004 the VideoLAN team
* $Id$
*
* Authors: Cyril Deguet <asmax@videolan.org>
* code from projectM http://xmms-projectm.sourceforge.net
*
* 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include "common.h"
#include "fatal.h"
#include "param_types.h"
#include "param.h"
#include "expr_types.h"
#include "eval.h"
#include "splaytree_types.h"
#include "splaytree.h"
#include "tree_types.h"
#include "per_frame_eqn_types.h"
#include "per_frame_eqn.h"
#include "init_cond_types.h"
#include "init_cond.h"
#include "preset_types.h"
#include "custom_shape_types.h"
#include "custom_shape.h"
#include "init_cond_types.h"
#include "init_cond.h"
custom_shape_t * interface_shape = NULL;
int cwave_interface_id = 0;
extern preset_t * active_preset;
static inline void eval_custom_shape_init_conds(custom_shape_t * custom_shape);
void load_unspec_init_cond_shape(param_t * param);
void destroy_param_db_tree_shape(splaytree_t * tree);
void destroy_per_frame_eqn_tree_shape(splaytree_t * tree);
void destroy_per_frame_init_eqn_tree_shape(splaytree_t * tree);
void destroy_init_cond_tree_shape(splaytree_t * tree);
custom_shape_t * new_custom_shape(int id) {
custom_shape_t * custom_shape;
param_t * param;
if ((custom_shape = (custom_shape_t*)malloc(sizeof(custom_shape_t))) == NULL)
return NULL;
custom_shape->id = id;
custom_shape->per_frame_count = 0;
custom_shape->per_frame_eqn_string_index = 0;
custom_shape->per_frame_init_eqn_string_index = 0;
/* Initialize tree data structures */
if ((custom_shape->param_tree =
create_splaytree(compare_string, copy_string, free_string)) == NULL) {
free_custom_shape(custom_shape);
return NULL;
}
if ((custom_shape->per_frame_eqn_tree =
create_splaytree(compare_int, copy_int, free_int)) == NULL) {
free_custom_shape(custom_shape);
return NULL;
}
if ((custom_shape->init_cond_tree =
create_splaytree(compare_string, copy_string, free_string)) == NULL) {
free_custom_shape(custom_shape);
return NULL;
}
if ((custom_shape->per_frame_init_eqn_tree =
create_splaytree(compare_string, copy_string, free_string)) == NULL) {
free_custom_shape(custom_shape);
return NULL;
}
/* Start: Load custom shape parameters */
if ((param = new_param_double("r", P_FLAG_NONE, &custom_shape->r, NULL, 1.0, 0.0, .5)) == NULL) {
free_custom_shape(custom_shape);
return NULL;
}
if (insert_param(param, custom_shape->param_tree) < 0) {
free_custom_shape(custom_shape);
return NULL;
}
if ((param = new_param_double("g", P_FLAG_NONE, &custom_shape->g, NULL, 1.0, 0.0, .5)) == NULL){
free_custom_shape(custom_shape);
return NULL;
}
if (insert_param(param, custom_shape->param_tree) < 0) {
free_custom_shape(custom_shape);
return NULL;
}
if ((param = new_param_double("b", P_FLAG_NONE, &custom_shape->b, NULL, 1.0, 0.0, .5)) == NULL){
free_custom_shape(custom_shape);
return NULL;
}
if (insert_param(param, custom_shape->param_tree) < 0) {
free_custom_shape(custom_shape);
return NULL;
}
if ((param = new_param_double("a", P_FLAG_NONE, &custom_shape->a, NULL, 1.0, 0.0, .5)) == NULL){
free_custom_shape(custom_shape);
return NULL;
}
if (insert_param(param, custom_shape->param_tree) < 0) {
free_custom_shape(custom_shape);
return NULL;
}
if ((param = new_param_double("border_r", P_FLAG_NONE, &custom_shape->border_r, NULL, 1.0, 0.0, .5)) == NULL) {
free_custom_shape(custom_shape);
return NULL;
}
if (insert_param(param, custom_shape->param_tree) < 0) {
free_custom_shape(custom_shape);
return NULL;
}
if ((param = new_param_double("border_g", P_FLAG_NONE, &custom_shape->border_g, NULL, 1.0, 0.0, .5)) == NULL){
free_custom_shape(custom_shape);
return NULL;
}
if (insert_param(param, custom_shape->param_tree) < 0) {
free_custom_shape(custom_shape);
return NULL;
}
if ((param = new_param_double("border_b", P_FLAG_NONE, &custom_shape->border_b, NULL, 1.0, 0.0, .5)) == NULL){
free_custom_shape(custom_shape);
return NULL;
}
if (insert_param(param, custom_shape->param_tree) < 0) {
free_custom_shape(custom_shape);
return NULL;
}
if ((param = new_param_double("border_a", P_FLAG_NONE, &custom_shape->border_a, NULL, 1.0, 0.0, .5)) == NULL){
free_custom_shape(custom_shape);
return NULL;
}
if (insert_param(param, custom_shape->param_tree) < 0) {
free_custom_shape(custom_shape);
return NULL;
}
if ((param = new_param_double("r2", P_FLAG_NONE, &custom_shape->r2, NULL, 1.0, 0.0, .5)) == NULL) {
free_custom_shape(custom_shape);
return NULL;
}
if (insert_param(param, custom_shape->param_tree) < 0) {
free_custom_shape(custom_shape);
return NULL;
}
if ((param = new_param_double("g2", P_FLAG_NONE, &custom_shape->g2, NULL, 1.0, 0.0, .5)) == NULL){
free_custom_shape(custom_shape);
return NULL;
}
if (insert_param(param, custom_shape->param_tree) < 0) {
free_custom_shape(custom_shape);
return NULL;
}
if ((param = new_param_double("b2", P_FLAG_NONE, &custom_shape->b2, NULL, 1.0, 0.0, .5)) == NULL){
free_custom_shape(custom_shape);
return NULL;
}
if (insert_param(param, custom_shape->param_tree) < 0) {
free_custom_shape(custom_shape);
return NULL;
}
if ((param = new_param_double("a2", P_FLAG_NONE, &custom_shape->a2, NULL, 1.0, 0.0, .5)) == NULL){
free_custom_shape(custom_shape);
return NULL;
}
if (insert_param(param, custom_shape->param_tree) < 0) {
free_custom_shape(custom_shape);
return NULL;
}
if ((param = new_param_double("x", P_FLAG_NONE, &custom_shape->x, NULL, 1.0, 0.0, .5)) == NULL) {
free_custom_shape(custom_shape);
return NULL;
}
if (insert_param(param, custom_shape->param_tree) < 0) {
free_custom_shape(custom_shape);
return NULL;
}
if ((param = new_param_double("y", P_FLAG_NONE, &custom_shape->y, NULL, 1.0, 0.0, .5)) == NULL) {
free_custom_shape(custom_shape);
return NULL;
}
if (insert_param(param, custom_shape->param_tree) < 0) {
free_custom_shape(custom_shape);
return NULL;
}
if ((param = new_param_bool("thickOutline", P_FLAG_NONE, &custom_shape->thickOutline, 1, 0, 0)) == NULL) {
free_custom_shape(custom_shape);
return NULL;
}
if (insert_param(param, custom_shape->param_tree) < 0) {
free_custom_shape(custom_shape);
return NULL;
}
if ((param = new_param_bool("enabled", P_FLAG_NONE, &custom_shape->enabled, 1, 0, 0)) == NULL) {
free_custom_shape(custom_shape);
return NULL;
}
if (insert_param(param, custom_shape->param_tree) < 0) {
free_custom_shape(custom_shape);
return NULL;
}
if ((param = new_param_int("sides", P_FLAG_NONE, &custom_shape->sides, 100, 3, 3)) == NULL) {
free_custom_shape(custom_shape);
return NULL;
}
if (insert_param(param, custom_shape->param_tree) < 0) {
free_custom_shape(custom_shape);
return NULL;
}
if ((param = new_param_bool("additive", P_FLAG_NONE, &custom_shape->additive, 1, 0, 0)) == NULL) {
free_custom_shape(custom_shape);
return NULL;
}
if (insert_param(param, custom_shape->param_tree) < 0) {
free_custom_shape(custom_shape);
return NULL;
}
if ((param = new_param_bool("textured", P_FLAG_NONE, &custom_shape->textured, 1, 0, 0)) == NULL) {
free_custom_shape(custom_shape);
return NULL;
}
if (insert_param(param, custom_shape->param_tree) < 0) {
free_custom_shape(custom_shape);
return NULL;
}
if ((param = new_param_double("rad", P_FLAG_NONE, &custom_shape->rad, NULL, MAX_DOUBLE_SIZE, 0, 0.0)) == NULL) {
free_custom_shape(custom_shape);
return NULL;
}
if (insert_param(param, custom_shape->param_tree) < 0) {
free_custom_shape(custom_shape);
return NULL;
}
if ((param = new_param_double("ang", P_FLAG_NONE, &custom_shape->ang, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
free_custom_shape(custom_shape);
return NULL;
}
if (insert_param(param, custom_shape->param_tree) < 0) {
free_custom_shape(custom_shape);
return NULL;
}
if ((param = new_param_double("tex_zoom", P_FLAG_NONE, &custom_shape->tex_zoom, NULL, MAX_DOUBLE_SIZE, .00000000001, 0.0)) == NULL) {
free_custom_shape(custom_shape);
return NULL;
}
if (insert_param(param, custom_shape->param_tree) < 0) {
free_custom_shape(custom_shape);
return NULL;
}
if ((param = new_param_double("tex_ang", P_FLAG_NONE, &custom_shape->tex_ang, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
free_custom_shape(custom_shape);
return NULL;
}
if (insert_param(param, custom_shape->param_tree) < 0) {
free_custom_shape(custom_shape);
return NULL;
}
if ((param = new_param_double("t1", P_FLAG_TVAR, &custom_shape->t1, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
free_custom_shape(custom_shape);
return NULL;
}
if (insert_param(param, custom_shape->param_tree) < 0) {
free_custom_shape(custom_shape);
return NULL;
}
if ((param = new_param_double("t2", P_FLAG_TVAR, &custom_shape->t2, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
free_custom_shape(custom_shape);
return NULL;
}
if (insert_param(param, custom_shape->param_tree) < 0) {
free_custom_shape(custom_shape);
return NULL;
}
if ((param = new_param_double("t3", P_FLAG_TVAR, &custom_shape->t3, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
free_custom_shape(custom_shape);
return NULL;
}
if (insert_param(param, custom_shape->param_tree) < 0) {
free_custom_shape(custom_shape);
return NULL;
}
if ((param = new_param_double("t4", P_FLAG_TVAR, &custom_shape->t4, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
free_custom_shape(custom_shape);
return NULL;
}
if (insert_param(param, custom_shape->param_tree) < 0) {
free_custom_shape(custom_shape);
return NULL;
}
if ((param = new_param_double("t5", P_FLAG_TVAR, &custom_shape->t5, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
free_custom_shape(custom_shape);
return NULL;
}
if (insert_param(param, custom_shape->param_tree) < 0) {
free_custom_shape(custom_shape);
return NULL;
}
if ((param = new_param_double("t6", P_FLAG_TVAR, &custom_shape->t6, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
free_custom_shape(custom_shape);
return NULL;
}
if (insert_param(param, custom_shape->param_tree) < 0) {
free_custom_shape(custom_shape);
return NULL;
}
if ((param = new_param_double("t7", P_FLAG_TVAR, &custom_shape->t7, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
free_custom_shape(custom_shape);
return NULL;
}
if (insert_param(param, custom_shape->param_tree) < 0) {
free_custom_shape(custom_shape);
return NULL;
}
if ((param = new_param_double("t8", P_FLAG_TVAR, &custom_shape->t8, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
free_custom_shape(custom_shape);
return NULL;
}
if (insert_param(param, custom_shape->param_tree) < 0) {
free_custom_shape(custom_shape);
return NULL;
}
/* End of parameter loading. Note that the read only parameters associated
with custom shapes (ie, sample) are global variables, and not specific to
the custom shape datastructure. */
return custom_shape;
}
void destroy_per_frame_init_eqn_tree_shape(splaytree_t * tree) {
if (!tree)
return;
splay_traverse(free_init_cond, tree);
destroy_splaytree(tree);
}
void destroy_init_cond_tree_shape(splaytree_t * tree) {
if (!tree)
return;
splay_traverse(free_init_cond, tree);
destroy_splaytree(tree);
}
void destroy_per_frame_eqn_tree_shape(splaytree_t * tree) {
if (!tree)
return;
splay_traverse(free_per_frame_eqn, tree);
destroy_splaytree(tree);
}
void destroy_param_db_tree_shape(splaytree_t * tree) {
if (!tree)
return;
splay_traverse(free_param, tree);
destroy_splaytree(tree);
}
/* Frees a custom shape form object */
void free_custom_shape(custom_shape_t * custom_shape) {
if (custom_shape == NULL)
return;
if (custom_shape->param_tree == NULL)
return;
destroy_per_frame_eqn_tree_shape(custom_shape->per_frame_eqn_tree);
destroy_init_cond_tree_shape(custom_shape->init_cond_tree);
destroy_param_db_tree_shape(custom_shape->param_tree);
destroy_per_frame_init_eqn_tree_shape(custom_shape->per_frame_init_eqn_tree);
free(custom_shape);
return;
}
custom_shape_t * find_custom_shape(int id, preset_t * preset, int create_flag) {
custom_shape_t * custom_shape = NULL;
if (preset == NULL)
return NULL;
if ((custom_shape = splay_find(&id, preset->custom_shape_tree)) == NULL) {
if (CUSTOM_SHAPE_DEBUG) { printf("find_custom_shape: creating custom shape (id = %d)...", id);fflush(stdout);}
if (create_flag == FALSE) {
if (CUSTOM_SHAPE_DEBUG) printf("you specified not to (create flag = false), returning null\n");
return NULL;
}
if ((custom_shape = new_custom_shape(id)) == NULL) {
if (CUSTOM_SHAPE_DEBUG) printf("failed...out of memory?\n");
return NULL;
}
if (CUSTOM_SHAPE_DEBUG) { printf("success.Inserting..."); fflush(stdout);}
if (splay_insert(custom_shape, &custom_shape->id, preset->custom_shape_tree) < 0) {
if (CUSTOM_SHAPE_DEBUG) printf("failed, probably a duplicated!!\n");
free_custom_shape(custom_shape);
return NULL;
}
if (CUSTOM_SHAPE_DEBUG) printf("done.\n");
}
return custom_shape;
}
void evalCustomShapeInitConditions() {
splay_traverse(eval_custom_shape_init_conds, active_preset->custom_shape_tree);
}
static inline void eval_custom_shape_init_conds(custom_shape_t * custom_shape) {
splay_traverse(eval_init_cond, custom_shape->init_cond_tree);
splay_traverse(eval_init_cond, custom_shape->per_frame_init_eqn_tree);
}
void load_unspecified_init_conds_shape(custom_shape_t * custom_shape) {
interface_shape = custom_shape;
splay_traverse(load_unspec_init_cond_shape, interface_shape->param_tree);
interface_shape = NULL;
}
void load_unspec_init_cond_shape(param_t * param) {
init_cond_t * init_cond;
value_t init_val;
/* Don't count read only parameters as initial conditions */
if (param->flags & P_FLAG_READONLY)
return;
if (param->flags & P_FLAG_QVAR)
return;
if (param->flags & P_FLAG_TVAR)
return;
if (param->flags & P_FLAG_USERDEF)
return;
/* If initial condition was not defined by the preset file, force a default one
with the following code */
if ((init_cond = splay_find(param->name, interface_shape->init_cond_tree)) == NULL) {
/* Make sure initial condition does not exist in the set of per frame initial equations */
if ((init_cond = splay_find(param->name, interface_shape->per_frame_init_eqn_tree)) != NULL)
return;
if (param->type == P_TYPE_BOOL)
init_val.bool_val = 0;
else if (param->type == P_TYPE_INT)
init_val.int_val = *(int*)param->engine_val;
else if (param->type == P_TYPE_DOUBLE)
init_val.double_val = *(double*)param->engine_val;
//printf("%s\n", param->name);
/* Create new initial condition */
if ((init_cond = new_init_cond(param, init_val)) == NULL)
return;
/* Insert the initial condition into this presets tree */
if (splay_insert(init_cond, init_cond->param->name, interface_shape->init_cond_tree) < 0) {
free_init_cond(init_cond);
return;
}
}
}
/* Interface function. Makes another custom shape the current
concern for per frame / point equations */
custom_shape_t * nextCustomShape() {
if ((interface_shape = splay_find(&cwave_interface_id, active_preset->custom_shape_tree)) == NULL) {
cwave_interface_id = 0;
return NULL;
}
cwave_interface_id++;
/* Evaluate all per frame equations associated with this shape */
splay_traverse(eval_per_frame_eqn, interface_shape->per_frame_eqn_tree);
return interface_shape;
}
#ifndef CUSTOM_SHAPE_H
#define CUSTOM_SHAPE_H
#define CUSTOM_SHAPE_DEBUG 0
#include "expr_types.h"
#include "custom_shape_types.h"
#include "preset_types.h"
void free_custom_shape(custom_shape_t * custom_shape);
custom_shape_t * new_custom_shape(int id);
custom_shape_t * find_custom_shape(int id, preset_t * preset, int create_flag);
void load_unspecified_init_conds_shape(custom_shape_t * custom_shape);
void evalCustomShapeInitConditions();
custom_shape_t * nextCustomShape();
#endif
#ifndef CUSTOM_SHAPE_TYPES_H
#define CUSTOM_SHAPE_TYPES_H
#include "common.h"
#include "splaytree_types.h"
#include "expr_types.h"
typedef struct CUSTOM_SHAPE_T {
/* Numerical id */
int id;
int per_frame_count;
/* Parameter tree associated with this custom shape */
splaytree_t * param_tree;
/* Engine variables */
int sides;
int thickOutline;
int enabled;
int additive;
int textured;
double tex_zoom;
double tex_ang;
double x; /* x position for per point equations */
double y; /* y position for per point equations */
double rad;
double ang;
double r; /* red color value */
double g; /* green color value */
double b; /* blue color value */
double a; /* alpha color value */
double r2; /* red color value */
double g2; /* green color value */
double b2; /* blue color value */
double a2; /* alpha color value */
double border_r; /* red color value */
double border_g; /* green color value */
double border_b; /* blue color value */
double border_a; /* alpha color value */
/* stupid t variables */
double t1;
double t2;
double t3;
double t4;
double t5;
double t6;
double t7;
double t8;
/* Data structure to hold per frame / per frame init equations */
splaytree_t * init_cond_tree;
splaytree_t * per_frame_eqn_tree;
splaytree_t * per_frame_init_eqn_tree;
/* Denotes the index of the last character for each string buffer */
int per_frame_eqn_string_index;
int per_frame_init_eqn_string_index;
/* String buffers for per frame / per frame init equations */
char per_frame_eqn_string_buffer[STRING_BUFFER_SIZE];
char per_frame_init_eqn_string_buffer[STRING_BUFFER_SIZE];
/* Per point equation array */
} custom_shape_t;
#endif
/*****************************************************************************
* custom_wave.c:
*****************************************************************************
* Copyright (C) 2004 the VideoLAN team
* $Id$
*
* Authors: Cyril Deguet <asmax@videolan.org>
* code from projectM http://xmms-projectm.sourceforge.net
*
* 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "common.h"
#include "fatal.h"
#include "param_types.h"
#include "param.h"
#include "expr_types.h"
#include "eval.h"
#include "splaytree_types.h"
#include "splaytree.h"
#include "tree_types.h"
#include "per_frame_eqn_types.h"
#include "per_frame_eqn.h"
#include "init_cond_types.h"
#include "init_cond.h"
#include "preset_types.h"
#include "custom_wave_types.h"
#include "custom_wave.h"
#include "init_cond_types.h"
#include "init_cond.h"
#include "engine_vars.h"
#define MAX_SAMPLE_SIZE 4096
extern int mesh_i;
custom_wave_t * interface_wave = NULL;
int interface_id = 0;
extern preset_t * active_preset;
static inline void eval_custom_wave_init_conds(custom_wave_t * custom_wave);
void load_unspec_init_cond(param_t * param);
void destroy_per_point_eqn_tree(splaytree_t * tree);
void destroy_param_db_tree(splaytree_t * tree);
void destroy_per_frame_eqn_tree(splaytree_t * tree);
void destroy_per_frame_init_eqn_tree(splaytree_t * tree);
void destroy_init_cond_tree(splaytree_t * tree);
static inline void evalPerPointEqn(per_point_eqn_t * per_point_eqn);
custom_wave_t * new_custom_wave(int id) {
custom_wave_t * custom_wave;
param_t * param;
if ((custom_wave = (custom_wave_t*)malloc(sizeof(custom_wave_t))) == NULL)
return NULL;
custom_wave->id = id;
custom_wave->per_frame_count = 0;
custom_wave->samples = 512;
custom_wave->bSpectrum = 0;
custom_wave->enabled = 1;
custom_wave->sep = 1;
custom_wave->smoothing = 0.0;
custom_wave->bUseDots = 0;
custom_wave->bAdditive = 0;
custom_wave->r = custom_wave->g = custom_wave->b = custom_wave->a = 0.0;
custom_wave->scaling = 1.0;
custom_wave->per_frame_eqn_string_index = 0;
custom_wave->per_frame_init_eqn_string_index = 0;
custom_wave->per_point_eqn_string_index = 0;
custom_wave->r_mesh = malloc(MAX_SAMPLE_SIZE*sizeof(double));
custom_wave->g_mesh = malloc(MAX_SAMPLE_SIZE*sizeof(double));
custom_wave->b_mesh = malloc(MAX_SAMPLE_SIZE*sizeof(double));
custom_wave->a_mesh = malloc(MAX_SAMPLE_SIZE*sizeof(double));
custom_wave->x_mesh = malloc(MAX_SAMPLE_SIZE*sizeof(double));
custom_wave->y_mesh = malloc(MAX_SAMPLE_SIZE*sizeof(double));
custom_wave->value1 = malloc(MAX_SAMPLE_SIZE*sizeof(double));
custom_wave->value2 = malloc(MAX_SAMPLE_SIZE*sizeof(double));
custom_wave->sample_mesh = malloc(MAX_SAMPLE_SIZE*sizeof(double));
/* Initialize tree data structures */
if ((custom_wave->param_tree =
create_splaytree(compare_string, copy_string, free_string)) == NULL) {
free_custom_wave(custom_wave);
return NULL;
}
if ((custom_wave->per_point_eqn_tree =
create_splaytree(compare_int, copy_int, free_int)) == NULL) {
free_custom_wave(custom_wave);
return NULL;
}
if ((custom_wave->per_frame_eqn_tree =
create_splaytree(compare_int, copy_int, free_int)) == NULL) {
free_custom_wave(custom_wave);
return NULL;
}
if ((custom_wave->init_cond_tree =
create_splaytree(compare_string, copy_string, free_string)) == NULL) {
free_custom_wave(custom_wave);
return NULL;
}
if ((custom_wave->per_frame_init_eqn_tree =
create_splaytree(compare_string, copy_string, free_string)) == NULL) {
free_custom_wave(custom_wave);
return NULL;
}
/* Start: Load custom wave parameters */
if ((param = new_param_double("r", P_FLAG_DONT_FREE_MATRIX | P_FLAG_PER_POINT, &custom_wave->r, custom_wave->r_mesh, 1.0, 0.0, .5)) == NULL) {
free_custom_wave(custom_wave);
return NULL;
}
if (insert_param(param, custom_wave->param_tree) < 0) {
free_custom_wave(custom_wave);
return NULL;
}
if ((param = new_param_double("g", P_FLAG_DONT_FREE_MATRIX | P_FLAG_PER_POINT, &custom_wave->g, custom_wave->g_mesh, 1.0, 0.0, .5)) == NULL){
free_custom_wave(custom_wave);
return NULL;
}
if (insert_param(param, custom_wave->param_tree) < 0) {
free_custom_wave(custom_wave);
return NULL;
}
if ((param = new_param_double("b", P_FLAG_DONT_FREE_MATRIX | P_FLAG_PER_POINT, &custom_wave->b, custom_wave->b_mesh, 1.0, 0.0, .5)) == NULL){
free_custom_wave(custom_wave);
return NULL;
}
if (insert_param(param, custom_wave->param_tree) < 0) {
free_custom_wave(custom_wave);
return NULL;
}
if ((param = new_param_double("a", P_FLAG_DONT_FREE_MATRIX | P_FLAG_PER_POINT, &custom_wave->a, custom_wave->a_mesh, 1.0, 0.0, .5)) == NULL){
free_custom_wave(custom_wave);
return NULL;
}
if (insert_param(param, custom_wave->param_tree) < 0) {
free_custom_wave(custom_wave);
return NULL;
}
if ((param = new_param_double("x", P_FLAG_DONT_FREE_MATRIX | P_FLAG_PER_POINT, &custom_wave->x, custom_wave->x_mesh, 1.0, 0.0, .5)) == NULL) {
free_custom_wave(custom_wave);
return NULL;
}
if (insert_param(param, custom_wave->param_tree) < 0) {
free_custom_wave(custom_wave);
return NULL;
}
if ((param = new_param_double("y", P_FLAG_DONT_FREE_MATRIX | P_FLAG_PER_POINT, &custom_wave->y, custom_wave->y_mesh, 1.0, 0.0, .5)) == NULL) {
free_custom_wave(custom_wave);
return NULL;
}
if (insert_param(param, custom_wave->param_tree) < 0) {
free_custom_wave(custom_wave);
return NULL;
}
if ((param = new_param_bool("enabled", P_FLAG_NONE, &custom_wave->enabled, 1, 0, 0)) == NULL) {
free_custom_wave(custom_wave);
return NULL;
}
if (insert_param(param, custom_wave->param_tree) < 0) {
free_custom_wave(custom_wave);
return NULL;
}
if ((param = new_param_int("sep", P_FLAG_NONE, &custom_wave->sep, 100, -100, 0)) == NULL) {
free_custom_wave(custom_wave);
return NULL;
}
if (insert_param(param, custom_wave->param_tree) < 0) {
free_custom_wave(custom_wave);
return NULL;
}
if ((param = new_param_bool("bSpectrum", P_FLAG_NONE, &custom_wave->bSpectrum, 1, 0, 0)) == NULL) {
free_custom_wave(custom_wave);
return NULL;
}
if (insert_param(param, custom_wave->param_tree) < 0) {
free_custom_wave(custom_wave);
return NULL;
}
if ((param = new_param_bool("bDrawThick", P_FLAG_NONE, &custom_wave->bDrawThick, 1, 0, 0)) == NULL) {
free_custom_wave(custom_wave);
return NULL;
}
if (insert_param(param, custom_wave->param_tree) < 0) {
free_custom_wave(custom_wave);
return NULL;
}
if ((param = new_param_bool("bUseDots", P_FLAG_NONE, &custom_wave->bUseDots, 1, 0, 0)) == NULL) {
free_custom_wave(custom_wave);
return NULL;
}
if (insert_param(param, custom_wave->param_tree) < 0) {
free_custom_wave(custom_wave);
return NULL;
}
if ((param = new_param_bool("bAdditive", P_FLAG_NONE, &custom_wave->bAdditive, 1, 0, 0)) == NULL) {
free_custom_wave(custom_wave);
return NULL;
}
if (insert_param(param, custom_wave->param_tree) < 0) {
free_custom_wave(custom_wave);
return NULL;
}
if ((param = new_param_int("samples", P_FLAG_NONE, &custom_wave->samples, 2048, 1, 512)) == NULL) {
free_custom_wave(custom_wave);
return NULL;
}
if (insert_param(param, custom_wave->param_tree) < 0) {
free_custom_wave(custom_wave);
return NULL;
}
if ((param = new_param_double("sample", P_FLAG_READONLY | P_FLAG_DONT_FREE_MATRIX | P_FLAG_ALWAYS_MATRIX | P_FLAG_PER_POINT,
&custom_wave->sample, custom_wave->sample_mesh, 1.0, 0.0, 0.0)) == NULL) {
free_custom_wave(custom_wave);
return NULL;
}
if (insert_param(param, custom_wave->param_tree) < 0) {
printf("failed to insert sample\n");
free_custom_wave(custom_wave);
return NULL;
}
if ((param = new_param_double("value1", P_FLAG_READONLY | P_FLAG_DONT_FREE_MATRIX | P_FLAG_ALWAYS_MATRIX | P_FLAG_PER_POINT, &custom_wave->v1, custom_wave->value1, 1.0, -1.0, 0.0)) == NULL) {
free_custom_wave(custom_wave);
return NULL;
}
if (insert_param(param, custom_wave->param_tree) < 0) {
free_custom_wave(custom_wave);
return NULL;
}
if ((param = new_param_double("value2", P_FLAG_READONLY | P_FLAG_DONT_FREE_MATRIX | P_FLAG_ALWAYS_MATRIX | P_FLAG_PER_POINT, &custom_wave->v2, custom_wave->value2, 1.0, -1.0, 0.0)) == NULL) {
free_custom_wave(custom_wave);
return NULL;
}
if (insert_param(param, custom_wave->param_tree) < 0) {
free_custom_wave(custom_wave);
return NULL;
}
if ((param = new_param_double("smoothing", P_FLAG_NONE, &custom_wave->smoothing, NULL, 1.0, 0.0, 0.0)) == NULL) {
free_custom_wave(custom_wave);
return NULL;
}
if (insert_param(param, custom_wave->param_tree) < 0) {
free_custom_wave(custom_wave);
return NULL;
}
if ((param = new_param_double("scaling", P_FLAG_NONE, &custom_wave->scaling, NULL, MAX_DOUBLE_SIZE, 0.0, 1.0)) == NULL) {
free_custom_wave(custom_wave);
return NULL;
}
if (insert_param(param, custom_wave->param_tree) < 0) {
free_custom_wave(custom_wave);
return NULL;
}
if ((param = new_param_double("t1", P_FLAG_PER_POINT | P_FLAG_TVAR, &custom_wave->t1, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
free_custom_wave(custom_wave);
return NULL;
}
if (insert_param(param, custom_wave->param_tree) < 0) {
free_custom_wave(custom_wave);
return NULL;
}
if ((param = new_param_double("t2", P_FLAG_PER_POINT |P_FLAG_TVAR, &custom_wave->t2, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
free_custom_wave(custom_wave);
return NULL;
}
if (insert_param(param, custom_wave->param_tree) < 0) {
free_custom_wave(custom_wave);
return NULL;
}
if ((param = new_param_double("t3", P_FLAG_PER_POINT |P_FLAG_TVAR, &custom_wave->t3, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
free_custom_wave(custom_wave);
return NULL;
}
if (insert_param(param, custom_wave->param_tree) < 0) {
free_custom_wave(custom_wave);
return NULL;
}
if ((param = new_param_double("t4", P_FLAG_PER_POINT |P_FLAG_TVAR, &custom_wave->t4, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
free_custom_wave(custom_wave);
return NULL;
}
if (insert_param(param, custom_wave->param_tree) < 0) {
free_custom_wave(custom_wave);
return NULL;
}
if ((param = new_param_double("t5", P_FLAG_TVAR, &custom_wave->t5, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
free_custom_wave(custom_wave);
return NULL;
}
if (insert_param(param, custom_wave->param_tree) < 0) {
free_custom_wave(custom_wave);
return NULL;
}
if ((param = new_param_double("t6", P_FLAG_TVAR | P_FLAG_PER_POINT, &custom_wave->t6, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
free_custom_wave(custom_wave);
return NULL;
}
if (insert_param(param, custom_wave->param_tree) < 0) {
free_custom_wave(custom_wave);
return NULL;
}
if ((param = new_param_double("t7", P_FLAG_TVAR | P_FLAG_PER_POINT, &custom_wave->t7, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
free_custom_wave(custom_wave);
return NULL;
}
if (insert_param(param, custom_wave->param_tree) < 0) {
free_custom_wave(custom_wave);
return NULL;
}
if ((param = new_param_double("t8", P_FLAG_TVAR | P_FLAG_PER_POINT, &custom_wave->t8, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
free_custom_wave(custom_wave);
return NULL;
}
if (insert_param(param, custom_wave->param_tree) < 0) {
free_custom_wave(custom_wave);
return NULL;
}
/* End of parameter loading. Note that the read only parameters associated
with custom waves (ie, sample) are global variables, and not specific to
the custom wave datastructure. */
return custom_wave;
}
void destroy_per_frame_init_eqn_tree(splaytree_t * tree) {
if (!tree)
return;
splay_traverse(free_init_cond, tree);
destroy_splaytree(tree);
}
void destroy_per_point_eqn_tree(splaytree_t * tree) {
if (!tree)
return;
splay_traverse(free_per_point_eqn, tree);
destroy_splaytree(tree);
}
void destroy_init_cond_tree(splaytree_t * tree) {
if (!tree)
return;
splay_traverse(free_init_cond, tree);
destroy_splaytree(tree);
}
void destroy_per_frame_eqn_tree(splaytree_t * tree) {
if (!tree)
return;
splay_traverse(free_per_frame_eqn, tree);
destroy_splaytree(tree);
}
void destroy_param_db_tree(splaytree_t * tree) {
if (!tree)
return;
splay_traverse(free_param, tree);
destroy_splaytree(tree);
}
/* Frees a custom wave form object */
void free_custom_wave(custom_wave_t * custom_wave) {
if (custom_wave == NULL)
return;
if (custom_wave->param_tree == NULL)
return;
destroy_per_point_eqn_tree(custom_wave->per_point_eqn_tree);
destroy_per_frame_eqn_tree(custom_wave->per_frame_eqn_tree);
destroy_init_cond_tree(custom_wave->init_cond_tree);
destroy_param_db_tree(custom_wave->param_tree);
destroy_per_frame_init_eqn_tree(custom_wave->per_frame_init_eqn_tree);
free(custom_wave->r_mesh);
free(custom_wave->g_mesh);
free(custom_wave->b_mesh);
free(custom_wave->a_mesh);
free(custom_wave->x_mesh);
free(custom_wave->y_mesh);
free(custom_wave->value1);
free(custom_wave->value2);
free(custom_wave->sample_mesh);
free(custom_wave);
return;
}
int add_per_point_eqn(char * name, gen_expr_t * gen_expr, custom_wave_t * custom_wave) {
per_point_eqn_t * per_point_eqn;
int index;
param_t * param = NULL;
/* Argument checks */
if (custom_wave == NULL)
return FAILURE;
if (gen_expr == NULL)
return FAILURE;
if (name == NULL)
return FAILURE;
if (CUSTOM_WAVE_DEBUG) printf("add_per_point_eqn: per pixel equation (name = \"%s\")\n", name);
/* Search for the parameter so we know what matrix the per pixel equation is referencing */
if ((param = find_param_db(name, custom_wave->param_tree, TRUE)) == NULL) {
if (CUSTOM_WAVE_DEBUG) printf("add_per_point_eqn: failed to allocate a new parameter!\n");
return FAILURE;
}
/* Find most largest index in the splaytree */
if ((per_point_eqn = splay_find_max(custom_wave->per_point_eqn_tree)) == NULL)
index = 0;
else
index = per_point_eqn->index+1;
/* Create the per pixel equation given the index, parameter, and general expression */
if ((per_point_eqn = new_per_point_eqn(index, param, gen_expr)) == NULL)
return FAILURE;
if (CUSTOM_WAVE_DEBUG)
printf("add_per_point_eqn: created new equation (index = %d) (name = \"%s\")\n", per_point_eqn->index, per_point_eqn->param->name);
/* Insert the per pixel equation into the preset per pixel database */
if (splay_insert(per_point_eqn, &per_point_eqn->index, custom_wave->per_point_eqn_tree) < 0) {
free_per_point_eqn(per_point_eqn);
return FAILURE;
}
/* Done */
return SUCCESS;
}
per_point_eqn_t * new_per_point_eqn(int index, param_t * param, gen_expr_t * gen_expr) {
per_point_eqn_t * per_point_eqn;
if (param == NULL)
return NULL;
if (gen_expr == NULL)
return NULL;
if ((per_point_eqn = (per_point_eqn_t*)malloc(sizeof(per_point_eqn_t))) == NULL)
return NULL;
per_point_eqn->index = index;
per_point_eqn->gen_expr = gen_expr;
per_point_eqn->param = param;
return per_point_eqn;
}
void free_per_point_eqn(per_point_eqn_t * per_point_eqn) {
if (per_point_eqn == NULL)
return;
free_gen_expr(per_point_eqn->gen_expr);
free(per_point_eqn);
return;
}
custom_wave_t * find_custom_wave(int id, preset_t * preset, int create_flag) {
custom_wave_t * custom_wave = NULL;
if (preset == NULL)
return NULL;
if ((custom_wave = splay_find(&id, preset->custom_wave_tree)) == NULL) {
if (CUSTOM_WAVE_DEBUG) { printf("find_custom_wave: creating custom wave (id = %d)...", id);fflush(stdout);}
if (create_flag == FALSE) {
if (CUSTOM_WAVE_DEBUG) printf("you specified not to (create flag = false), returning null\n");
return NULL;
}
if ((custom_wave = new_custom_wave(id)) == NULL) {
if (CUSTOM_WAVE_DEBUG) printf("failed...out of memory?\n");
return NULL;
}
if (CUSTOM_WAVE_DEBUG) {printf("success.Inserting..."); fflush(stdout);}
if (splay_insert(custom_wave, &custom_wave->id, preset->custom_wave_tree) < 0) {
if (CUSTOM_WAVE_DEBUG) printf("failed!\n");
free_custom_wave(custom_wave);
return NULL;
}
if (CUSTOM_WAVE_DEBUG) printf("done.\n");
}
return custom_wave;
}
/* Interface function. Makes another custom wave the current
concern for per frame / point equations */
custom_wave_t * nextCustomWave() {
if ((interface_wave = splay_find(&interface_id, active_preset->custom_wave_tree)) == NULL) {
interface_id = 0;
return NULL;
}
interface_id++;
/* Evaluate all per frame equations associated with this wave */
splay_traverse(eval_per_frame_eqn, interface_wave->per_frame_eqn_tree);
return interface_wave;
}
void evalPerPointEqns() {
int x;
for (x = 0; x < interface_wave->samples; x++)
interface_wave->r_mesh[x] = interface_wave->r;
for (x = 0; x < interface_wave->samples; x++)
interface_wave->g_mesh[x] = interface_wave->g;
for (x = 0; x < interface_wave->samples; x++)
interface_wave->b_mesh[x] = interface_wave->b;
for (x = 0; x < interface_wave->samples; x++)
interface_wave->a_mesh[x] = interface_wave->a;
for (x = 0; x < interface_wave->samples; x++)
interface_wave->x_mesh[x] = interface_wave->x;
for (x = 0; x < interface_wave->samples; x++)
interface_wave->y_mesh[x] = interface_wave->y;
/* Evaluate per pixel equations */
splay_traverse(evalPerPointEqn, interface_wave->per_point_eqn_tree);
/* Reset index */
mesh_i = -1;
}
/* Evaluates a per point equation for the current custom wave given by interface_wave ptr */
static inline void evalPerPointEqn(per_point_eqn_t * per_point_eqn) {
int samples, size;
double * param_matrix;
gen_expr_t * eqn_ptr;
samples = interface_wave->samples;
eqn_ptr = per_point_eqn->gen_expr;
if (per_point_eqn->param->matrix == NULL) {
if ((param_matrix = per_point_eqn->param->matrix = malloc(size = samples*sizeof(double))) == NULL)
return;
memset(param_matrix, 0, size);
}
else
param_matrix = (double*)per_point_eqn->param->matrix;
for (mesh_i = 0; mesh_i < samples; mesh_i++) {
param_matrix[mesh_i] = eval_gen_expr(eqn_ptr);
}
/* Now that this parameter has been referenced with a per
point equation, we let the evaluator know by setting
this flag */
per_point_eqn->param->matrix_flag = 1;
}
void load_unspecified_init_conds(custom_wave_t * custom_wave) {
interface_wave = custom_wave;
splay_traverse(load_unspec_init_cond, interface_wave->param_tree);
interface_wave = NULL;
}
void load_unspec_init_cond(param_t * param) {
init_cond_t * init_cond;
value_t init_val;
/* Don't count these parameters as initial conditions */
if (param->flags & P_FLAG_READONLY)
return;
if (param->flags & P_FLAG_QVAR)
return;
if (param->flags & P_FLAG_TVAR)
return;
if (param->flags & P_FLAG_USERDEF)
return;
/* If initial condition was not defined by the preset file, force a default one
with the following code */
if ((init_cond = splay_find(param->name, interface_wave->init_cond_tree)) == NULL) {
/* Make sure initial condition does not exist in the set of per frame initial equations */
if ((init_cond = splay_find(param->name, interface_wave->per_frame_init_eqn_tree)) != NULL)
return;
if (param->type == P_TYPE_BOOL)
init_val.bool_val = 0;
else if (param->type == P_TYPE_INT)
init_val.int_val = *(int*)param->engine_val;
else if (param->type == P_TYPE_DOUBLE)
init_val.double_val = *(double*)param->engine_val;
//printf("%s\n", param->name);
/* Create new initial condition */
if ((init_cond = new_init_cond(param, init_val)) == NULL)
return;
/* Insert the initial condition into this presets tree */
if (splay_insert(init_cond, init_cond->param->name, interface_wave->init_cond_tree) < 0) {
free_init_cond(init_cond);
return;
}
}
}
void evalCustomWaveInitConditions() {
splay_traverse(eval_custom_wave_init_conds, active_preset->custom_wave_tree);
}
#ifndef CUSTOM_WAVE_H
#define CUSTOM_WAVE_H
#define CUSTOM_WAVE_DEBUG 0
#include "expr_types.h"
#include "custom_wave_types.h"
#include "preset_types.h"
#include "splaytree.h"
#include "init_cond.h"
void free_custom_wave(custom_wave_t * custom_wave);
custom_wave_t * new_custom_wave(int id);
void free_per_point_eqn(per_point_eqn_t * per_point_eqn);
per_point_eqn_t * new_per_point_eqn(int index, param_t * param,gen_expr_t * gen_expr);
void reset_per_point_eqn_array(custom_wave_t * custom_wave);
custom_wave_t * find_custom_wave(int id, preset_t * preset, int create_flag);
int add_per_point_eqn(char * name, gen_expr_t * gen_expr, custom_wave_t * custom_wave);
void evalCustomWaveInitConditions();
void evalPerPointEqns();
custom_wave_t * nextCustomWave();
void load_unspecified_init_conds(custom_wave_t * custom_wave);
static inline void eval_custom_wave_init_conds(custom_wave_t * custom_wave) {
splay_traverse(eval_init_cond, custom_wave->init_cond_tree);
splay_traverse(eval_init_cond, custom_wave->per_frame_init_eqn_tree);
}
#endif
#ifndef CUSTOM_WAVE_TYPES_H
#define CUSTOM_WAVE_TYPES_H
#include "common.h"
#include "splaytree_types.h"
#include "expr_types.h"
#define X_POINT_OP 0
#define Y_POINT_OP 1
#define R_POINT_OP 2
#define G_POINT_OP 3
#define B_POINT_OP 4
#define A_POINT_OP 5
#define NUM_POINT_OPS 6
typedef struct PER_POINT_EQN_T {
int index;
param_t * param;
gen_expr_t * gen_expr;
} per_point_eqn_t;
typedef struct CUSTOM_WAVE_T {
/* Numerical id */
int id;
int per_frame_count;
/* Parameter tree associated with this custom wave */
splaytree_t * param_tree;
/* Engine variables */
double x; /* x position for per point equations */
double y; /* y position for per point equations */
double r; /* red color value */
double g; /* green color value */
double b; /* blue color value */
double a; /* alpha color value */
double * x_mesh;
double * y_mesh;
double * r_mesh;
double * b_mesh;
double * g_mesh;
double * a_mesh;
double * value1;
double * value2;
double * sample_mesh;
int enabled; /* if nonzero then wave is visible, hidden otherwise */
int samples; /* number of samples associated with this wave form. Usually powers of 2 */
double sample;
int bSpectrum; /* spectrum data or pcm data */
int bUseDots; /* draw wave as dots or lines */
int bDrawThick; /* draw thicker lines */
int bAdditive; /* add color values together */
double scaling; /* scale factor of waveform */
double smoothing; /* smooth factor of waveform */
int sep; /* no idea what this is yet... */
/* stupid t variables */
double t1;
double t2;
double t3;
double t4;
double t5;
double t6;
double t7;
double t8;
double v1,v2;
/* Data structure to hold per frame and per point equations */
splaytree_t * init_cond_tree;
splaytree_t * per_frame_eqn_tree;
splaytree_t * per_point_eqn_tree;
splaytree_t * per_frame_init_eqn_tree;
/* Denotes the index of the last character for each string buffer */
int per_point_eqn_string_index;
int per_frame_eqn_string_index;
int per_frame_init_eqn_string_index;
/* String buffers for per point and per frame equations */
char per_point_eqn_string_buffer[STRING_BUFFER_SIZE];
char per_frame_eqn_string_buffer[STRING_BUFFER_SIZE];
char per_frame_init_eqn_string_buffer[STRING_BUFFER_SIZE];
/* Per point equation array */
gen_expr_t * per_point_eqn_array[NUM_POINT_OPS];
} custom_wave_t;
#endif
/*****************************************************************************
* engine_vars.c:
*****************************************************************************
* Copyright (C) 2004 the VideoLAN team
* $Id$
*
* Authors: Cyril Deguet <asmax@videolan.org>
* code from projectM http://xmms-projectm.sourceforge.net
*
* 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/* Include engine_vars.h to use these variables */
char preset_name[256];
/* PER FRAME CONSTANTS BEGIN */
double zoom=1.0;
double zoomexp= 1.0;
double rot= 0.0;
double warp= 0.0;
double sx= 1.0;
double sy= 1.0;
double dx= 0.0;
double dy= 0.0;
double cx= 0.5;
double cy= 0.5;
int gx = 32;
int gy = 24;
double decay=.98;
double wave_r= 1.0;
double wave_g= 0.2;
double wave_b= 0.0;
double wave_x= 0.5;
double wave_y= 0.5;
double wave_mystery= 0.0;
double ob_size= 0.0;
double ob_r= 0.0;
double ob_g= 0.0;
double ob_b= 0.0;
double ob_a= 0.0;
double ib_size = 0.0;
double ib_r = 0.0;
double ib_g = 0.0;
double ib_b = 0.0;
double ib_a = 0.0;
double mv_a = 0.0;
double mv_r = 0.0;
double mv_g = 0.0;
double mv_b = 0.0;
double mv_l = 1.0;
double mv_x = 16.0;
double mv_y = 12.0;
double mv_dy = 0.02;
double mv_dx = 0.02;
int meshx = 0;
int meshy = 0;
double Time = 0;
double treb = 0;
double mid = 0;
double bass = 0;
double treb_att = 0;
double mid_att = 0;
double bass_att = 0;
double progress = 0;
int frame = 0;
int fps = 30;
//double bass_thresh = 0;
/* PER_FRAME CONSTANTS END */
double fRating = 0;
double fGammaAdj = 1.0;
double fVideoEchoZoom = 1.0;
double fVideoEchoAlpha = 0;
double nVideoEchoOrientation = 0;
int nWaveMode = 7;
int bAdditiveWaves = 0;
int bWaveDots = 0;
int bWaveThick = 0;
int bModWaveAlphaByVolume = 0;
int bMaximizeWaveColor = 0;
int bTexWrap = 0;
int bDarkenCenter = 0;
int bRedBlueStereo = 0;
int bBrighten = 0;
int bDarken = 0;
int bSolarize = 0;
int bInvert = 0;
int bMotionVectorsOn = 1;
double fWaveAlpha =1.0;
double fWaveScale = 1.0;
double fWaveSmoothing = 0;
double fWaveParam = 0;
double fModWaveAlphaStart = 0;
double fModWaveAlphaEnd = 0;
double fWarpAnimSpeed = 0;
double fWarpScale = 0;
double fShader = 0;
/* PER_PIXEL CONSTANTS BEGIN */
double x_per_pixel = 0;
double y_per_pixel = 0;
double rad_per_pixel = 0;
double ang_per_pixel = 0;
/* PER_PIXEL CONSTANT END */
/* Q AND T VARIABLES START */
double q1 = 0;
double q2 = 0;
double q3 = 0;
double q4 = 0;
double q5 = 0;
double q6 = 0;
double q7 = 0;
double q8 = 0;
/* Q AND T VARIABLES END */
//per pixel meshes
double **zoom_mesh;
double **zoomexp_mesh;
double **rot_mesh;
double **sx_mesh;
double **sy_mesh;
double **dx_mesh;
double **dy_mesh;
double **cx_mesh;
double **cy_mesh;
double **x_mesh;
double **y_mesh;
double **rad_mesh;
double **theta_mesh;
//custom wave per point meshes
/* Temporay file until these variables are all externed */
#ifndef ENGINE_VARS_H
#define ENGINE_VARS_H
extern char preset_name[256];
/* PER FRAME CONSTANTS BEGIN */
extern double zoom;
extern double zoomexp;
extern double rot;
extern double warp;
extern double sx;
extern double sy;
extern double dx;
extern double dy;
extern double cx;
extern double cy;
extern int gy;
extern int gx;
extern double decay;
extern double wave_r;
extern double wave_g;
extern double wave_b;
extern double wave_x;
extern double wave_y;
extern double wave_mystery;
extern double ob_size;
extern double ob_r;
extern double ob_g;
extern double ob_b;
extern double ob_a;
extern double ib_size;
extern double ib_r;
extern double ib_g;
extern double ib_b;
extern double ib_a;
extern int meshx;
extern int meshy;
extern double mv_a ;
extern double mv_r ;
extern double mv_g ;
extern double mv_b ;
extern double mv_l;
extern double mv_x;
extern double mv_y;
extern double mv_dy;
extern double mv_dx;
extern double Time;
extern double treb ;
extern double mid ;
extern double bass ;
extern double treb_att ;
extern double mid_att ;
extern double bass_att ;
extern double progress ;
extern int frame ;
/* PER_FRAME CONSTANTS END */
/* PER_PIXEL CONSTANTS BEGIN */
extern double x_per_pixel;
extern double y_per_pixel;
extern double rad_per_pixel;
extern double ang_per_pixel;
/* PER_PIXEL CONSTANT END */
extern double fRating;
extern double fGammaAdj;
extern double fVideoEchoZoom;
extern double fVideoEchoAlpha;
extern int nVideoEchoOrientation;
extern int nWaveMode;
extern int bAdditiveWaves;
extern int bWaveDots;
extern int bWaveThick;
extern int bModWaveAlphaByVolume;
extern int bMaximizeWaveColor;
extern int bTexWrap;
extern int bDarkenCenter;
extern int bRedBlueStereo;
extern int bBrighten;
extern int bDarken;
extern int bSolarize;
extern int bInvert;
extern int bMotionVectorsOn;
extern int fps;
extern double fWaveAlpha ;
extern double fWaveScale;
extern double fWaveSmoothing;
extern double fWaveParam;
extern double fModWaveAlphaStart;
extern double fModWaveAlphaEnd;
extern double fWarpAnimSpeed;
extern double fWarpScale;
extern double fShader;
/* Q VARIABLES START */
extern double q1;
extern double q2;
extern double q3;
extern double q4;
extern double q5;
extern double q6;
extern double q7;
extern double q8;
/* Q VARIABLES END */
extern double **zoom_mesh;
extern double **zoomexp_mesh;
extern double **rot_mesh;
extern double **sx_mesh;
extern double **sy_mesh;
extern double **dx_mesh;
extern double **dy_mesh;
extern double **cx_mesh;
extern double **cy_mesh;
extern double **x_mesh;
extern double **y_mesh;
extern double **rad_mesh;
extern double **theta_mesh;
#endif
/*****************************************************************************
* eval.c:
*****************************************************************************
* Copyright (C) 2004 the VideoLAN team
* $Id$
*
* Authors: Cyril Deguet <asmax@videolan.org>
* code from projectM http://xmms-projectm.sourceforge.net
*
* 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#include <stdlib.h>
/* Evaluation Code */
#include <stdio.h>
#include "common.h"
#include "fatal.h"
#include "param_types.h"
#include "func_types.h"
#include "expr_types.h"
#include "eval.h"
#include "engine_vars.h"
#include "builtin_funcs.h"
#define EVAL_ERROR -1
/* All infix operators (except '=') are prototyped here */
infix_op_t * infix_add, * infix_minus, * infix_div, * infix_mult,
* infix_or, * infix_and, * infix_mod, * infix_negative, * infix_positive;
int mesh_i=-1, mesh_j=-1;
static inline double eval_tree_expr(tree_expr_t * tree_expr);
static inline double eval_prefun_expr(prefun_expr_t * prefun_expr);
static inline double eval_val_expr(val_expr_t * val_expr);
double eval_gen_expr(gen_expr_t * gen_expr) {
double l;
if (gen_expr == NULL)
return 0;
switch(gen_expr->type) {
case VAL_T:
return eval_val_expr(gen_expr->item);
case PREFUN_T:
l = eval_prefun_expr(gen_expr->item);
//if (EVAL_DEBUG) printf("eval_gen_expr: prefix function return value: %f\n", l);
return l;
case TREE_T:
return eval_tree_expr(gen_expr->item);
default:
#ifdef EVAL_DEBUG
printf("eval_gen_expr: general expression matched no cases!\n");
#endif
return EVAL_ERROR;
}
}
/* Evaluates functions in prefix form */
static inline double eval_prefun_expr(prefun_expr_t * prefun_expr) {
int i;
/* This is slightly less than safe, since
who knows if the passed argument is valid. For
speed purposes we'll go with this */
double arg_list[prefun_expr->num_args];
#ifdef EVAL_DEBUG
printf("fn[");
fflush(stdout);
#endif
/* Evaluate each argument before calling the function itself */
for (i = 0; i < prefun_expr->num_args; i++) {
arg_list[i] = eval_gen_expr(prefun_expr->expr_list[i]);
#ifdef EVAL_DEBUG
if (i < (prefun_expr->num_args - 1))
printf(", ");
fflush(stdout);
#endif
}
#ifdef EVAL_DEBUG
printf("]");
fflush(stdout);
#endif
/* Now we call the function, passing a list of
doubles as its argument */
return (prefun_expr->func_ptr)(arg_list);
}
/* Evaluates a value expression */
static inline double eval_val_expr(val_expr_t * val_expr) {
/* Shouldn't happen */
if (val_expr == NULL)
return EVAL_ERROR;
/* Value is a constant, return the double value */
if (val_expr->type == CONSTANT_TERM_T) {
#ifdef EVAL_DEBUG
printf("%.4f", val_expr->term.constant);
fflush(stdout);
#endif
return (val_expr->term.constant);
}
/* Value is variable, dereference it */
if (val_expr->type == PARAM_TERM_T) {
switch (val_expr->term.param->type) {
case P_TYPE_BOOL:
#ifdef EVAL_DEBUG
printf("(%s:%.4f)", val_expr->term.param->name, (double)(*((int*)(val_expr->term.param->engine_val))));
fflush(stdout);
#endif
return (double)(*((int*)(val_expr->term.param->engine_val)));
case P_TYPE_INT:
#ifdef EVAL_DEBUG
printf("(%s:%.4f)", val_expr->term.param->name, (double)(*((int*)(val_expr->term.param->engine_val))));
fflush(stdout);
#endif
return (double)(*((int*)(val_expr->term.param->engine_val)));
case P_TYPE_DOUBLE:
#ifdef EVAL_DEBUG
printf("(%s:%.4f)", val_expr->term.param->name, (*((double*)val_expr->term.param->engine_val)));
fflush(stdout);
#endif
if (val_expr->term.param->matrix_flag | (val_expr->term.param->flags & P_FLAG_ALWAYS_MATRIX)) {
if (mesh_j >= 0) {
return (((double**)val_expr->term.param->matrix)[mesh_i][mesh_j]);
}
else {
return (((double*)val_expr->term.param->matrix)[mesh_i]);
}
}
return *((double*)(val_expr->term.param->engine_val));
default:
return ERROR;
}
}
/* Unknown type, return failure */
return FAILURE;
}
/* Evaluates an expression tree */
static inline double eval_tree_expr(tree_expr_t * tree_expr) {
double left_arg, right_arg;
infix_op_t * infix_op;
/* Shouldn't happen */
if (tree_expr == NULL)
return EVAL_ERROR;
/* A leaf node, evaluate the general expression. If the expression is null as well, return zero */
if (tree_expr->infix_op == NULL) {
if (tree_expr->gen_expr == NULL)
return 0;
else
return eval_gen_expr(tree_expr->gen_expr);
}
/* Otherwise, this node is an infix operator. Evaluate
accordingly */
infix_op = (infix_op_t*)tree_expr->infix_op;
#ifdef EVAL_DEBUG
printf("(");
fflush(stdout);
#endif
left_arg = eval_tree_expr(tree_expr->left);
#ifdef EVAL_DEBUG
switch (infix_op->type) {
case INFIX_ADD:
printf("+");
break;
case INFIX_MINUS:
printf("-");
break;
case INFIX_MULT:
printf("*");
break;
case INFIX_MOD:
printf("%%");
break;
case INFIX_OR:
printf("|");
break;
case INFIX_AND:
printf("&");
break;
case INFIX_DIV:
printf("/");
break;
default:
printf("?");
}
fflush(stdout);
#endif
right_arg = eval_tree_expr(tree_expr->right);
#ifdef EVAL_DEBUG
printf(")");
fflush(stdout);
#endif
switch (infix_op->type) {
case INFIX_ADD:
return (left_arg + right_arg);
case INFIX_MINUS:
return (left_arg - right_arg);
case INFIX_MULT:
return (left_arg * right_arg);
case INFIX_MOD:
if ((int)right_arg == 0) {
#ifdef EVAL_DEBUG
printf("eval_tree_expr: modulo zero!\n");
#endif
return DIV_BY_ZERO;
}
return ((int)left_arg % (int)right_arg);
case INFIX_OR:
return ((int)left_arg | (int)right_arg);
case INFIX_AND:
return ((int)left_arg & (int)right_arg);
case INFIX_DIV:
if (right_arg == 0) {
#ifdef EVAL_DEBUG
printf("eval_tree_expr: division by zero!\n");
#endif
return MAX_DOUBLE_SIZE;
}
return (left_arg / right_arg);
default:
#ifdef EVAL_DEBUG
printf("eval_tree_expr: unknown infix operator!\n");
#endif
return ERROR;
}
return ERROR;
}
/* Converts a double value to a general expression */
gen_expr_t * const_to_expr(double val) {
gen_expr_t * gen_expr;
val_expr_t * val_expr;
term_t term;
term.constant = val;
if ((val_expr = new_val_expr(CONSTANT_TERM_T, term)) == NULL)
return NULL;
gen_expr = new_gen_expr(VAL_T, (void*)val_expr);
if (gen_expr == NULL) {
free_val_expr(val_expr);
}
return gen_expr;
}
/* Converts a regular parameter to an expression */
gen_expr_t * param_to_expr(param_t * param) {
gen_expr_t * gen_expr = NULL;
val_expr_t * val_expr = NULL;
term_t term;
if (param == NULL)
return NULL;
/* This code is still a work in progress. We need
to figure out if the initial condition is used for
each per frame equation or not. I am guessing that
it isn't, and it is thusly implemented this way */
/* Current guess of true behavior (08/01/03) note from carm
First try to use the per_pixel_expr (with cloning).
If it is null however, use the engine variable instead. */
/* 08/20/03 : Presets are now objects, as well as per pixel equations. This ends up
making the parser handle the case where parameters are essentially per pixel equation
substitutions */
term.param = param;
if ((val_expr = new_val_expr(PARAM_TERM_T, term)) == NULL)
return NULL;
if ((gen_expr = new_gen_expr(VAL_T, (void*)val_expr)) == NULL) {
free_val_expr(val_expr);
return NULL;
}
return gen_expr;
}
/* Converts a prefix function to an expression */
gen_expr_t * prefun_to_expr(double (*func_ptr)(), gen_expr_t ** expr_list, int num_args) {
gen_expr_t * gen_expr;
prefun_expr_t * prefun_expr;
/* Malloc a new prefix function expression */
prefun_expr = (prefun_expr_t*)malloc(sizeof(prefun_expr_t));
if (prefun_expr == NULL)
return NULL;
prefun_expr->num_args = num_args;
prefun_expr->func_ptr = func_ptr;
prefun_expr->expr_list = expr_list;
gen_expr = new_gen_expr(PREFUN_T, (void*)prefun_expr);
if (gen_expr == NULL)
free_prefun_expr(prefun_expr);
return gen_expr;
}
/* Creates a new tree expression */
tree_expr_t * new_tree_expr(infix_op_t * infix_op, gen_expr_t * gen_expr, tree_expr_t * left, tree_expr_t * right) {
tree_expr_t * tree_expr;
tree_expr = (tree_expr_t*)malloc(sizeof(tree_expr_t));
if (tree_expr == NULL)
return NULL;
tree_expr->infix_op = infix_op;
tree_expr->gen_expr = gen_expr;
tree_expr->left = left;
tree_expr->right = right;
return tree_expr;
}
/* Creates a new value expression */
val_expr_t * new_val_expr(int type, term_t term) {
val_expr_t * val_expr;
val_expr = (val_expr_t*)malloc(sizeof(val_expr_t));
if (val_expr == NULL)
return NULL;
val_expr->type = type;
val_expr->term = term;
return val_expr;
}
/* Creates a new general expression */
gen_expr_t * new_gen_expr(int type, void * item) {
gen_expr_t * gen_expr;
gen_expr = (gen_expr_t*)malloc(sizeof(gen_expr_t));
if (gen_expr == NULL)
return NULL;
gen_expr->type = type;
gen_expr->item = item;
return gen_expr;
}
/* Frees a general expression */
int free_gen_expr(gen_expr_t * gen_expr) {
if (gen_expr == NULL)
return SUCCESS;
switch (gen_expr->type) {
case VAL_T:
free_val_expr(gen_expr->item);
break;
case PREFUN_T:
free_prefun_expr(gen_expr->item);
break;
case TREE_T:
free_tree_expr(gen_expr->item);
break;
default:
return FAILURE;
}
free(gen_expr);
return SUCCESS;
}
/* Frees a function in prefix notation */
int free_prefun_expr(prefun_expr_t * prefun_expr) {
int i;
if (prefun_expr == NULL)
return SUCCESS;
/* Free every element in expression list */
for (i = 0 ; i < prefun_expr->num_args; i++) {
free_gen_expr(prefun_expr->expr_list[i]);
}
free(prefun_expr);
return SUCCESS;
}
/* Frees values of type VARIABLE and CONSTANT */
int free_val_expr(val_expr_t * val_expr) {
if (val_expr == NULL)
return SUCCESS;
free(val_expr);
return SUCCESS;
}
/* Frees a tree expression */
int free_tree_expr(tree_expr_t * tree_expr) {
if (tree_expr == NULL)
return SUCCESS;
/* free left tree */
free_tree_expr(tree_expr->left);
/* free general expression object */
free_gen_expr(tree_expr->gen_expr);
/* Note that infix operators are always
stored in memory unless the program
exits, so we don't remove them here */
/* free right tree */
free_tree_expr(tree_expr->right);
/* finally, free the struct itself */
free(tree_expr);
return SUCCESS;
}
/* Initializes all infix operators */
int init_infix_ops() {
infix_add = new_infix_op(INFIX_ADD, 4);
infix_minus = new_infix_op(INFIX_MINUS, 3);
infix_div = new_infix_op(INFIX_DIV, 2);
infix_or = new_infix_op(INFIX_OR, 5);
infix_and = new_infix_op(INFIX_AND,4);
infix_mod = new_infix_op(INFIX_MOD, 1);
infix_mult = new_infix_op(INFIX_MULT, 2);
/* Prefix operators */
infix_positive = new_infix_op(INFIX_ADD, 0);
infix_negative = new_infix_op(INFIX_MINUS, 0);
return SUCCESS;
}
/* Destroys the infix operator list. This should
be done on program exit */
int destroy_infix_ops()
{
free(infix_add);
free(infix_minus);
free(infix_div);
free(infix_or);
free(infix_and);
free(infix_mod);
free(infix_mult);
free(infix_positive);
free(infix_negative);
return SUCCESS;
}
/* Initializes an infix operator */
infix_op_t * new_infix_op(int type, int precedence) {
infix_op_t * infix_op;
infix_op = (infix_op_t*)malloc(sizeof(infix_op_t));
if (infix_op == NULL)
return NULL;
infix_op->type = type;
infix_op->precedence = precedence;
return infix_op;
}
/* Clones a general expression */
gen_expr_t * clone_gen_expr(gen_expr_t * gen_expr) {
gen_expr_t * new_gen_expr;
val_expr_t * val_expr;
tree_expr_t * tree_expr;
prefun_expr_t * prefun_expr;
/* Null argument check */
if (gen_expr == NULL)
return NULL;
/* Out of memory */
if ((new_gen_expr = (gen_expr_t*)malloc(sizeof(gen_expr_t))) == NULL)
return NULL;
/* Case on the type of general expression */
switch (new_gen_expr->type = gen_expr->type) {
case VAL_T: /* val expression */
if ((val_expr = clone_val_expr((val_expr_t*)gen_expr->item)) == NULL) {
free(new_gen_expr);
return NULL;
}
new_gen_expr->item = (void*)val_expr;
break;
case PREFUN_T: /* prefix function expression */
if ((prefun_expr = clone_prefun_expr((prefun_expr_t*)gen_expr->item)) == NULL) {
free(new_gen_expr);
return NULL;
}
new_gen_expr->item = (void*)prefun_expr;
break;
case TREE_T: /* tree expression */
if ((tree_expr = clone_tree_expr((tree_expr_t*)gen_expr->item)) == NULL) {
free(new_gen_expr);
return NULL;
}
new_gen_expr->item = (void*)tree_expr;
break;
default: /* unknown type, ut oh.. */
free(new_gen_expr);
return NULL;
}
return new_gen_expr; /* Return the new (cloned) general expression */
}
/* Clones a tree expression */
tree_expr_t * clone_tree_expr(tree_expr_t * tree_expr) {
tree_expr_t * new_tree_expr;
/* Null argument */
if (tree_expr == NULL)
return NULL;
/* Out of memory */
if ((new_tree_expr = (tree_expr_t*)malloc(sizeof(tree_expr_t))) == NULL)
return NULL;
/* Set each argument in tree_expr_t struct */
new_tree_expr->infix_op = tree_expr->infix_op; /* infix operators are in shared memory */
new_tree_expr->gen_expr = clone_gen_expr(tree_expr->gen_expr); /* clone the general expression */
new_tree_expr->left = clone_tree_expr(tree_expr->left); /* clone the left tree expression */
new_tree_expr->right = clone_tree_expr(tree_expr->right); /* clone the right tree expression */
return new_tree_expr; /* Return the new (cloned) tree expression */
}
/* Clones a value expression, currently only passes the pointer to
the value that this object represents, not a pointer to a copy of the value */
val_expr_t * clone_val_expr(val_expr_t * val_expr) {
val_expr_t * new_val_expr;
/* Null argument */
if (val_expr == NULL)
return NULL;
/* Allocate space, check for out of memory */
if ((new_val_expr = (val_expr_t*)malloc(sizeof(val_expr_t))) == NULL)
return NULL;
/* Set the values in the val_expr_t struct */
new_val_expr->type = val_expr->type;
new_val_expr->term = val_expr->term;
/* Return the new (cloned) value expression */
return new_val_expr;
}
/* Clones a prefix function with its arguments */
prefun_expr_t * clone_prefun_expr(prefun_expr_t * prefun_expr) {
int i;
prefun_expr_t * new_prefun_expr;
/* Null argument */
if (prefun_expr == NULL)
return NULL;
/* Out of memory */
if ((new_prefun_expr = (prefun_expr_t*)malloc(sizeof(prefun_expr_t))) == NULL)
return NULL;
/* Set the function argument paired with its number of arguments */
new_prefun_expr->num_args = prefun_expr->num_args;
new_prefun_expr->func_ptr = prefun_expr->func_ptr;
/* Allocate space for the expression list pointers */
if ((new_prefun_expr->expr_list = (gen_expr_t**)malloc(sizeof(gen_expr_t*)*new_prefun_expr->num_args)) == NULL) {
free(new_prefun_expr);
return NULL;
}
/* Now copy each general expression from the argument expression list */
for (i = 0; i < new_prefun_expr->num_args;i++)
new_prefun_expr->expr_list[i] = clone_gen_expr(prefun_expr->expr_list[i]);
/* Finally, return the new (cloned) prefix function expression */
return new_prefun_expr;
}
/* Reinitializes the engine variables to a default (conservative and sane) value */
void reset_engine_vars() {
zoom=1.0;
zoomexp= 1.0;
rot= 0.0;
warp= 0.0;
sx= 1.0;
sy= 1.0;
dx= 0.0;
dy= 0.0;
cx= 0.5;
cy= 0.5;
decay=.98;
wave_r= 1.0;
wave_g= 0.2;
wave_b= 0.0;
wave_x= 0.5;
wave_y= 0.5;
wave_mystery= 0.0;
ob_size= 0.0;
ob_r= 0.0;
ob_g= 0.0;
ob_b= 0.0;
ob_a= 0.0;
ib_size = 0.0;
ib_r = 0.0;
ib_g = 0.0;
ib_b = 0.0;
ib_a = 0.0;
mv_a = 0.0;
mv_r = 0.0;
mv_g = 0.0;
mv_b = 0.0;
mv_l = 1.0;
mv_x = 16.0;
mv_y = 12.0;
mv_dy = 0.02;
mv_dx = 0.02;
meshx = 0;
meshy = 0;
Time = 0;
treb = 0;
mid = 0;
bass = 0;
treb_att = 0;
mid_att = 0;
bass_att = 0;
progress = 0;
frame = 0;
// bass_thresh = 0;
/* PER_FRAME CONSTANTS END */
fRating = 0;
fGammaAdj = 1.0;
fVideoEchoZoom = 1.0;
fVideoEchoAlpha = 0;
nVideoEchoOrientation = 0;
nWaveMode = 7;
bAdditiveWaves = 0;
bWaveDots = 0;
bWaveThick = 0;
bModWaveAlphaByVolume = 0;
bMaximizeWaveColor = 0;
bTexWrap = 0;
bDarkenCenter = 0;
bRedBlueStereo = 0;
bBrighten = 0;
bDarken = 0;
bSolarize = 0;
bInvert = 0;
bMotionVectorsOn = 1;
fWaveAlpha =1.0;
fWaveScale = 1.0;
fWaveSmoothing = 0;
fWaveParam = 0;
fModWaveAlphaStart = 0;
fModWaveAlphaEnd = 0;
fWarpAnimSpeed = 0;
fWarpScale = 0;
fShader = 0;
/* PER_PIXEL CONSTANTS BEGIN */
x_per_pixel = 0;
y_per_pixel = 0;
rad_per_pixel = 0;
ang_per_pixel = 0;
/* PER_PIXEL CONSTANT END */
/* Q VARIABLES START */
q1 = 0;
q2 = 0;
q3 = 0;
q4 = 0;
q5 = 0;
q6 = 0;
q7 = 0;
q8 = 0;
/* Q VARIABLES END */
}
/* eval.h: evaluation functions of expressions */
#ifndef EVAL_H
#define EVAL_H
#include "func_types.h"
#include "param_types.h"
#define VAL_T 1
#define PREFUN_T 3
#define TREE_T 4
#define NONE_T 0
#define CONSTANT_TERM_T 0
#define PARAM_TERM_T 1
#define INFIX_ADD 0
#define INFIX_MINUS 1
#define INFIX_MOD 2
#define INFIX_DIV 3
#define INFIX_MULT 4
#define INFIX_OR 5
#define INFIX_AND 6
//#define EVAL_DEBUG
double eval_gen_expr(gen_expr_t * gen_expr);
inline gen_expr_t * opt_gen_expr(gen_expr_t * gen_expr, int ** param_list);
gen_expr_t * const_to_expr(double val);
gen_expr_t * param_to_expr(struct PARAM_T * param);
gen_expr_t * prefun_to_expr(double (*func_ptr)(), gen_expr_t ** expr_list, int num_args);
tree_expr_t * new_tree_expr(infix_op_t * infix_op, gen_expr_t * gen_expr, tree_expr_t * left, tree_expr_t * right);
gen_expr_t * new_gen_expr(int type, void * item);
val_expr_t * new_val_expr(int type, term_t term);
int free_gen_expr(gen_expr_t * gen_expr);
int free_prefun_expr(prefun_expr_t * prefun_expr);
int free_tree_expr(tree_expr_t * tree_expr);
int free_val_expr(val_expr_t * val_expr);
infix_op_t * new_infix_op(int type, int precedence);
int init_infix_ops();
int destroy_infix_ops();
void reset_engine_vars();
gen_expr_t * clone_gen_expr(gen_expr_t * gen_expr);
tree_expr_t * clone_tree_expr(tree_expr_t * tree_expr);
val_expr_t * clone_val_expr(val_expr_t * val_expr);
prefun_expr_t * clone_prefun_expr(prefun_expr_t * prefun_expr);
#endif
#ifndef EXPR_TYPES_H
#define EXPR_TYPES_H
#include "param_types.h"
#define CONST_STACK_ELEMENT 0
#define EXPR_STACK_ELEMENT 1
/* General Expression Type */
typedef struct GEN_EXPR_T {
int type;
void * item;
} gen_expr_t;
typedef union TERM_T {
double constant; /* static variable */
struct PARAM_T * param; /* pointer to a changing variable */
} term_t;
/* Value expression, contains a term union */
typedef struct VAL_EXPR_T {
int type;
term_t term;
} val_expr_t;
/* Infix Operator Function */
typedef struct INFIX_OP_T {
int type;
int precedence;
} infix_op_t;
/* A binary expression tree ordered by operator precedence */
typedef struct TREE_EXPR_T {
infix_op_t * infix_op; /* null if leaf */
gen_expr_t * gen_expr;
struct TREE_EXPR_T * left, * right;
} tree_expr_t;
/* A function expression in prefix form */
typedef struct PREFUN_EXPR_T {
double (*func_ptr)();
int num_args;
gen_expr_t ** expr_list;
} prefun_expr_t;
#endif
/* Fatal Error Definitions */
#define OUTOFMEM_ERROR -7; /* out of memory */
#define ERROR -1 /* non specific error */
#define SUCCESS 1
#define FAILURE -1
#define PARSE_ERROR -11
#define DIV_BY_ZERO -3
#define OK 2
/*****************************************************************************
* fftsg.c:
*****************************************************************************
* Copyright (C) 2004 the VideoLAN team
* $Id$
*
* Authors: Cyril Deguet <asmax@videolan.org>
* code from projectM http://xmms-projectm.sourceforge.net
*
* 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*
Fast Fourier/Cosine/Sine Transform
dimension :one
data length :power of 2
decimation :frequency
radix :split-radix
data :inplace
table :use
functions
cdft: Complex Discrete Fourier Transform
rdft: Real Discrete Fourier Transform
ddct: Discrete Cosine Transform
ddst: Discrete Sine Transform
dfct: Cosine Transform of RDFT (Real Symmetric DFT)
dfst: Sine Transform of RDFT (Real Anti-symmetric DFT)
function prototypes
void cdft(int, int, double *, int *, double *);
void rdft(int, int, double *, int *, double *);
void ddct(int, int, double *, int *, double *);
void ddst(int, int, double *, int *, double *);
void dfct(int, double *, double *, int *, double *);
void dfst(int, double *, double *, int *, double *);
macro definitions
USE_CDFT_PTHREADS : default=not defined
CDFT_THREADS_BEGIN_N : must be >= 512, default=8192
CDFT_4THREADS_BEGIN_N : must be >= 512, default=65536
USE_CDFT_WINTHREADS : default=not defined
CDFT_THREADS_BEGIN_N : must be >= 512, default=32768
CDFT_4THREADS_BEGIN_N : must be >= 512, default=524288
-------- Complex DFT (Discrete Fourier Transform) --------
[definition]
<case1>
X[k] = sum_j=0^n-1 x[j]*exp(2*pi*i*j*k/n), 0<=k<n
<case2>
X[k] = sum_j=0^n-1 x[j]*exp(-2*pi*i*j*k/n), 0<=k<n
(notes: sum_j=0^n-1 is a summation from j=0 to n-1)
[usage]
<case1>
ip[0] = 0; // first time only
cdft(2*n, 1, a, ip, w);
<case2>
ip[0] = 0; // first time only
cdft(2*n, -1, a, ip, w);
[parameters]
2*n :data length (int)
n >= 1, n = power of 2
a[0...2*n-1] :input/output data (double *)
input data
a[2*j] = Re(x[j]),
a[2*j+1] = Im(x[j]), 0<=j<n
output data
a[2*k] = Re(X[k]),
a[2*k+1] = Im(X[k]), 0<=k<n
ip[0...*] :work area for bit reversal (int *)
length of ip >= 2+sqrt(n)
strictly,
length of ip >=
2+(1<<(int)(log(n+0.5)/log(2))/2).
ip[0],ip[1] are pointers of the cos/sin table.
w[0...n/2-1] :cos/sin table (double *)
w[],ip[] are initialized if ip[0] == 0.
[remark]
Inverse of
cdft(2*n, -1, a, ip, w);
is
cdft(2*n, 1, a, ip, w);
for (j = 0; j <= 2 * n - 1; j++) {
a[j] *= 1.0 / n;
}
.
-------- Real DFT / Inverse of Real DFT --------
[definition]
<case1> RDFT
R[k] = sum_j=0^n-1 a[j]*cos(2*pi*j*k/n), 0<=k<=n/2
I[k] = sum_j=0^n-1 a[j]*sin(2*pi*j*k/n), 0<k<n/2
<case2> IRDFT (excluding scale)
a[k] = (R[0] + R[n/2]*cos(pi*k))/2 +
sum_j=1^n/2-1 R[j]*cos(2*pi*j*k/n) +
sum_j=1^n/2-1 I[j]*sin(2*pi*j*k/n), 0<=k<n
[usage]
<case1>
ip[0] = 0; // first time only
rdft(n, 1, a, ip, w);
<case2>
ip[0] = 0; // first time only
rdft(n, -1, a, ip, w);
[parameters]
n :data length (int)
n >= 2, n = power of 2
a[0...n-1] :input/output data (double *)
<case1>
output data
a[2*k] = R[k], 0<=k<n/2
a[2*k+1] = I[k], 0<k<n/2
a[1] = R[n/2]
<case2>
input data
a[2*j] = R[j], 0<=j<n/2
a[2*j+1] = I[j], 0<j<n/2
a[1] = R[n/2]
ip[0...*] :work area for bit reversal (int *)
length of ip >= 2+sqrt(n/2)
strictly,
length of ip >=
2+(1<<(int)(log(n/2+0.5)/log(2))/2).
ip[0],ip[1] are pointers of the cos/sin table.
w[0...n/2-1] :cos/sin table (double *)
w[],ip[] are initialized if ip[0] == 0.
[remark]
Inverse of
rdft(n, 1, a, ip, w);
is
rdft(n, -1, a, ip, w);
for (j = 0; j <= n - 1; j++) {
a[j] *= 2.0 / n;
}
.
-------- DCT (Discrete Cosine Transform) / Inverse of DCT --------
[definition]
<case1> IDCT (excluding scale)
C[k] = sum_j=0^n-1 a[j]*cos(pi*j*(k+1/2)/n), 0<=k<n
<case2> DCT
C[k] = sum_j=0^n-1 a[j]*cos(pi*(j+1/2)*k/n), 0<=k<n
[usage]
<case1>
ip[0] = 0; // first time only
ddct(n, 1, a, ip, w);
<case2>
ip[0] = 0; // first time only
ddct(n, -1, a, ip, w);
[parameters]
n :data length (int)
n >= 2, n = power of 2
a[0...n-1] :input/output data (double *)
output data
a[k] = C[k], 0<=k<n
ip[0...*] :work area for bit reversal (int *)
length of ip >= 2+sqrt(n/2)
strictly,
length of ip >=
2+(1<<(int)(log(n/2+0.5)/log(2))/2).
ip[0],ip[1] are pointers of the cos/sin table.
w[0...n*5/4-1] :cos/sin table (double *)
w[],ip[] are initialized if ip[0] == 0.
[remark]
Inverse of
ddct(n, -1, a, ip, w);
is
a[0] *= 0.5;
ddct(n, 1, a, ip, w);
for (j = 0; j <= n - 1; j++) {
a[j] *= 2.0 / n;
}
.
-------- DST (Discrete Sine Transform) / Inverse of DST --------
[definition]
<case1> IDST (excluding scale)
S[k] = sum_j=1^n A[j]*sin(pi*j*(k+1/2)/n), 0<=k<n
<case2> DST
S[k] = sum_j=0^n-1 a[j]*sin(pi*(j+1/2)*k/n), 0<k<=n
[usage]
<case1>
ip[0] = 0; // first time only
ddst(n, 1, a, ip, w);
<case2>
ip[0] = 0; // first time only
ddst(n, -1, a, ip, w);
[parameters]
n :data length (int)
n >= 2, n = power of 2
a[0...n-1] :input/output data (double *)
<case1>
input data
a[j] = A[j], 0<j<n
a[0] = A[n]
output data
a[k] = S[k], 0<=k<n
<case2>
output data
a[k] = S[k], 0<k<n
a[0] = S[n]
ip[0...*] :work area for bit reversal (int *)
length of ip >= 2+sqrt(n/2)
strictly,
length of ip >=
2+(1<<(int)(log(n/2+0.5)/log(2))/2).
ip[0],ip[1] are pointers of the cos/sin table.
w[0...n*5/4-1] :cos/sin table (double *)
w[],ip[] are initialized if ip[0] == 0.
[remark]
Inverse of
ddst(n, -1, a, ip, w);
is
a[0] *= 0.5;
ddst(n, 1, a, ip, w);
for (j = 0; j <= n - 1; j++) {
a[j] *= 2.0 / n;
}
.
-------- Cosine Transform of RDFT (Real Symmetric DFT) --------
[definition]
C[k] = sum_j=0^n a[j]*cos(pi*j*k/n), 0<=k<=n
[usage]
ip[0] = 0; // first time only
dfct(n, a, t, ip, w);
[parameters]
n :data length - 1 (int)
n >= 2, n = power of 2
a[0...n] :input/output data (double *)
output data
a[k] = C[k], 0<=k<=n
t[0...n/2] :work area (double *)
ip[0...*] :work area for bit reversal (int *)
length of ip >= 2+sqrt(n/4)
strictly,
length of ip >=
2+(1<<(int)(log(n/4+0.5)/log(2))/2).
ip[0],ip[1] are pointers of the cos/sin table.
w[0...n*5/8-1] :cos/sin table (double *)
w[],ip[] are initialized if ip[0] == 0.
[remark]
Inverse of
a[0] *= 0.5;
a[n] *= 0.5;
dfct(n, a, t, ip, w);
is
a[0] *= 0.5;
a[n] *= 0.5;
dfct(n, a, t, ip, w);
for (j = 0; j <= n; j++) {
a[j] *= 2.0 / n;
}
.
-------- Sine Transform of RDFT (Real Anti-symmetric DFT) --------
[definition]
S[k] = sum_j=1^n-1 a[j]*sin(pi*j*k/n), 0<k<n
[usage]
ip[0] = 0; // first time only
dfst(n, a, t, ip, w);
[parameters]
n :data length + 1 (int)
n >= 2, n = power of 2
a[0...n-1] :input/output data (double *)
output data
a[k] = S[k], 0<k<n
(a[0] is used for work area)
t[0...n/2-1] :work area (double *)
ip[0...*] :work area for bit reversal (int *)
length of ip >= 2+sqrt(n/4)
strictly,
length of ip >=
2+(1<<(int)(log(n/4+0.5)/log(2))/2).
ip[0],ip[1] are pointers of the cos/sin table.
w[0...n*5/8-1] :cos/sin table (double *)
w[],ip[] are initialized if ip[0] == 0.
[remark]
Inverse of
dfst(n, a, t, ip, w);
is
dfst(n, a, t, ip, w);
for (j = 1; j <= n - 1; j++) {
a[j] *= 2.0 / n;
}
.
Appendix :
The cos/sin table is recalculated when the larger table required.
w[] and ip[] are compatible with all routines.
*/
void cdft(int n, int isgn, double *a, int *ip, double *w)
{
void makewt(int nw, int *ip, double *w);
void cftfsub(int n, double *a, int *ip, int nw, double *w);
void cftbsub(int n, double *a, int *ip, int nw, double *w);
int nw;
nw = ip[0];
if (n > (nw << 2)) {
nw = n >> 2;
makewt(nw, ip, w);
}
if (isgn >= 0) {
cftfsub(n, a, ip, nw, w);
} else {
cftbsub(n, a, ip, nw, w);
}
}
void rdft(int n, int isgn, double *a, int *ip, double *w)
{
void makewt(int nw, int *ip, double *w);
void makect(int nc, int *ip, double *c);
void cftfsub(int n, double *a, int *ip, int nw, double *w);
void cftbsub(int n, double *a, int *ip, int nw, double *w);
void rftfsub(int n, double *a, int nc, double *c);
void rftbsub(int n, double *a, int nc, double *c);
int nw, nc;
double xi;
nw = ip[0];
if (n > (nw << 2)) {
nw = n >> 2;
makewt(nw, ip, w);
}
nc = ip[1];
if (n > (nc << 2)) {
nc = n >> 2;
makect(nc, ip, w + nw);
}
if (isgn >= 0) {
if (n > 4) {
cftfsub(n, a, ip, nw, w);
rftfsub(n, a, nc, w + nw);
} else if (n == 4) {
cftfsub(n, a, ip, nw, w);
}
xi = a[0] - a[1];
a[0] += a[1];
a[1] = xi;
} else {
a[1] = 0.5 * (a[0] - a[1]);
a[0] -= a[1];
if (n > 4) {
rftbsub(n, a, nc, w + nw);
cftbsub(n, a, ip, nw, w);
} else if (n == 4) {
cftbsub(n, a, ip, nw, w);
}
}
}
void ddct(int n, int isgn, double *a, int *ip, double *w)
{
void makewt(int nw, int *ip, double *w);
void makect(int nc, int *ip, double *c);
void cftfsub(int n, double *a, int *ip, int nw, double *w);
void cftbsub(int n, double *a, int *ip, int nw, double *w);
void rftfsub(int n, double *a, int nc, double *c);
void rftbsub(int n, double *a, int nc, double *c);
void dctsub(int n, double *a, int nc, double *c);
int j, nw, nc;
double xr;
nw = ip[0];
if (n > (nw << 2)) {
nw = n >> 2;
makewt(nw, ip, w);
}
nc = ip[1];
if (n > nc) {
nc = n;
makect(nc, ip, w + nw);
}
if (isgn < 0) {
xr = a[n - 1];
for (j = n - 2; j >= 2; j -= 2) {
a[j + 1] = a[j] - a[j - 1];
a[j] += a[j - 1];
}
a[1] = a[0] - xr;
a[0] += xr;
if (n > 4) {
rftbsub(n, a, nc, w + nw);
cftbsub(n, a, ip, nw, w);
} else if (n == 4) {
cftbsub(n, a, ip, nw, w);
}
}
dctsub(n, a, nc, w + nw);
if (isgn >= 0) {
if (n > 4) {
cftfsub(n, a, ip, nw, w);
rftfsub(n, a, nc, w + nw);
} else if (n == 4) {
cftfsub(n, a, ip, nw, w);
}
xr = a[0] - a[1];
a[0] += a[1];
for (j = 2; j < n; j += 2) {
a[j - 1] = a[j] - a[j + 1];
a[j] += a[j + 1];
}
a[n - 1] = xr;
}
}
void ddst(int n, int isgn, double *a, int *ip, double *w)
{
void makewt(int nw, int *ip, double *w);
void makect(int nc, int *ip, double *c);
void cftfsub(int n, double *a, int *ip, int nw, double *w);
void cftbsub(int n, double *a, int *ip, int nw, double *w);
void rftfsub(int n, double *a, int nc, double *c);
void rftbsub(int n, double *a, int nc, double *c);
void dstsub(int n, double *a, int nc, double *c);
int j, nw, nc;
double xr;
nw = ip[0];
if (n > (nw << 2)) {
nw = n >> 2;
makewt(nw, ip, w);
}
nc = ip[1];
if (n > nc) {
nc = n;
makect(nc, ip, w + nw);
}
if (isgn < 0) {
xr = a[n - 1];
for (j = n - 2; j >= 2; j -= 2) {
a[j + 1] = -a[j] - a[j - 1];
a[j] -= a[j - 1];
}
a[1] = a[0] + xr;
a[0] -= xr;
if (n > 4) {
rftbsub(n, a, nc, w + nw);
cftbsub(n, a, ip, nw, w);
} else if (n == 4) {
cftbsub(n, a, ip, nw, w);
}
}
dstsub(n, a, nc, w + nw);
if (isgn >= 0) {
if (n > 4) {
cftfsub(n, a, ip, nw, w);
rftfsub(n, a, nc, w + nw);
} else if (n == 4) {
cftfsub(n, a, ip, nw, w);
}
xr = a[0] - a[1];
a[0] += a[1];
for (j = 2; j < n; j += 2) {
a[j - 1] = -a[j] - a[j + 1];
a[j] -= a[j + 1];
}
a[n - 1] = -xr;
}
}
void dfct(int n, double *a, double *t, int *ip, double *w)
{
void makewt(int nw, int *ip, double *w);
void makect(int nc, int *ip, double *c);
void cftfsub(int n, double *a, int *ip, int nw, double *w);
void rftfsub(int n, double *a, int nc, double *c);
void dctsub(int n, double *a, int nc, double *c);
int j, k, l, m, mh, nw, nc;
double xr, xi, yr, yi;
nw = ip[0];
if (n > (nw << 3)) {
nw = n >> 3;
makewt(nw, ip, w);
}
nc = ip[1];
if (n > (nc << 1)) {
nc = n >> 1;
makect(nc, ip, w + nw);
}
m = n >> 1;
yi = a[m];
xi = a[0] + a[n];
a[0] -= a[n];
t[0] = xi - yi;
t[m] = xi + yi;
if (n > 2) {
mh = m >> 1;
for (j = 1; j < mh; j++) {
k = m - j;
xr = a[j] - a[n - j];
xi = a[j] + a[n - j];
yr = a[k] - a[n - k];
yi = a[k] + a[n - k];
a[j] = xr;
a[k] = yr;
t[j] = xi - yi;
t[k] = xi + yi;
}
t[mh] = a[mh] + a[n - mh];
a[mh] -= a[n - mh];
dctsub(m, a, nc, w + nw);
if (m > 4) {
cftfsub(m, a, ip, nw, w);
rftfsub(m, a, nc, w + nw);
} else if (m == 4) {
cftfsub(m, a, ip, nw, w);
}
a[n - 1] = a[0] - a[1];
a[1] = a[0] + a[1];
for (j = m - 2; j >= 2; j -= 2) {
a[2 * j + 1] = a[j] + a[j + 1];
a[2 * j - 1] = a[j] - a[j + 1];
}
l = 2;
m = mh;
while (m >= 2) {
dctsub(m, t, nc, w + nw);
if (m > 4) {
cftfsub(m, t, ip, nw, w);
rftfsub(m, t, nc, w + nw);
} else if (m == 4) {
cftfsub(m, t, ip, nw, w);
}
a[n - l] = t[0] - t[1];
a[l] = t[0] + t[1];
k = 0;
for (j = 2; j < m; j += 2) {
k += l << 2;
a[k - l] = t[j] - t[j + 1];
a[k + l] = t[j] + t[j + 1];
}
l <<= 1;
mh = m >> 1;
for (j = 0; j < mh; j++) {
k = m - j;
t[j] = t[m + k] - t[m + j];
t[k] = t[m + k] + t[m + j];
}
t[mh] = t[m + mh];
m = mh;
}
a[l] = t[0];
a[n] = t[2] - t[1];
a[0] = t[2] + t[1];
} else {
a[1] = a[0];
a[2] = t[0];
a[0] = t[1];
}
}
void dfst(int n, double *a, double *t, int *ip, double *w)
{
void makewt(int nw, int *ip, double *w);
void makect(int nc, int *ip, double *c);
void cftfsub(int n, double *a, int *ip, int nw, double *w);
void rftfsub(int n, double *a, int nc, double *c);
void dstsub(int n, double *a, int nc, double *c);
int j, k, l, m, mh, nw, nc;
double xr, xi, yr, yi;
nw = ip[0];
if (n > (nw << 3)) {
nw = n >> 3;
makewt(nw, ip, w);
}
nc = ip[1];
if (n > (nc << 1)) {
nc = n >> 1;
makect(nc, ip, w + nw);
}
if (n > 2) {
m = n >> 1;
mh = m >> 1;
for (j = 1; j < mh; j++) {
k = m - j;
xr = a[j] + a[n - j];
xi = a[j] - a[n - j];
yr = a[k] + a[n - k];
yi = a[k] - a[n - k];
a[j] = xr;
a[k] = yr;
t[j] = xi + yi;
t[k] = xi - yi;
}
t[0] = a[mh] - a[n - mh];
a[mh] += a[n - mh];
a[0] = a[m];
dstsub(m, a, nc, w + nw);
if (m > 4) {
cftfsub(m, a, ip, nw, w);
rftfsub(m, a, nc, w + nw);
} else if (m == 4) {
cftfsub(m, a, ip, nw, w);
}
a[n - 1] = a[1] - a[0];
a[1] = a[0] + a[1];
for (j = m - 2; j >= 2; j -= 2) {
a[2 * j + 1] = a[j] - a[j + 1];
a[2 * j - 1] = -a[j] - a[j + 1];
}
l = 2;
m = mh;
while (m >= 2) {
dstsub(m, t, nc, w + nw);
if (m > 4) {
cftfsub(m, t, ip, nw, w);
rftfsub(m, t, nc, w + nw);
} else if (m == 4) {
cftfsub(m, t, ip, nw, w);
}
a[n - l] = t[1] - t[0];
a[l] = t[0] + t[1];
k = 0;
for (j = 2; j < m; j += 2) {
k += l << 2;
a[k - l] = -t[j] - t[j + 1];
a[k + l] = t[j] - t[j + 1];
}
l <<= 1;
mh = m >> 1;
for (j = 1; j < mh; j++) {
k = m - j;
t[j] = t[m + k] + t[m + j];
t[k] = t[m + k] - t[m + j];
}
t[0] = t[m + mh];
m = mh;
}
a[l] = t[0];
}
a[0] = 0;
}
/* -------- initializing routines -------- */
#include <math.h>
void makewt(int nw, int *ip, double *w)
{
void makeipt(int nw, int *ip);
int j, nwh, nw0, nw1;
double delta, wn4r, wk1r, wk1i, wk3r, wk3i;
ip[0] = nw;
ip[1] = 1;
if (nw > 2) {
nwh = nw >> 1;
delta = atan(1.0) / nwh;
wn4r = cos(delta * nwh);
w[0] = 1;
w[1] = wn4r;
if (nwh == 4) {
w[2] = cos(delta * 2);
w[3] = sin(delta * 2);
} else if (nwh > 4) {
makeipt(nw, ip);
w[2] = 0.5 / cos(delta * 2);
w[3] = 0.5 / cos(delta * 6);
for (j = 4; j < nwh; j += 4) {
w[j] = cos(delta * j);
w[j + 1] = sin(delta * j);
w[j + 2] = cos(3 * delta * j);
w[j + 3] = -sin(3 * delta * j);
}
}
nw0 = 0;
while (nwh > 2) {
nw1 = nw0 + nwh;
nwh >>= 1;
w[nw1] = 1;
w[nw1 + 1] = wn4r;
if (nwh == 4) {
wk1r = w[nw0 + 4];
wk1i = w[nw0 + 5];
w[nw1 + 2] = wk1r;
w[nw1 + 3] = wk1i;
} else if (nwh > 4) {
wk1r = w[nw0 + 4];
wk3r = w[nw0 + 6];
w[nw1 + 2] = 0.5 / wk1r;
w[nw1 + 3] = 0.5 / wk3r;
for (j = 4; j < nwh; j += 4) {
wk1r = w[nw0 + 2 * j];
wk1i = w[nw0 + 2 * j + 1];
wk3r = w[nw0 + 2 * j + 2];
wk3i = w[nw0 + 2 * j + 3];
w[nw1 + j] = wk1r;
w[nw1 + j + 1] = wk1i;
w[nw1 + j + 2] = wk3r;
w[nw1 + j + 3] = wk3i;
}
}
nw0 = nw1;
}
}
}
void makeipt(int nw, int *ip)
{
int j, l, m, m2, p, q;
ip[2] = 0;
ip[3] = 16;
m = 2;
for (l = nw; l > 32; l >>= 2) {
m2 = m << 1;
q = m2 << 3;
for (j = m; j < m2; j++) {
p = ip[j] << 2;
ip[m + j] = p;
ip[m2 + j] = p + q;
}
m = m2;
}
}
void makect(int nc, int *ip, double *c)
{
int j, nch;
double delta;
ip[1] = nc;
if (nc > 1) {
nch = nc >> 1;
delta = atan(1.0) / nch;
c[0] = cos(delta * nch);
c[nch] = 0.5 * c[0];
for (j = 1; j < nch; j++) {
c[j] = 0.5 * cos(delta * j);
c[nc - j] = 0.5 * sin(delta * j);
}
}
}
/* -------- child routines -------- */
#ifdef USE_CDFT_PTHREADS
#define USE_CDFT_THREADS
#ifndef CDFT_THREADS_BEGIN_N
#define CDFT_THREADS_BEGIN_N 8192
#endif
#ifndef CDFT_4THREADS_BEGIN_N
#define CDFT_4THREADS_BEGIN_N 65536
#endif
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#define cdft_thread_t pthread_t
#define cdft_thread_create(thp,func,argp) { \
if (pthread_create(thp, NULL, func, (void *) argp) != 0) { \
fprintf(stderr, "cdft thread error\n"); \
exit(1); \
} \
}
#define cdft_thread_wait(th) { \
if (pthread_join(th, NULL) != 0) { \
fprintf(stderr, "cdft thread error\n"); \
exit(1); \
} \
}
#endif /* USE_CDFT_PTHREADS */
#ifdef USE_CDFT_WINTHREADS
#define USE_CDFT_THREADS
#ifndef CDFT_THREADS_BEGIN_N
#define CDFT_THREADS_BEGIN_N 32768
#endif
#ifndef CDFT_4THREADS_BEGIN_N
#define CDFT_4THREADS_BEGIN_N 524288
#endif
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#define cdft_thread_t HANDLE
#define cdft_thread_create(thp,func,argp) { \
DWORD thid; \
*(thp) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) func, (LPVOID) argp, 0, &thid); \
if (*(thp) == 0) { \
fprintf(stderr, "cdft thread error\n"); \
exit(1); \
} \
}
#define cdft_thread_wait(th) { \
WaitForSingleObject(th, INFINITE); \
CloseHandle(th); \
}
#endif /* USE_CDFT_WINTHREADS */
void cftfsub(int n, double *a, int *ip, int nw, double *w)
{
void bitrv2(int n, int *ip, double *a);
void bitrv216(double *a);
void bitrv208(double *a);
void cftf1st(int n, double *a, double *w);
void cftrec4(int n, double *a, int nw, double *w);
void cftleaf(int n, int isplt, double *a, int nw, double *w);
void cftfx41(int n, double *a, int nw, double *w);
void cftf161(double *a, double *w);
void cftf081(double *a, double *w);
void cftf040(double *a);
void cftx020(double *a);
#ifdef USE_CDFT_THREADS
void cftrec4_th(int n, double *a, int nw, double *w);
#endif /* USE_CDFT_THREADS */
if (n > 8) {
if (n > 32) {
cftf1st(n, a, &w[nw - (n >> 2)]);
#ifdef USE_CDFT_THREADS
if (n > CDFT_THREADS_BEGIN_N) {
cftrec4_th(n, a, nw, w);
} else
#endif /* USE_CDFT_THREADS */
if (n > 512) {
cftrec4(n, a, nw, w);
} else if (n > 128) {
cftleaf(n, 1, a, nw, w);
} else {
cftfx41(n, a, nw, w);
}
bitrv2(n, ip, a);
} else if (n == 32) {
cftf161(a, &w[nw - 8]);
bitrv216(a);
} else {
cftf081(a, w);
bitrv208(a);
}
} else if (n == 8) {
cftf040(a);
} else if (n == 4) {
cftx020(a);
}
}
void cftbsub(int n, double *a, int *ip, int nw, double *w)
{
void bitrv2conj(int n, int *ip, double *a);
void bitrv216neg(double *a);
void bitrv208neg(double *a);
void cftb1st(int n, double *a, double *w);
void cftrec4(int n, double *a, int nw, double *w);
void cftleaf(int n, int isplt, double *a, int nw, double *w);
void cftfx41(int n, double *a, int nw, double *w);
void cftf161(double *a, double *w);
void cftf081(double *a, double *w);
void cftb040(double *a);
void cftx020(double *a);
#ifdef USE_CDFT_THREADS
void cftrec4_th(int n, double *a, int nw, double *w);
#endif /* USE_CDFT_THREADS */
if (n > 8) {
if (n > 32) {
cftb1st(n, a, &w[nw - (n >> 2)]);
#ifdef USE_CDFT_THREADS
if (n > CDFT_THREADS_BEGIN_N) {
cftrec4_th(n, a, nw, w);
} else
#endif /* USE_CDFT_THREADS */
if (n > 512) {
cftrec4(n, a, nw, w);
} else if (n > 128) {
cftleaf(n, 1, a, nw, w);
} else {
cftfx41(n, a, nw, w);
}
bitrv2conj(n, ip, a);
} else if (n == 32) {
cftf161(a, &w[nw - 8]);
bitrv216neg(a);
} else {
cftf081(a, w);
bitrv208neg(a);
}
} else if (n == 8) {
cftb040(a);
} else if (n == 4) {
cftx020(a);
}
}
void bitrv2(int n, int *ip, double *a)
{
int j, j1, k, k1, l, m, nh, nm;
double xr, xi, yr, yi;
m = 1;
for (l = n >> 2; l > 8; l >>= 2) {
m <<= 1;
}
nh = n >> 1;
nm = 4 * m;
if (l == 8) {
for (k = 0; k < m; k++) {
for (j = 0; j < k; j++) {
j1 = 4 * j + 2 * ip[m + k];
k1 = 4 * k + 2 * ip[m + j];
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 += nm;
k1 += 2 * nm;
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 += nm;
k1 -= nm;
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 += nm;
k1 += 2 * nm;
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 += nh;
k1 += 2;
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 -= nm;
k1 -= 2 * nm;
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 -= nm;
k1 += nm;
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 -= nm;
k1 -= 2 * nm;
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 += 2;
k1 += nh;
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 += nm;
k1 += 2 * nm;
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 += nm;
k1 -= nm;
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 += nm;
k1 += 2 * nm;
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 -= nh;
k1 -= 2;
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 -= nm;
k1 -= 2 * nm;
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 -= nm;
k1 += nm;
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 -= nm;
k1 -= 2 * nm;
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
}
k1 = 4 * k + 2 * ip[m + k];
j1 = k1 + 2;
k1 += nh;
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 += nm;
k1 += 2 * nm;
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 += nm;
k1 -= nm;
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 -= 2;
k1 -= nh;
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 += nh + 2;
k1 += nh + 2;
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 -= nh - nm;
k1 += 2 * nm - 2;
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
}
} else {
for (k = 0; k < m; k++) {
for (j = 0; j < k; j++) {
j1 = 4 * j + ip[m + k];
k1 = 4 * k + ip[m + j];
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 += nm;
k1 += nm;
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 += nh;
k1 += 2;
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 -= nm;
k1 -= nm;
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 += 2;
k1 += nh;
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 += nm;
k1 += nm;
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 -= nh;
k1 -= 2;
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 -= nm;
k1 -= nm;
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
}
k1 = 4 * k + ip[m + k];
j1 = k1 + 2;
k1 += nh;
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 += nm;
k1 += nm;
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
}
}
}
void bitrv2conj(int n, int *ip, double *a)
{
int j, j1, k, k1, l, m, nh, nm;
double xr, xi, yr, yi;
m = 1;
for (l = n >> 2; l > 8; l >>= 2) {
m <<= 1;
}
nh = n >> 1;
nm = 4 * m;
if (l == 8) {
for (k = 0; k < m; k++) {
for (j = 0; j < k; j++) {
j1 = 4 * j + 2 * ip[m + k];
k1 = 4 * k + 2 * ip[m + j];
xr = a[j1];
xi = -a[j1 + 1];
yr = a[k1];
yi = -a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 += nm;
k1 += 2 * nm;
xr = a[j1];
xi = -a[j1 + 1];
yr = a[k1];
yi = -a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 += nm;
k1 -= nm;
xr = a[j1];
xi = -a[j1 + 1];
yr = a[k1];
yi = -a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 += nm;
k1 += 2 * nm;
xr = a[j1];
xi = -a[j1 + 1];
yr = a[k1];
yi = -a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 += nh;
k1 += 2;
xr = a[j1];
xi = -a[j1 + 1];
yr = a[k1];
yi = -a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 -= nm;
k1 -= 2 * nm;
xr = a[j1];
xi = -a[j1 + 1];
yr = a[k1];
yi = -a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 -= nm;
k1 += nm;
xr = a[j1];
xi = -a[j1 + 1];
yr = a[k1];
yi = -a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 -= nm;
k1 -= 2 * nm;
xr = a[j1];
xi = -a[j1 + 1];
yr = a[k1];
yi = -a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 += 2;
k1 += nh;
xr = a[j1];
xi = -a[j1 + 1];
yr = a[k1];
yi = -a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 += nm;
k1 += 2 * nm;
xr = a[j1];
xi = -a[j1 + 1];
yr = a[k1];
yi = -a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 += nm;
k1 -= nm;
xr = a[j1];
xi = -a[j1 + 1];
yr = a[k1];
yi = -a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 += nm;
k1 += 2 * nm;
xr = a[j1];
xi = -a[j1 + 1];
yr = a[k1];
yi = -a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 -= nh;
k1 -= 2;
xr = a[j1];
xi = -a[j1 + 1];
yr = a[k1];
yi = -a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 -= nm;
k1 -= 2 * nm;
xr = a[j1];
xi = -a[j1 + 1];
yr = a[k1];
yi = -a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 -= nm;
k1 += nm;
xr = a[j1];
xi = -a[j1 + 1];
yr = a[k1];
yi = -a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 -= nm;
k1 -= 2 * nm;
xr = a[j1];
xi = -a[j1 + 1];
yr = a[k1];
yi = -a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
}
k1 = 4 * k + 2 * ip[m + k];
j1 = k1 + 2;
k1 += nh;
a[j1 - 1] = -a[j1 - 1];
xr = a[j1];
xi = -a[j1 + 1];
yr = a[k1];
yi = -a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
a[k1 + 3] = -a[k1 + 3];
j1 += nm;
k1 += 2 * nm;
xr = a[j1];
xi = -a[j1 + 1];
yr = a[k1];
yi = -a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 += nm;
k1 -= nm;
xr = a[j1];
xi = -a[j1 + 1];
yr = a[k1];
yi = -a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 -= 2;
k1 -= nh;
xr = a[j1];
xi = -a[j1 + 1];
yr = a[k1];
yi = -a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 += nh + 2;
k1 += nh + 2;
xr = a[j1];
xi = -a[j1 + 1];
yr = a[k1];
yi = -a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 -= nh - nm;
k1 += 2 * nm - 2;
a[j1 - 1] = -a[j1 - 1];
xr = a[j1];
xi = -a[j1 + 1];
yr = a[k1];
yi = -a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
a[k1 + 3] = -a[k1 + 3];
}
} else {
for (k = 0; k < m; k++) {
for (j = 0; j < k; j++) {
j1 = 4 * j + ip[m + k];
k1 = 4 * k + ip[m + j];
xr = a[j1];
xi = -a[j1 + 1];
yr = a[k1];
yi = -a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 += nm;
k1 += nm;
xr = a[j1];
xi = -a[j1 + 1];
yr = a[k1];
yi = -a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 += nh;
k1 += 2;
xr = a[j1];
xi = -a[j1 + 1];
yr = a[k1];
yi = -a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 -= nm;
k1 -= nm;
xr = a[j1];
xi = -a[j1 + 1];
yr = a[k1];
yi = -a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 += 2;
k1 += nh;
xr = a[j1];
xi = -a[j1 + 1];
yr = a[k1];
yi = -a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 += nm;
k1 += nm;
xr = a[j1];
xi = -a[j1 + 1];
yr = a[k1];
yi = -a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 -= nh;
k1 -= 2;
xr = a[j1];
xi = -a[j1 + 1];
yr = a[k1];
yi = -a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 -= nm;
k1 -= nm;
xr = a[j1];
xi = -a[j1 + 1];
yr = a[k1];
yi = -a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
}
k1 = 4 * k + ip[m + k];
j1 = k1 + 2;
k1 += nh;
a[j1 - 1] = -a[j1 - 1];
xr = a[j1];
xi = -a[j1 + 1];
yr = a[k1];
yi = -a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
a[k1 + 3] = -a[k1 + 3];
j1 += nm;
k1 += nm;
a[j1 - 1] = -a[j1 - 1];
xr = a[j1];
xi = -a[j1 + 1];
yr = a[k1];
yi = -a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
a[k1 + 3] = -a[k1 + 3];
}
}
}
void bitrv216(double *a)
{
double x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i,
x5r, x5i, x7r, x7i, x8r, x8i, x10r, x10i,
x11r, x11i, x12r, x12i, x13r, x13i, x14r, x14i;
x1r = a[2];
x1i = a[3];
x2r = a[4];
x2i = a[5];
x3r = a[6];
x3i = a[7];
x4r = a[8];
x4i = a[9];
x5r = a[10];
x5i = a[11];
x7r = a[14];
x7i = a[15];
x8r = a[16];
x8i = a[17];
x10r = a[20];
x10i = a[21];
x11r = a[22];
x11i = a[23];
x12r = a[24];
x12i = a[25];
x13r = a[26];
x13i = a[27];
x14r = a[28];
x14i = a[29];
a[2] = x8r;
a[3] = x8i;
a[4] = x4r;
a[5] = x4i;
a[6] = x12r;
a[7] = x12i;
a[8] = x2r;
a[9] = x2i;
a[10] = x10r;
a[11] = x10i;
a[14] = x14r;
a[15] = x14i;
a[16] = x1r;
a[17] = x1i;
a[20] = x5r;
a[21] = x5i;
a[22] = x13r;
a[23] = x13i;
a[24] = x3r;
a[25] = x3i;
a[26] = x11r;
a[27] = x11i;
a[28] = x7r;
a[29] = x7i;
}
void bitrv216neg(double *a)
{
double x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i,
x5r, x5i, x6r, x6i, x7r, x7i, x8r, x8i,
x9r, x9i, x10r, x10i, x11r, x11i, x12r, x12i,
x13r, x13i, x14r, x14i, x15r, x15i;
x1r = a[2];
x1i = a[3];
x2r = a[4];
x2i = a[5];
x3r = a[6];
x3i = a[7];
x4r = a[8];
x4i = a[9];
x5r = a[10];
x5i = a[11];
x6r = a[12];
x6i = a[13];
x7r = a[14];
x7i = a[15];
x8r = a[16];
x8i = a[17];
x9r = a[18];
x9i = a[19];
x10r = a[20];
x10i = a[21];
x11r = a[22];
x11i = a[23];
x12r = a[24];
x12i = a[25];
x13r = a[26];
x13i = a[27];
x14r = a[28];
x14i = a[29];
x15r = a[30];
x15i = a[31];
a[2] = x15r;
a[3] = x15i;
a[4] = x7r;
a[5] = x7i;
a[6] = x11r;
a[7] = x11i;
a[8] = x3r;
a[9] = x3i;
a[10] = x13r;
a[11] = x13i;
a[12] = x5r;
a[13] = x5i;
a[14] = x9r;
a[15] = x9i;
a[16] = x1r;
a[17] = x1i;
a[18] = x14r;
a[19] = x14i;
a[20] = x6r;
a[21] = x6i;
a[22] = x10r;
a[23] = x10i;
a[24] = x2r;
a[25] = x2i;
a[26] = x12r;
a[27] = x12i;
a[28] = x4r;
a[29] = x4i;
a[30] = x8r;
a[31] = x8i;
}
void bitrv208(double *a)
{
double x1r, x1i, x3r, x3i, x4r, x4i, x6r, x6i;
x1r = a[2];
x1i = a[3];
x3r = a[6];
x3i = a[7];
x4r = a[8];
x4i = a[9];
x6r = a[12];
x6i = a[13];
a[2] = x4r;
a[3] = x4i;
a[6] = x6r;
a[7] = x6i;
a[8] = x1r;
a[9] = x1i;
a[12] = x3r;
a[13] = x3i;
}
void bitrv208neg(double *a)
{
double x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i,
x5r, x5i, x6r, x6i, x7r, x7i;
x1r = a[2];
x1i = a[3];
x2r = a[4];
x2i = a[5];
x3r = a[6];
x3i = a[7];
x4r = a[8];
x4i = a[9];
x5r = a[10];
x5i = a[11];
x6r = a[12];
x6i = a[13];
x7r = a[14];
x7i = a[15];
a[2] = x7r;
a[3] = x7i;
a[4] = x3r;
a[5] = x3i;
a[6] = x5r;
a[7] = x5i;
a[8] = x1r;
a[9] = x1i;
a[10] = x6r;
a[11] = x6i;
a[12] = x2r;
a[13] = x2i;
a[14] = x4r;
a[15] = x4i;
}
void cftf1st(int n, double *a, double *w)
{
int j, j0, j1, j2, j3, k, m, mh;
double wn4r, csc1, csc3, wk1r, wk1i, wk3r, wk3i,
wd1r, wd1i, wd3r, wd3i;
double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i,
y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i;
mh = n >> 3;
m = 2 * mh;
j1 = m;
j2 = j1 + m;
j3 = j2 + m;
x0r = a[0] + a[j2];
x0i = a[1] + a[j2 + 1];
x1r = a[0] - a[j2];
x1i = a[1] - a[j2 + 1];
x2r = a[j1] + a[j3];
x2i = a[j1 + 1] + a[j3 + 1];
x3r = a[j1] - a[j3];
x3i = a[j1 + 1] - a[j3 + 1];
a[0] = x0r + x2r;
a[1] = x0i + x2i;
a[j1] = x0r - x2r;
a[j1 + 1] = x0i - x2i;
a[j2] = x1r - x3i;
a[j2 + 1] = x1i + x3r;
a[j3] = x1r + x3i;
a[j3 + 1] = x1i - x3r;
wn4r = w[1];
csc1 = w[2];
csc3 = w[3];
wd1r = 1;
wd1i = 0;
wd3r = 1;
wd3i = 0;
k = 0;
for (j = 2; j < mh - 2; j += 4) {
k += 4;
wk1r = csc1 * (wd1r + w[k]);
wk1i = csc1 * (wd1i + w[k + 1]);
wk3r = csc3 * (wd3r + w[k + 2]);
wk3i = csc3 * (wd3i + w[k + 3]);
wd1r = w[k];
wd1i = w[k + 1];
wd3r = w[k + 2];
wd3i = w[k + 3];
j1 = j + m;
j2 = j1 + m;
j3 = j2 + m;
x0r = a[j] + a[j2];
x0i = a[j + 1] + a[j2 + 1];
x1r = a[j] - a[j2];
x1i = a[j + 1] - a[j2 + 1];
y0r = a[j + 2] + a[j2 + 2];
y0i = a[j + 3] + a[j2 + 3];
y1r = a[j + 2] - a[j2 + 2];
y1i = a[j + 3] - a[j2 + 3];
x2r = a[j1] + a[j3];
x2i = a[j1 + 1] + a[j3 + 1];
x3r = a[j1] - a[j3];
x3i = a[j1 + 1] - a[j3 + 1];
y2r = a[j1 + 2] + a[j3 + 2];
y2i = a[j1 + 3] + a[j3 + 3];
y3r = a[j1 + 2] - a[j3 + 2];
y3i = a[j1 + 3] - a[j3 + 3];
a[j] = x0r + x2r;
a[j + 1] = x0i + x2i;
a[j + 2] = y0r + y2r;
a[j + 3] = y0i + y2i;
a[j1] = x0r - x2r;
a[j1 + 1] = x0i - x2i;
a[j1 + 2] = y0r - y2r;
a[j1 + 3] = y0i - y2i;
x0r = x1r - x3i;
x0i = x1i + x3r;
a[j2] = wk1r * x0r - wk1i * x0i;
a[j2 + 1] = wk1r * x0i + wk1i * x0r;
x0r = y1r - y3i;
x0i = y1i + y3r;
a[j2 + 2] = wd1r * x0r - wd1i * x0i;
a[j2 + 3] = wd1r * x0i + wd1i * x0r;
x0r = x1r + x3i;
x0i = x1i - x3r;
a[j3] = wk3r * x0r + wk3i * x0i;
a[j3 + 1] = wk3r * x0i - wk3i * x0r;
x0r = y1r + y3i;
x0i = y1i - y3r;
a[j3 + 2] = wd3r * x0r + wd3i * x0i;
a[j3 + 3] = wd3r * x0i - wd3i * x0r;
j0 = m - j;
j1 = j0 + m;
j2 = j1 + m;
j3 = j2 + m;
x0r = a[j0] + a[j2];
x0i = a[j0 + 1] + a[j2 + 1];
x1r = a[j0] - a[j2];
x1i = a[j0 + 1] - a[j2 + 1];
y0r = a[j0 - 2] + a[j2 - 2];
y0i = a[j0 - 1] + a[j2 - 1];
y1r = a[j0 - 2] - a[j2 - 2];
y1i = a[j0 - 1] - a[j2 - 1];
x2r = a[j1] + a[j3];
x2i = a[j1 + 1] + a[j3 + 1];
x3r = a[j1] - a[j3];
x3i = a[j1 + 1] - a[j3 + 1];
y2r = a[j1 - 2] + a[j3 - 2];
y2i = a[j1 - 1] + a[j3 - 1];
y3r = a[j1 - 2] - a[j3 - 2];
y3i = a[j1 - 1] - a[j3 - 1];
a[j0] = x0r + x2r;
a[j0 + 1] = x0i + x2i;
a[j0 - 2] = y0r + y2r;
a[j0 - 1] = y0i + y2i;
a[j1] = x0r - x2r;
a[j1 + 1] = x0i - x2i;
a[j1 - 2] = y0r - y2r;
a[j1 - 1] = y0i - y2i;
x0r = x1r - x3i;
x0i = x1i + x3r;
a[j2] = wk1i * x0r - wk1r * x0i;
a[j2 + 1] = wk1i * x0i + wk1r * x0r;
x0r = y1r - y3i;
x0i = y1i + y3r;
a[j2 - 2] = wd1i * x0r - wd1r * x0i;
a[j2 - 1] = wd1i * x0i + wd1r * x0r;
x0r = x1r + x3i;
x0i = x1i - x3r;
a[j3] = wk3i * x0r + wk3r * x0i;
a[j3 + 1] = wk3i * x0i - wk3r * x0r;
x0r = y1r + y3i;
x0i = y1i - y3r;
a[j3 - 2] = wd3i * x0r + wd3r * x0i;
a[j3 - 1] = wd3i * x0i - wd3r * x0r;
}
wk1r = csc1 * (wd1r + wn4r);
wk1i = csc1 * (wd1i + wn4r);
wk3r = csc3 * (wd3r - wn4r);
wk3i = csc3 * (wd3i - wn4r);
j0 = mh;
j1 = j0 + m;
j2 = j1 + m;
j3 = j2 + m;
x0r = a[j0 - 2] + a[j2 - 2];
x0i = a[j0 - 1] + a[j2 - 1];
x1r = a[j0 - 2] - a[j2 - 2];
x1i = a[j0 - 1] - a[j2 - 1];
x2r = a[j1 - 2] + a[j3 - 2];
x2i = a[j1 - 1] + a[j3 - 1];
x3r = a[j1 - 2] - a[j3 - 2];
x3i = a[j1 - 1] - a[j3 - 1];
a[j0 - 2] = x0r + x2r;
a[j0 - 1] = x0i + x2i;
a[j1 - 2] = x0r - x2r;
a[j1 - 1] = x0i - x2i;
x0r = x1r - x3i;
x0i = x1i + x3r;
a[j2 - 2] = wk1r * x0r - wk1i * x0i;
a[j2 - 1] = wk1r * x0i + wk1i * x0r;
x0r = x1r + x3i;
x0i = x1i - x3r;
a[j3 - 2] = wk3r * x0r + wk3i * x0i;
a[j3 - 1] = wk3r * x0i - wk3i * x0r;
x0r = a[j0] + a[j2];
x0i = a[j0 + 1] + a[j2 + 1];
x1r = a[j0] - a[j2];
x1i = a[j0 + 1] - a[j2 + 1];
x2r = a[j1] + a[j3];
x2i = a[j1 + 1] + a[j3 + 1];
x3r = a[j1] - a[j3];
x3i = a[j1 + 1] - a[j3 + 1];
a[j0] = x0r + x2r;
a[j0 + 1] = x0i + x2i;
a[j1] = x0r - x2r;
a[j1 + 1] = x0i - x2i;
x0r = x1r - x3i;
x0i = x1i + x3r;
a[j2] = wn4r * (x0r - x0i);
a[j2 + 1] = wn4r * (x0i + x0r);
x0r = x1r + x3i;
x0i = x1i - x3r;
a[j3] = -wn4r * (x0r + x0i);
a[j3 + 1] = -wn4r * (x0i - x0r);
x0r = a[j0 + 2] + a[j2 + 2];
x0i = a[j0 + 3] + a[j2 + 3];
x1r = a[j0 + 2] - a[j2 + 2];
x1i = a[j0 + 3] - a[j2 + 3];
x2r = a[j1 + 2] + a[j3 + 2];
x2i = a[j1 + 3] + a[j3 + 3];
x3r = a[j1 + 2] - a[j3 + 2];
x3i = a[j1 + 3] - a[j3 + 3];
a[j0 + 2] = x0r + x2r;
a[j0 + 3] = x0i + x2i;
a[j1 + 2] = x0r - x2r;
a[j1 + 3] = x0i - x2i;
x0r = x1r - x3i;
x0i = x1i + x3r;
a[j2 + 2] = wk1i * x0r - wk1r * x0i;
a[j2 + 3] = wk1i * x0i + wk1r * x0r;
x0r = x1r + x3i;
x0i = x1i - x3r;
a[j3 + 2] = wk3i * x0r + wk3r * x0i;
a[j3 + 3] = wk3i * x0i - wk3r * x0r;
}
void cftb1st(int n, double *a, double *w)
{
int j, j0, j1, j2, j3, k, m, mh;
double wn4r, csc1, csc3, wk1r, wk1i, wk3r, wk3i,
wd1r, wd1i, wd3r, wd3i;
double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i,
y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i;
mh = n >> 3;
m = 2 * mh;
j1 = m;
j2 = j1 + m;
j3 = j2 + m;
x0r = a[0] + a[j2];
x0i = -a[1] - a[j2 + 1];
x1r = a[0] - a[j2];
x1i = -a[1] + a[j2 + 1];
x2r = a[j1] + a[j3];
x2i = a[j1 + 1] + a[j3 + 1];
x3r = a[j1] - a[j3];
x3i = a[j1 + 1] - a[j3 + 1];
a[0] = x0r + x2r;
a[1] = x0i - x2i;
a[j1] = x0r - x2r;
a[j1 + 1] = x0i + x2i;
a[j2] = x1r + x3i;
a[j2 + 1] = x1i + x3r;
a[j3] = x1r - x3i;
a[j3 + 1] = x1i - x3r;
wn4r = w[1];
csc1 = w[2];
csc3 = w[3];
wd1r = 1;
wd1i = 0;
wd3r = 1;
wd3i = 0;
k = 0;
for (j = 2; j < mh - 2; j += 4) {
k += 4;
wk1r = csc1 * (wd1r + w[k]);
wk1i = csc1 * (wd1i + w[k + 1]);
wk3r = csc3 * (wd3r + w[k + 2]);
wk3i = csc3 * (wd3i + w[k + 3]);
wd1r = w[k];
wd1i = w[k + 1];
wd3r = w[k + 2];
wd3i = w[k + 3];
j1 = j + m;
j2 = j1 + m;
j3 = j2 + m;
x0r = a[j] + a[j2];
x0i = -a[j + 1] - a[j2 + 1];
x1r = a[j] - a[j2];
x1i = -a[j + 1] + a[j2 + 1];
y0r = a[j + 2] + a[j2 + 2];
y0i = -a[j + 3] - a[j2 + 3];
y1r = a[j + 2] - a[j2 + 2];
y1i = -a[j + 3] + a[j2 + 3];
x2r = a[j1] + a[j3];
x2i = a[j1 + 1] + a[j3 + 1];
x3r = a[j1] - a[j3];
x3i = a[j1 + 1] - a[j3 + 1];
y2r = a[j1 + 2] + a[j3 + 2];
y2i = a[j1 + 3] + a[j3 + 3];
y3r = a[j1 + 2] - a[j3 + 2];
y3i = a[j1 + 3] - a[j3 + 3];
a[j] = x0r + x2r;
a[j + 1] = x0i - x2i;
a[j + 2] = y0r + y2r;
a[j + 3] = y0i - y2i;
a[j1] = x0r - x2r;
a[j1 + 1] = x0i + x2i;
a[j1 + 2] = y0r - y2r;
a[j1 + 3] = y0i + y2i;
x0r = x1r + x3i;
x0i = x1i + x3r;
a[j2] = wk1r * x0r - wk1i * x0i;
a[j2 + 1] = wk1r * x0i + wk1i * x0r;
x0r = y1r + y3i;
x0i = y1i + y3r;
a[j2 + 2] = wd1r * x0r - wd1i * x0i;
a[j2 + 3] = wd1r * x0i + wd1i * x0r;
x0r = x1r - x3i;
x0i = x1i - x3r;
a[j3] = wk3r * x0r + wk3i * x0i;
a[j3 + 1] = wk3r * x0i - wk3i * x0r;
x0r = y1r - y3i;
x0i = y1i - y3r;
a[j3 + 2] = wd3r * x0r + wd3i * x0i;
a[j3 + 3] = wd3r * x0i - wd3i * x0r;
j0 = m - j;
j1 = j0 + m;
j2 = j1 + m;
j3 = j2 + m;
x0r = a[j0] + a[j2];
x0i = -a[j0 + 1] - a[j2 + 1];
x1r = a[j0] - a[j2];
x1i = -a[j0 + 1] + a[j2 + 1];
y0r = a[j0 - 2] + a[j2 - 2];
y0i = -a[j0 - 1] - a[j2 - 1];
y1r = a[j0 - 2] - a[j2 - 2];
y1i = -a[j0 - 1] + a[j2 - 1];
x2r = a[j1] + a[j3];
x2i = a[j1 + 1] + a[j3 + 1];
x3r = a[j1] - a[j3];
x3i = a[j1 + 1] - a[j3 + 1];
y2r = a[j1 - 2] + a[j3 - 2];
y2i = a[j1 - 1] + a[j3 - 1];
y3r = a[j1 - 2] - a[j3 - 2];
y3i = a[j1 - 1] - a[j3 - 1];
a[j0] = x0r + x2r;
a[j0 + 1] = x0i - x2i;
a[j0 - 2] = y0r + y2r;
a[j0 - 1] = y0i - y2i;
a[j1] = x0r - x2r;
a[j1 + 1] = x0i + x2i;
a[j1 - 2] = y0r - y2r;
a[j1 - 1] = y0i + y2i;
x0r = x1r + x3i;
x0i = x1i + x3r;
a[j2] = wk1i * x0r - wk1r * x0i;
a[j2 + 1] = wk1i * x0i + wk1r * x0r;
x0r = y1r + y3i;
x0i = y1i + y3r;
a[j2 - 2] = wd1i * x0r - wd1r * x0i;
a[j2 - 1] = wd1i * x0i + wd1r * x0r;
x0r = x1r - x3i;
x0i = x1i - x3r;
a[j3] = wk3i * x0r + wk3r * x0i;
a[j3 + 1] = wk3i * x0i - wk3r * x0r;
x0r = y1r - y3i;
x0i = y1i - y3r;
a[j3 - 2] = wd3i * x0r + wd3r * x0i;
a[j3 - 1] = wd3i * x0i - wd3r * x0r;
}
wk1r = csc1 * (wd1r + wn4r);
wk1i = csc1 * (wd1i + wn4r);
wk3r = csc3 * (wd3r - wn4r);
wk3i = csc3 * (wd3i - wn4r);
j0 = mh;
j1 = j0 + m;
j2 = j1 + m;
j3 = j2 + m;
x0r = a[j0 - 2] + a[j2 - 2];
x0i = -a[j0 - 1] - a[j2 - 1];
x1r = a[j0 - 2] - a[j2 - 2];
x1i = -a[j0 - 1] + a[j2 - 1];
x2r = a[j1 - 2] + a[j3 - 2];
x2i = a[j1 - 1] + a[j3 - 1];
x3r = a[j1 - 2] - a[j3 - 2];
x3i = a[j1 - 1] - a[j3 - 1];
a[j0 - 2] = x0r + x2r;
a[j0 - 1] = x0i - x2i;
a[j1 - 2] = x0r - x2r;
a[j1 - 1] = x0i + x2i;
x0r = x1r + x3i;
x0i = x1i + x3r;
a[j2 - 2] = wk1r * x0r - wk1i * x0i;
a[j2 - 1] = wk1r * x0i + wk1i * x0r;
x0r = x1r - x3i;
x0i = x1i - x3r;
a[j3 - 2] = wk3r * x0r + wk3i * x0i;
a[j3 - 1] = wk3r * x0i - wk3i * x0r;
x0r = a[j0] + a[j2];
x0i = -a[j0 + 1] - a[j2 + 1];
x1r = a[j0] - a[j2];
x1i = -a[j0 + 1] + a[j2 + 1];
x2r = a[j1] + a[j3];
x2i = a[j1 + 1] + a[j3 + 1];
x3r = a[j1] - a[j3];
x3i = a[j1 + 1] - a[j3 + 1];
a[j0] = x0r + x2r;
a[j0 + 1] = x0i - x2i;
a[j1] = x0r - x2r;
a[j1 + 1] = x0i + x2i;
x0r = x1r + x3i;
x0i = x1i + x3r;
a[j2] = wn4r * (x0r - x0i);
a[j2 + 1] = wn4r * (x0i + x0r);
x0r = x1r - x3i;
x0i = x1i - x3r;
a[j3] = -wn4r * (x0r + x0i);
a[j3 + 1] = -wn4r * (x0i - x0r);
x0r = a[j0 + 2] + a[j2 + 2];
x0i = -a[j0 + 3] - a[j2 + 3];
x1r = a[j0 + 2] - a[j2 + 2];
x1i = -a[j0 + 3] + a[j2 + 3];
x2r = a[j1 + 2] + a[j3 + 2];
x2i = a[j1 + 3] + a[j3 + 3];
x3r = a[j1 + 2] - a[j3 + 2];
x3i = a[j1 + 3] - a[j3 + 3];
a[j0 + 2] = x0r + x2r;
a[j0 + 3] = x0i - x2i;
a[j1 + 2] = x0r - x2r;
a[j1 + 3] = x0i + x2i;
x0r = x1r + x3i;
x0i = x1i + x3r;
a[j2 + 2] = wk1i * x0r - wk1r * x0i;
a[j2 + 3] = wk1i * x0i + wk1r * x0r;
x0r = x1r - x3i;
x0i = x1i - x3r;
a[j3 + 2] = wk3i * x0r + wk3r * x0i;
a[j3 + 3] = wk3i * x0i - wk3r * x0r;
}
#ifdef USE_CDFT_THREADS
struct cdft_arg_st {
int n0;
int n;
double *a;
int nw;
double *w;
};
typedef struct cdft_arg_st cdft_arg_t;
void cftrec4_th(int n, double *a, int nw, double *w)
{
void *cftrec1_th(void *p);
void *cftrec2_th(void *p);
int i, idiv4, m, nthread;
cdft_thread_t th[4];
cdft_arg_t ag[4];
nthread = 2;
idiv4 = 0;
m = n >> 1;
if (n > CDFT_4THREADS_BEGIN_N) {
nthread = 4;
idiv4 = 1;
m >>= 1;
}
for (i = 0; i < nthread; i++) {
ag[i].n0 = n;
ag[i].n = m;
ag[i].a = &a[i * m];
ag[i].nw = nw;
ag[i].w = w;
if (i != idiv4) {
cdft_thread_create(&th[i], cftrec1_th, &ag[i]);
} else {
cdft_thread_create(&th[i], cftrec2_th, &ag[i]);
}
}
for (i = 0; i < nthread; i++) {
cdft_thread_wait(th[i]);
}
}
void *cftrec1_th(void *p)
{
int cfttree(int n, int j, int k, double *a, int nw, double *w);
void cftleaf(int n, int isplt, double *a, int nw, double *w);
void cftmdl1(int n, double *a, double *w);
int isplt, j, k, m, n, n0, nw;
double *a, *w;
n0 = ((cdft_arg_t *) p)->n0;
n = ((cdft_arg_t *) p)->n;
a = ((cdft_arg_t *) p)->a;
nw = ((cdft_arg_t *) p)->nw;
w = ((cdft_arg_t *) p)->w;
m = n0;
while (m > 512) {
m >>= 2;
cftmdl1(m, &a[n - m], &w[nw - (m >> 1)]);
}
cftleaf(m, 1, &a[n - m], nw, w);
k = 0;
for (j = n - m; j > 0; j -= m) {
k++;
isplt = cfttree(m, j, k, a, nw, w);
cftleaf(m, isplt, &a[j - m], nw, w);
}
return (void *) 0;
}
void *cftrec2_th(void *p)
{
int cfttree(int n, int j, int k, double *a, int nw, double *w);
void cftleaf(int n, int isplt, double *a, int nw, double *w);
void cftmdl2(int n, double *a, double *w);
int isplt, j, k, m, n, n0, nw;
double *a, *w;
n0 = ((cdft_arg_t *) p)->n0;
n = ((cdft_arg_t *) p)->n;
a = ((cdft_arg_t *) p)->a;
nw = ((cdft_arg_t *) p)->nw;
w = ((cdft_arg_t *) p)->w;
k = 1;
m = n0;
while (m > 512) {
m >>= 2;
k <<= 2;
cftmdl2(m, &a[n - m], &w[nw - m]);
}
cftleaf(m, 0, &a[n - m], nw, w);
k >>= 1;
for (j = n - m; j > 0; j -= m) {
k++;
isplt = cfttree(m, j, k, a, nw, w);
cftleaf(m, isplt, &a[j - m], nw, w);
}
return (void *) 0;
}
#endif /* USE_CDFT_THREADS */
void cftrec4(int n, double *a, int nw, double *w)
{
int cfttree(int n, int j, int k, double *a, int nw, double *w);
void cftleaf(int n, int isplt, double *a, int nw, double *w);
void cftmdl1(int n, double *a, double *w);
int isplt, j, k, m;
m = n;
while (m > 512) {
m >>= 2;
cftmdl1(m, &a[n - m], &w[nw - (m >> 1)]);
}
cftleaf(m, 1, &a[n - m], nw, w);
k = 0;
for (j = n - m; j > 0; j -= m) {
k++;
isplt = cfttree(m, j, k, a, nw, w);
cftleaf(m, isplt, &a[j - m], nw, w);
}
}
int cfttree(int n, int j, int k, double *a, int nw, double *w)
{
void cftmdl1(int n, double *a, double *w);
void cftmdl2(int n, double *a, double *w);
int i, isplt, m;
if ((k & 3) != 0) {
isplt = k & 1;
if (isplt != 0) {
cftmdl1(n, &a[j - n], &w[nw - (n >> 1)]);
} else {
cftmdl2(n, &a[j - n], &w[nw - n]);
}
} else {
m = n;
for (i = k; (i & 3) == 0; i >>= 2) {
m <<= 2;
}
isplt = i & 1;
if (isplt != 0) {
while (m > 128) {
cftmdl1(m, &a[j - m], &w[nw - (m >> 1)]);
m >>= 2;
}
} else {
while (m > 128) {
cftmdl2(m, &a[j - m], &w[nw - m]);
m >>= 2;
}
}
}
return isplt;
}
void cftleaf(int n, int isplt, double *a, int nw, double *w)
{
void cftmdl1(int n, double *a, double *w);
void cftmdl2(int n, double *a, double *w);
void cftf161(double *a, double *w);
void cftf162(double *a, double *w);
void cftf081(double *a, double *w);
void cftf082(double *a, double *w);
if (n == 512) {
cftmdl1(128, a, &w[nw - 64]);
cftf161(a, &w[nw - 8]);
cftf162(&a[32], &w[nw - 32]);
cftf161(&a[64], &w[nw - 8]);
cftf161(&a[96], &w[nw - 8]);
cftmdl2(128, &a[128], &w[nw - 128]);
cftf161(&a[128], &w[nw - 8]);
cftf162(&a[160], &w[nw - 32]);
cftf161(&a[192], &w[nw - 8]);
cftf162(&a[224], &w[nw - 32]);
cftmdl1(128, &a[256], &w[nw - 64]);
cftf161(&a[256], &w[nw - 8]);
cftf162(&a[288], &w[nw - 32]);
cftf161(&a[320], &w[nw - 8]);
cftf161(&a[352], &w[nw - 8]);
if (isplt != 0) {
cftmdl1(128, &a[384], &w[nw - 64]);
cftf161(&a[480], &w[nw - 8]);
} else {
cftmdl2(128, &a[384], &w[nw - 128]);
cftf162(&a[480], &w[nw - 32]);
}
cftf161(&a[384], &w[nw - 8]);
cftf162(&a[416], &w[nw - 32]);
cftf161(&a[448], &w[nw - 8]);
} else {
cftmdl1(64, a, &w[nw - 32]);
cftf081(a, &w[nw - 8]);
cftf082(&a[16], &w[nw - 8]);
cftf081(&a[32], &w[nw - 8]);
cftf081(&a[48], &w[nw - 8]);
cftmdl2(64, &a[64], &w[nw - 64]);
cftf081(&a[64], &w[nw - 8]);
cftf082(&a[80], &w[nw - 8]);
cftf081(&a[96], &w[nw - 8]);
cftf082(&a[112], &w[nw - 8]);
cftmdl1(64, &a[128], &w[nw - 32]);
cftf081(&a[128], &w[nw - 8]);
cftf082(&a[144], &w[nw - 8]);
cftf081(&a[160], &w[nw - 8]);
cftf081(&a[176], &w[nw - 8]);
if (isplt != 0) {
cftmdl1(64, &a[192], &w[nw - 32]);
cftf081(&a[240], &w[nw - 8]);
} else {
cftmdl2(64, &a[192], &w[nw - 64]);
cftf082(&a[240], &w[nw - 8]);
}
cftf081(&a[192], &w[nw - 8]);
cftf082(&a[208], &w[nw - 8]);
cftf081(&a[224], &w[nw - 8]);
}
}
void cftmdl1(int n, double *a, double *w)
{
int j, j0, j1, j2, j3, k, m, mh;
double wn4r, wk1r, wk1i, wk3r, wk3i;
double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
mh = n >> 3;
m = 2 * mh;
j1 = m;
j2 = j1 + m;
j3 = j2 + m;
x0r = a[0] + a[j2];
x0i = a[1] + a[j2 + 1];
x1r = a[0] - a[j2];
x1i = a[1] - a[j2 + 1];
x2r = a[j1] + a[j3];
x2i = a[j1 + 1] + a[j3 + 1];
x3r = a[j1] - a[j3];
x3i = a[j1 + 1] - a[j3 + 1];
a[0] = x0r + x2r;
a[1] = x0i + x2i;
a[j1] = x0r - x2r;
a[j1 + 1] = x0i - x2i;
a[j2] = x1r - x3i;
a[j2 + 1] = x1i + x3r;
a[j3] = x1r + x3i;
a[j3 + 1] = x1i - x3r;
wn4r = w[1];
k = 0;
for (j = 2; j < mh; j += 2) {
k += 4;
wk1r = w[k];
wk1i = w[k + 1];
wk3r = w[k + 2];
wk3i = w[k + 3];
j1 = j + m;
j2 = j1 + m;
j3 = j2 + m;
x0r = a[j] + a[j2];
x0i = a[j + 1] + a[j2 + 1];
x1r = a[j] - a[j2];
x1i = a[j + 1] - a[j2 + 1];
x2r = a[j1] + a[j3];
x2i = a[j1 + 1] + a[j3 + 1];
x3r = a[j1] - a[j3];
x3i = a[j1 + 1] - a[j3 + 1];
a[j] = x0r + x2r;
a[j + 1] = x0i + x2i;
a[j1] = x0r - x2r;
a[j1 + 1] = x0i - x2i;
x0r = x1r - x3i;
x0i = x1i + x3r;
a[j2] = wk1r * x0r - wk1i * x0i;
a[j2 + 1] = wk1r * x0i + wk1i * x0r;
x0r = x1r + x3i;
x0i = x1i - x3r;
a[j3] = wk3r * x0r + wk3i * x0i;
a[j3 + 1] = wk3r * x0i - wk3i * x0r;
j0 = m - j;
j1 = j0 + m;
j2 = j1 + m;
j3 = j2 + m;
x0r = a[j0] + a[j2];
x0i = a[j0 + 1] + a[j2 + 1];
x1r = a[j0] - a[j2];
x1i = a[j0 + 1] - a[j2 + 1];
x2r = a[j1] + a[j3];
x2i = a[j1 + 1] + a[j3 + 1];
x3r = a[j1] - a[j3];
x3i = a[j1 + 1] - a[j3 + 1];
a[j0] = x0r + x2r;
a[j0 + 1] = x0i + x2i;
a[j1] = x0r - x2r;
a[j1 + 1] = x0i - x2i;
x0r = x1r - x3i;
x0i = x1i + x3r;
a[j2] = wk1i * x0r - wk1r * x0i;
a[j2 + 1] = wk1i * x0i + wk1r * x0r;
x0r = x1r + x3i;
x0i = x1i - x3r;
a[j3] = wk3i * x0r + wk3r * x0i;
a[j3 + 1] = wk3i * x0i - wk3r * x0r;
}
j0 = mh;
j1 = j0 + m;
j2 = j1 + m;
j3 = j2 + m;
x0r = a[j0] + a[j2];
x0i = a[j0 + 1] + a[j2 + 1];
x1r = a[j0] - a[j2];
x1i = a[j0 + 1] - a[j2 + 1];
x2r = a[j1] + a[j3];
x2i = a[j1 + 1] + a[j3 + 1];
x3r = a[j1] - a[j3];
x3i = a[j1 + 1] - a[j3 + 1];
a[j0] = x0r + x2r;
a[j0 + 1] = x0i + x2i;
a[j1] = x0r - x2r;
a[j1 + 1] = x0i - x2i;
x0r = x1r - x3i;
x0i = x1i + x3r;
a[j2] = wn4r * (x0r - x0i);
a[j2 + 1] = wn4r * (x0i + x0r);
x0r = x1r + x3i;
x0i = x1i - x3r;
a[j3] = -wn4r * (x0r + x0i);
a[j3 + 1] = -wn4r * (x0i - x0r);
}
void cftmdl2(int n, double *a, double *w)
{
int j, j0, j1, j2, j3, k, kr, m, mh;
double wn4r, wk1r, wk1i, wk3r, wk3i, wd1r, wd1i, wd3r, wd3i;
double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y2r, y2i;
mh = n >> 3;
m = 2 * mh;
wn4r = w[1];
j1 = m;
j2 = j1 + m;
j3 = j2 + m;
x0r = a[0] - a[j2 + 1];
x0i = a[1] + a[j2];
x1r = a[0] + a[j2 + 1];
x1i = a[1] - a[j2];
x2r = a[j1] - a[j3 + 1];
x2i = a[j1 + 1] + a[j3];
x3r = a[j1] + a[j3 + 1];
x3i = a[j1 + 1] - a[j3];
y0r = wn4r * (x2r - x2i);
y0i = wn4r * (x2i + x2r);
a[0] = x0r + y0r;
a[1] = x0i + y0i;
a[j1] = x0r - y0r;
a[j1 + 1] = x0i - y0i;
y0r = wn4r * (x3r - x3i);
y0i = wn4r * (x3i + x3r);
a[j2] = x1r - y0i;
a[j2 + 1] = x1i + y0r;
a[j3] = x1r + y0i;
a[j3 + 1] = x1i - y0r;
k = 0;
kr = 2 * m;
for (j = 2; j < mh; j += 2) {
k += 4;
wk1r = w[k];
wk1i = w[k + 1];
wk3r = w[k + 2];
wk3i = w[k + 3];
kr -= 4;
wd1i = w[kr];
wd1r = w[kr + 1];
wd3i = w[kr + 2];
wd3r = w[kr + 3];
j1 = j + m;
j2 = j1 + m;
j3 = j2 + m;
x0r = a[j] - a[j2 + 1];
x0i = a[j + 1] + a[j2];
x1r = a[j] + a[j2 + 1];
x1i = a[j + 1] - a[j2];
x2r = a[j1] - a[j3 + 1];
x2i = a[j1 + 1] + a[j3];
x3r = a[j1] + a[j3 + 1];
x3i = a[j1 + 1] - a[j3];
y0r = wk1r * x0r - wk1i * x0i;
y0i = wk1r * x0i + wk1i * x0r;
y2r = wd1r * x2r - wd1i * x2i;
y2i = wd1r * x2i + wd1i * x2r;
a[j] = y0r + y2r;
a[j + 1] = y0i + y2i;
a[j1] = y0r - y2r;
a[j1 + 1] = y0i - y2i;
y0r = wk3r * x1r + wk3i * x1i;
y0i = wk3r * x1i - wk3i * x1r;
y2r = wd3r * x3r + wd3i * x3i;
y2i = wd3r * x3i - wd3i * x3r;
a[j2] = y0r + y2r;
a[j2 + 1] = y0i + y2i;
a[j3] = y0r - y2r;
a[j3 + 1] = y0i - y2i;
j0 = m - j;
j1 = j0 + m;
j2 = j1 + m;
j3 = j2 + m;
x0r = a[j0] - a[j2 + 1];
x0i = a[j0 + 1] + a[j2];
x1r = a[j0] + a[j2 + 1];
x1i = a[j0 + 1] - a[j2];
x2r = a[j1] - a[j3 + 1];
x2i = a[j1 + 1] + a[j3];
x3r = a[j1] + a[j3 + 1];
x3i = a[j1 + 1] - a[j3];
y0r = wd1i * x0r - wd1r * x0i;
y0i = wd1i * x0i + wd1r * x0r;
y2r = wk1i * x2r - wk1r * x2i;
y2i = wk1i * x2i + wk1r * x2r;
a[j0] = y0r + y2r;
a[j0 + 1] = y0i + y2i;
a[j1] = y0r - y2r;
a[j1 + 1] = y0i - y2i;
y0r = wd3i * x1r + wd3r * x1i;
y0i = wd3i * x1i - wd3r * x1r;
y2r = wk3i * x3r + wk3r * x3i;
y2i = wk3i * x3i - wk3r * x3r;
a[j2] = y0r + y2r;
a[j2 + 1] = y0i + y2i;
a[j3] = y0r - y2r;
a[j3 + 1] = y0i - y2i;
}
wk1r = w[m];
wk1i = w[m + 1];
j0 = mh;
j1 = j0 + m;
j2 = j1 + m;
j3 = j2 + m;
x0r = a[j0] - a[j2 + 1];
x0i = a[j0 + 1] + a[j2];
x1r = a[j0] + a[j2 + 1];
x1i = a[j0 + 1] - a[j2];
x2r = a[j1] - a[j3 + 1];
x2i = a[j1 + 1] + a[j3];
x3r = a[j1] + a[j3 + 1];
x3i = a[j1 + 1] - a[j3];
y0r = wk1r * x0r - wk1i * x0i;
y0i = wk1r * x0i + wk1i * x0r;
y2r = wk1i * x2r - wk1r * x2i;
y2i = wk1i * x2i + wk1r * x2r;
a[j0] = y0r + y2r;
a[j0 + 1] = y0i + y2i;
a[j1] = y0r - y2r;
a[j1 + 1] = y0i - y2i;
y0r = wk1i * x1r - wk1r * x1i;
y0i = wk1i * x1i + wk1r * x1r;
y2r = wk1r * x3r - wk1i * x3i;
y2i = wk1r * x3i + wk1i * x3r;
a[j2] = y0r - y2r;
a[j2 + 1] = y0i - y2i;
a[j3] = y0r + y2r;
a[j3 + 1] = y0i + y2i;
}
void cftfx41(int n, double *a, int nw, double *w)
{
void cftf161(double *a, double *w);
void cftf162(double *a, double *w);
void cftf081(double *a, double *w);
void cftf082(double *a, double *w);
if (n == 128) {
cftf161(a, &w[nw - 8]);
cftf162(&a[32], &w[nw - 32]);
cftf161(&a[64], &w[nw - 8]);
cftf161(&a[96], &w[nw - 8]);
} else {
cftf081(a, &w[nw - 8]);
cftf082(&a[16], &w[nw - 8]);
cftf081(&a[32], &w[nw - 8]);
cftf081(&a[48], &w[nw - 8]);
}
}
void cftf161(double *a, double *w)
{
double wn4r, wk1r, wk1i,
x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i,
y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i,
y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i,
y8r, y8i, y9r, y9i, y10r, y10i, y11r, y11i,
y12r, y12i, y13r, y13i, y14r, y14i, y15r, y15i;
wn4r = w[1];
wk1r = w[2];
wk1i = w[3];
x0r = a[0] + a[16];
x0i = a[1] + a[17];
x1r = a[0] - a[16];
x1i = a[1] - a[17];
x2r = a[8] + a[24];
x2i = a[9] + a[25];
x3r = a[8] - a[24];
x3i = a[9] - a[25];
y0r = x0r + x2r;
y0i = x0i + x2i;
y4r = x0r - x2r;
y4i = x0i - x2i;
y8r = x1r - x3i;
y8i = x1i + x3r;
y12r = x1r + x3i;
y12i = x1i - x3r;
x0r = a[2] + a[18];
x0i = a[3] + a[19];
x1r = a[2] - a[18];
x1i = a[3] - a[19];
x2r = a[10] + a[26];
x2i = a[11] + a[27];
x3r = a[10] - a[26];
x3i = a[11] - a[27];
y1r = x0r + x2r;
y1i = x0i + x2i;
y5r = x0r - x2r;
y5i = x0i - x2i;
x0r = x1r - x3i;
x0i = x1i + x3r;
y9r = wk1r * x0r - wk1i * x0i;
y9i = wk1r * x0i + wk1i * x0r;
x0r = x1r + x3i;
x0i = x1i - x3r;
y13r = wk1i * x0r - wk1r * x0i;
y13i = wk1i * x0i + wk1r * x0r;
x0r = a[4] + a[20];
x0i = a[5] + a[21];
x1r = a[4] - a[20];
x1i = a[5] - a[21];
x2r = a[12] + a[28];
x2i = a[13] + a[29];
x3r = a[12] - a[28];
x3i = a[13] - a[29];
y2r = x0r + x2r;
y2i = x0i + x2i;
y6r = x0r - x2r;
y6i = x0i - x2i;
x0r = x1r - x3i;
x0i = x1i + x3r;
y10r = wn4r * (x0r - x0i);
y10i = wn4r * (x0i + x0r);
x0r = x1r + x3i;
x0i = x1i - x3r;
y14r = wn4r * (x0r + x0i);
y14i = wn4r * (x0i - x0r);
x0r = a[6] + a[22];
x0i = a[7] + a[23];
x1r = a[6] - a[22];
x1i = a[7] - a[23];
x2r = a[14] + a[30];
x2i = a[15] + a[31];
x3r = a[14] - a[30];
x3i = a[15] - a[31];
y3r = x0r + x2r;
y3i = x0i + x2i;
y7r = x0r - x2r;
y7i = x0i - x2i;
x0r = x1r - x3i;
x0i = x1i + x3r;
y11r = wk1i * x0r - wk1r * x0i;
y11i = wk1i * x0i + wk1r * x0r;
x0r = x1r + x3i;
x0i = x1i - x3r;
y15r = wk1r * x0r - wk1i * x0i;
y15i = wk1r * x0i + wk1i * x0r;
x0r = y12r - y14r;
x0i = y12i - y14i;
x1r = y12r + y14r;
x1i = y12i + y14i;
x2r = y13r - y15r;
x2i = y13i - y15i;
x3r = y13r + y15r;
x3i = y13i + y15i;
a[24] = x0r + x2r;
a[25] = x0i + x2i;
a[26] = x0r - x2r;
a[27] = x0i - x2i;
a[28] = x1r - x3i;
a[29] = x1i + x3r;
a[30] = x1r + x3i;
a[31] = x1i - x3r;
x0r = y8r + y10r;
x0i = y8i + y10i;
x1r = y8r - y10r;
x1i = y8i - y10i;
x2r = y9r + y11r;
x2i = y9i + y11i;
x3r = y9r - y11r;
x3i = y9i - y11i;
a[16] = x0r + x2r;
a[17] = x0i + x2i;
a[18] = x0r - x2r;
a[19] = x0i - x2i;
a[20] = x1r - x3i;
a[21] = x1i + x3r;
a[22] = x1r + x3i;
a[23] = x1i - x3r;
x0r = y5r - y7i;
x0i = y5i + y7r;
x2r = wn4r * (x0r - x0i);
x2i = wn4r * (x0i + x0r);
x0r = y5r + y7i;
x0i = y5i - y7r;
x3r = wn4r * (x0r - x0i);
x3i = wn4r * (x0i + x0r);
x0r = y4r - y6i;
x0i = y4i + y6r;
x1r = y4r + y6i;
x1i = y4i - y6r;
a[8] = x0r + x2r;
a[9] = x0i + x2i;
a[10] = x0r - x2r;
a[11] = x0i - x2i;
a[12] = x1r - x3i;
a[13] = x1i + x3r;
a[14] = x1r + x3i;
a[15] = x1i - x3r;
x0r = y0r + y2r;
x0i = y0i + y2i;
x1r = y0r - y2r;
x1i = y0i - y2i;
x2r = y1r + y3r;
x2i = y1i + y3i;
x3r = y1r - y3r;
x3i = y1i - y3i;
a[0] = x0r + x2r;
a[1] = x0i + x2i;
a[2] = x0r - x2r;
a[3] = x0i - x2i;
a[4] = x1r - x3i;
a[5] = x1i + x3r;
a[6] = x1r + x3i;
a[7] = x1i - x3r;
}
void cftf162(double *a, double *w)
{
double wn4r, wk1r, wk1i, wk2r, wk2i, wk3r, wk3i,
x0r, x0i, x1r, x1i, x2r, x2i,
y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i,
y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i,
y8r, y8i, y9r, y9i, y10r, y10i, y11r, y11i,
y12r, y12i, y13r, y13i, y14r, y14i, y15r, y15i;
wn4r = w[1];
wk1r = w[4];
wk1i = w[5];
wk3r = w[6];
wk3i = -w[7];
wk2r = w[8];
wk2i = w[9];
x1r = a[0] - a[17];
x1i = a[1] + a[16];
x0r = a[8] - a[25];
x0i = a[9] + a[24];
x2r = wn4r * (x0r - x0i);
x2i = wn4r * (x0i + x0r);
y0r = x1r + x2r;
y0i = x1i + x2i;
y4r = x1r - x2r;
y4i = x1i - x2i;
x1r = a[0] + a[17];
x1i = a[1] - a[16];
x0r = a[8] + a[25];
x0i = a[9] - a[24];
x2r = wn4r * (x0r - x0i);
x2i = wn4r * (x0i + x0r);
y8r = x1r - x2i;
y8i = x1i + x2r;
y12r = x1r + x2i;
y12i = x1i - x2r;
x0r = a[2] - a[19];
x0i = a[3] + a[18];
x1r = wk1r * x0r - wk1i * x0i;
x1i = wk1r * x0i + wk1i * x0r;
x0r = a[10] - a[27];
x0i = a[11] + a[26];
x2r = wk3i * x0r - wk3r * x0i;
x2i = wk3i * x0i + wk3r * x0r;
y1r = x1r + x2r;
y1i = x1i + x2i;
y5r = x1r - x2r;
y5i = x1i - x2i;
x0r = a[2] + a[19];
x0i = a[3] - a[18];
x1r = wk3r * x0r - wk3i * x0i;
x1i = wk3r * x0i + wk3i * x0r;
x0r = a[10] + a[27];
x0i = a[11] - a[26];
x2r = wk1r * x0r + wk1i * x0i;
x2i = wk1r * x0i - wk1i * x0r;
y9r = x1r - x2r;
y9i = x1i - x2i;
y13r = x1r + x2r;
y13i = x1i + x2i;
x0r = a[4] - a[21];
x0i = a[5] + a[20];
x1r = wk2r * x0r - wk2i * x0i;
x1i = wk2r * x0i + wk2i * x0r;
x0r = a[12] - a[29];
x0i = a[13] + a[28];
x2r = wk2i * x0r - wk2r * x0i;
x2i = wk2i * x0i + wk2r * x0r;
y2r = x1r + x2r;
y2i = x1i + x2i;
y6r = x1r - x2r;
y6i = x1i - x2i;
x0r = a[4] + a[21];
x0i = a[5] - a[20];
x1r = wk2i * x0r - wk2r * x0i;
x1i = wk2i * x0i + wk2r * x0r;
x0r = a[12] + a[29];
x0i = a[13] - a[28];
x2r = wk2r * x0r - wk2i * x0i;
x2i = wk2r * x0i + wk2i * x0r;
y10r = x1r - x2r;
y10i = x1i - x2i;
y14r = x1r + x2r;
y14i = x1i + x2i;
x0r = a[6] - a[23];
x0i = a[7] + a[22];
x1r = wk3r * x0r - wk3i * x0i;
x1i = wk3r * x0i + wk3i * x0r;
x0r = a[14] - a[31];
x0i = a[15] + a[30];
x2r = wk1i * x0r - wk1r * x0i;
x2i = wk1i * x0i + wk1r * x0r;
y3r = x1r + x2r;
y3i = x1i + x2i;
y7r = x1r - x2r;
y7i = x1i - x2i;
x0r = a[6] + a[23];
x0i = a[7] - a[22];
x1r = wk1i * x0r + wk1r * x0i;
x1i = wk1i * x0i - wk1r * x0r;
x0r = a[14] + a[31];
x0i = a[15] - a[30];
x2r = wk3i * x0r - wk3r * x0i;
x2i = wk3i * x0i + wk3r * x0r;
y11r = x1r + x2r;
y11i = x1i + x2i;
y15r = x1r - x2r;
y15i = x1i - x2i;
x1r = y0r + y2r;
x1i = y0i + y2i;
x2r = y1r + y3r;
x2i = y1i + y3i;
a[0] = x1r + x2r;
a[1] = x1i + x2i;
a[2] = x1r - x2r;
a[3] = x1i - x2i;
x1r = y0r - y2r;
x1i = y0i - y2i;
x2r = y1r - y3r;
x2i = y1i - y3i;
a[4] = x1r - x2i;
a[5] = x1i + x2r;
a[6] = x1r + x2i;
a[7] = x1i - x2r;
x1r = y4r - y6i;
x1i = y4i + y6r;
x0r = y5r - y7i;
x0i = y5i + y7r;
x2r = wn4r * (x0r - x0i);
x2i = wn4r * (x0i + x0r);
a[8] = x1r + x2r;
a[9] = x1i + x2i;
a[10] = x1r - x2r;
a[11] = x1i - x2i;
x1r = y4r + y6i;
x1i = y4i - y6r;
x0r = y5r + y7i;
x0i = y5i - y7r;
x2r = wn4r * (x0r - x0i);
x2i = wn4r * (x0i + x0r);
a[12] = x1r - x2i;
a[13] = x1i + x2r;
a[14] = x1r + x2i;
a[15] = x1i - x2r;
x1r = y8r + y10r;
x1i = y8i + y10i;
x2r = y9r - y11r;
x2i = y9i - y11i;
a[16] = x1r + x2r;
a[17] = x1i + x2i;
a[18] = x1r - x2r;
a[19] = x1i - x2i;
x1r = y8r - y10r;
x1i = y8i - y10i;
x2r = y9r + y11r;
x2i = y9i + y11i;
a[20] = x1r - x2i;
a[21] = x1i + x2r;
a[22] = x1r + x2i;
a[23] = x1i - x2r;
x1r = y12r - y14i;
x1i = y12i + y14r;
x0r = y13r + y15i;
x0i = y13i - y15r;
x2r = wn4r * (x0r - x0i);
x2i = wn4r * (x0i + x0r);
a[24] = x1r + x2r;
a[25] = x1i + x2i;
a[26] = x1r - x2r;
a[27] = x1i - x2i;
x1r = y12r + y14i;
x1i = y12i - y14r;
x0r = y13r - y15i;
x0i = y13i + y15r;
x2r = wn4r * (x0r - x0i);
x2i = wn4r * (x0i + x0r);
a[28] = x1r - x2i;
a[29] = x1i + x2r;
a[30] = x1r + x2i;
a[31] = x1i - x2r;
}
void cftf081(double *a, double *w)
{
double wn4r, x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i,
y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i,
y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i;
wn4r = w[1];
x0r = a[0] + a[8];
x0i = a[1] + a[9];
x1r = a[0] - a[8];
x1i = a[1] - a[9];
x2r = a[4] + a[12];
x2i = a[5] + a[13];
x3r = a[4] - a[12];
x3i = a[5] - a[13];
y0r = x0r + x2r;
y0i = x0i + x2i;
y2r = x0r - x2r;
y2i = x0i - x2i;
y1r = x1r - x3i;
y1i = x1i + x3r;
y3r = x1r + x3i;
y3i = x1i - x3r;
x0r = a[2] + a[10];
x0i = a[3] + a[11];
x1r = a[2] - a[10];
x1i = a[3] - a[11];
x2r = a[6] + a[14];
x2i = a[7] + a[15];
x3r = a[6] - a[14];
x3i = a[7] - a[15];
y4r = x0r + x2r;
y4i = x0i + x2i;
y6r = x0r - x2r;
y6i = x0i - x2i;
x0r = x1r - x3i;
x0i = x1i + x3r;
x2r = x1r + x3i;
x2i = x1i - x3r;
y5r = wn4r * (x0r - x0i);
y5i = wn4r * (x0r + x0i);
y7r = wn4r * (x2r - x2i);
y7i = wn4r * (x2r + x2i);
a[8] = y1r + y5r;
a[9] = y1i + y5i;
a[10] = y1r - y5r;
a[11] = y1i - y5i;
a[12] = y3r - y7i;
a[13] = y3i + y7r;
a[14] = y3r + y7i;
a[15] = y3i - y7r;
a[0] = y0r + y4r;
a[1] = y0i + y4i;
a[2] = y0r - y4r;
a[3] = y0i - y4i;
a[4] = y2r - y6i;
a[5] = y2i + y6r;
a[6] = y2r + y6i;
a[7] = y2i - y6r;
}
void cftf082(double *a, double *w)
{
double wn4r, wk1r, wk1i, x0r, x0i, x1r, x1i,
y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i,
y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i;
wn4r = w[1];
wk1r = w[2];
wk1i = w[3];
y0r = a[0] - a[9];
y0i = a[1] + a[8];
y1r = a[0] + a[9];
y1i = a[1] - a[8];
x0r = a[4] - a[13];
x0i = a[5] + a[12];
y2r = wn4r * (x0r - x0i);
y2i = wn4r * (x0i + x0r);
x0r = a[4] + a[13];
x0i = a[5] - a[12];
y3r = wn4r * (x0r - x0i);
y3i = wn4r * (x0i + x0r);
x0r = a[2] - a[11];
x0i = a[3] + a[10];
y4r = wk1r * x0r - wk1i * x0i;
y4i = wk1r * x0i + wk1i * x0r;
x0r = a[2] + a[11];
x0i = a[3] - a[10];
y5r = wk1i * x0r - wk1r * x0i;
y5i = wk1i * x0i + wk1r * x0r;
x0r = a[6] - a[15];
x0i = a[7] + a[14];
y6r = wk1i * x0r - wk1r * x0i;
y6i = wk1i * x0i + wk1r * x0r;
x0r = a[6] + a[15];
x0i = a[7] - a[14];
y7r = wk1r * x0r - wk1i * x0i;
y7i = wk1r * x0i + wk1i * x0r;
x0r = y0r + y2r;
x0i = y0i + y2i;
x1r = y4r + y6r;
x1i = y4i + y6i;
a[0] = x0r + x1r;
a[1] = x0i + x1i;
a[2] = x0r - x1r;
a[3] = x0i - x1i;
x0r = y0r - y2r;
x0i = y0i - y2i;
x1r = y4r - y6r;
x1i = y4i - y6i;
a[4] = x0r - x1i;
a[5] = x0i + x1r;
a[6] = x0r + x1i;
a[7] = x0i - x1r;
x0r = y1r - y3i;
x0i = y1i + y3r;
x1r = y5r - y7r;
x1i = y5i - y7i;
a[8] = x0r + x1r;
a[9] = x0i + x1i;
a[10] = x0r - x1r;
a[11] = x0i - x1i;
x0r = y1r + y3i;
x0i = y1i - y3r;
x1r = y5r + y7r;
x1i = y5i + y7i;
a[12] = x0r - x1i;
a[13] = x0i + x1r;
a[14] = x0r + x1i;
a[15] = x0i - x1r;
}
void cftf040(double *a)
{
double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
x0r = a[0] + a[4];
x0i = a[1] + a[5];
x1r = a[0] - a[4];
x1i = a[1] - a[5];
x2r = a[2] + a[6];
x2i = a[3] + a[7];
x3r = a[2] - a[6];
x3i = a[3] - a[7];
a[0] = x0r + x2r;
a[1] = x0i + x2i;
a[2] = x1r - x3i;
a[3] = x1i + x3r;
a[4] = x0r - x2r;
a[5] = x0i - x2i;
a[6] = x1r + x3i;
a[7] = x1i - x3r;
}
void cftb040(double *a)
{
double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
x0r = a[0] + a[4];
x0i = a[1] + a[5];
x1r = a[0] - a[4];
x1i = a[1] - a[5];
x2r = a[2] + a[6];
x2i = a[3] + a[7];
x3r = a[2] - a[6];
x3i = a[3] - a[7];
a[0] = x0r + x2r;
a[1] = x0i + x2i;
a[2] = x1r + x3i;
a[3] = x1i - x3r;
a[4] = x0r - x2r;
a[5] = x0i - x2i;
a[6] = x1r - x3i;
a[7] = x1i + x3r;
}
void cftx020(double *a)
{
double x0r, x0i;
x0r = a[0] - a[2];
x0i = a[1] - a[3];
a[0] += a[2];
a[1] += a[3];
a[2] = x0r;
a[3] = x0i;
}
void rftfsub(int n, double *a, int nc, double *c)
{
int j, k, kk, ks, m;
double wkr, wki, xr, xi, yr, yi;
m = n >> 1;
ks = 2 * nc / m;
kk = 0;
for (j = 2; j < m; j += 2) {
k = n - j;
kk += ks;
wkr = 0.5 - c[nc - kk];
wki = c[kk];
xr = a[j] - a[k];
xi = a[j + 1] + a[k + 1];
yr = wkr * xr - wki * xi;
yi = wkr * xi + wki * xr;
a[j] -= yr;
a[j + 1] -= yi;
a[k] += yr;
a[k + 1] -= yi;
}
}
void rftbsub(int n, double *a, int nc, double *c)
{
int j, k, kk, ks, m;
double wkr, wki, xr, xi, yr, yi;
m = n >> 1;
ks = 2 * nc / m;
kk = 0;
for (j = 2; j < m; j += 2) {
k = n - j;
kk += ks;
wkr = 0.5 - c[nc - kk];
wki = c[kk];
xr = a[j] - a[k];
xi = a[j + 1] + a[k + 1];
yr = wkr * xr + wki * xi;
yi = wkr * xi - wki * xr;
a[j] -= yr;
a[j + 1] -= yi;
a[k] += yr;
a[k + 1] -= yi;
}
}
void dctsub(int n, double *a, int nc, double *c)
{
int j, k, kk, ks, m;
double wkr, wki, xr;
m = n >> 1;
ks = nc / n;
kk = 0;
for (j = 1; j < m; j++) {
k = n - j;
kk += ks;
wkr = c[kk] - c[nc - kk];
wki = c[kk] + c[nc - kk];
xr = wki * a[j] - wkr * a[k];
a[j] = wkr * a[j] + wki * a[k];
a[k] = xr;
}
a[m] *= c[0];
}
void dstsub(int n, double *a, int nc, double *c)
{
int j, k, kk, ks, m;
double wkr, wki, xr;
m = n >> 1;
ks = nc / n;
kk = 0;
for (j = 1; j < m; j++) {
k = n - j;
kk += ks;
wkr = c[kk] - c[nc - kk];
wki = c[kk] + c[nc - kk];
xr = wki * a[k] - wkr * a[j];
a[k] = wkr * a[k] + wki * a[j];
a[j] = xr;
}
a[m] *= c[0];
}
/*****************************************************************************
* fftsg.c:
*****************************************************************************
* Copyright (C) 2004 the VideoLAN team
* $Id$
*
* Authors: Cyril Deguet <asmax@videolan.org>
* code from projectM http://xmms-projectm.sourceforge.net
*
* 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
void cdft(int, int, double *, int *, double *);
void rdft(int, int, double *, int *, double *);
void ddct(int, int, double *, int *, double *);
void ddst(int, int, double *, int *, double *);
void dfct(int, double *, double *, int *, double *);
void dfst(int, double *, double *, int *, double *);
/* Function management */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "common.h"
#include "fatal.h"
#include "func_types.h"
#include "func.h"
#include "splaytree_types.h"
#include "splaytree.h"
#include "tree_types.h"
#include "builtin_funcs.h"
/* A splay tree of builtin functions */
splaytree_t * builtin_func_tree;
/* Private function prototypes */
int compare_func(char * name, char * name2);
int insert_func(func_t * name);
void * copy_func_key(char * string);
void * copy_func_key(char * string) {
char * clone_string;
if ((clone_string = malloc(MAX_TOKEN_SIZE)) == NULL)
return NULL;
strncpy(clone_string, string, MAX_TOKEN_SIZE-1);
return (void*)clone_string;
}
func_t * create_func (const char * name, double (*func_ptr)(), int num_args) {
func_t * func;
func = (func_t*)malloc(sizeof(func_t));
if (func == NULL)
return NULL;
/* Clear name space */
memset(func->name, 0, MAX_TOKEN_SIZE);
/* Copy given name into function structure */
strncpy(func->name, name, MAX_TOKEN_SIZE);
/* Assign value pointer */
func->func_ptr = func_ptr;
func->num_args = num_args;
/* Return instantiated function */
return func;
}
/* Initialize the builtin function database.
Should only be necessary once */
int init_builtin_func_db() {
int retval;
builtin_func_tree = create_splaytree(compare_string, copy_string, free_string);
if (builtin_func_tree == NULL)
return OUTOFMEM_ERROR;
retval = load_all_builtin_func();
return SUCCESS;
}
/* Destroy the builtin function database.
Generally, do this on projectm exit */
int destroy_builtin_func_db() {
splay_traverse(free_func, builtin_func_tree);
destroy_splaytree(builtin_func_tree);
return SUCCESS;
}
/* Insert a function into the database */
int insert_func(func_t * func) {
if (func == NULL)
return ERROR;
splay_insert(func, func->name, builtin_func_tree);
return SUCCESS;
}
/* Frees a function type, real complicated... */
void free_func(func_t * func) {
free(func);
}
/* Remove a function from the database */
int remove_func(func_t * func) {
if (func == NULL)
return ERROR;
splay_delete(func->name, builtin_func_tree);
return SUCCESS;
}
/* Find a function given its name */
func_t * find_func(char * name) {
func_t * func = NULL;
/* First look in the builtin database */
func = (func_t *)splay_find(name, builtin_func_tree);
return func;
}
/* Compare string name with function name */
int compare_func(char * name, char * name2) {
int cmpval;
/* Uses string comparison function */
cmpval = strncmp(name, name2, MAX_TOKEN_SIZE-1);
return cmpval;
}
/* Loads a builtin function */
int load_builtin_func(const char * name, double (*func_ptr)(), int num_args) {
func_t * func;
int retval;
/* Create new function */
func = create_func(name, func_ptr, num_args);
if (func == NULL)
return OUTOFMEM_ERROR;
retval = insert_func(func);
return retval;
}
/* Loads all builtin functions */
int load_all_builtin_func() {
if (load_builtin_func("int", int_wrapper, 1) < 0)
return ERROR;
if (load_builtin_func("abs", abs_wrapper, 1) < 0)
return ERROR;
if (load_builtin_func("sin", sin_wrapper, 1) < 0)
return ERROR;
if (load_builtin_func("cos", cos_wrapper, 1) < 0)
return ERROR;
if (load_builtin_func("tan", tan_wrapper, 1) < 0)
return ERROR;
if (load_builtin_func("asin", asin_wrapper, 1) < 0)
return ERROR;
if (load_builtin_func("acos", acos_wrapper, 1) < 0)
return ERROR;
if (load_builtin_func("atan", atan_wrapper, 1) < 0)
return ERROR;
if (load_builtin_func("sqr", sqr_wrapper, 1) < 0)
return ERROR;
if (load_builtin_func("sqrt", sqrt_wrapper, 1) < 0)
return ERROR;
if (load_builtin_func("pow", pow_wrapper, 2) < 0)
return ERROR;
if (load_builtin_func("exp", exp_wrapper, 1) < 0)
return ERROR;
if (load_builtin_func("log", log_wrapper, 1) < 0)
return ERROR;
if (load_builtin_func("log10", log10_wrapper, 1) < 0)
return ERROR;
if (load_builtin_func("sign", sign_wrapper, 1) < 0)
return ERROR;
if (load_builtin_func("min", min_wrapper, 2) < 0)
return ERROR;
if (load_builtin_func("max", max_wrapper, 2) < 0)
return ERROR;
if (load_builtin_func("sigmoid", sigmoid_wrapper, 2) < 0)
return ERROR;
if (load_builtin_func("atan2", atan2_wrapper, 2) < 0)
return ERROR;
if (load_builtin_func("rand", rand_wrapper, 1) < 0)
return ERROR;
if (load_builtin_func("band", band_wrapper, 2) < 0)
return ERROR;
if (load_builtin_func("bor", bor_wrapper, 2) < 0)
return ERROR;
if (load_builtin_func("bnot", bnot_wrapper, 1) < 0)
return ERROR;
if (load_builtin_func("if", if_wrapper, 3) < 0)
return ERROR;
if (load_builtin_func("equal", equal_wrapper, 2) < 0)
return ERROR;
if (load_builtin_func("above", above_wrapper, 2) < 0)
return ERROR;
if (load_builtin_func("below", below_wrapper, 2) < 0)
return ERROR;
if (load_builtin_func("nchoosek", nchoosek_wrapper, 2) < 0)
return ERROR;
if (load_builtin_func("fact", fact_wrapper, 1) < 0)
return ERROR;
return SUCCESS;
}
#ifndef FUNC_H
#define FUNC_H
/* Public Prototypes */
func_t * create_func (const char * name, double (*func_ptr)(), int num_args);
int remove_func(func_t * func);
func_t * find_func(char * name);
int init_builtin_func_db();
int destroy_builtin_func_db();
int load_all_builtin_func();
int load_builtin_func(const char * name, double (*func_ptr)(), int num_args);
void free_func(func_t * func);
#endif
#ifndef FUNC_TYPES_H
#define FUNC_TYPES_H
#include "common.h"
/* Function Type */
typedef struct FUNC_T {
char name[MAX_TOKEN_SIZE];
double (*func_ptr)();
int num_args;
} func_t;
#endif
#ifndef IDLE_PRESET_H
#include "preset_types.h"
#define IDLE_PRESET_H
#define IDLE_PRESET_STRING "[idlepreset]\n"
preset_t * idle_preset;
#endif
/*****************************************************************************
* init_cond.:
*****************************************************************************
* Copyright (C) 2004 the VideoLAN team
* $Id$
*
* Authors: Cyril Deguet <asmax@videolan.org>
* code from projectM http://xmms-projectm.sourceforge.net
*
* 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc_common.h>
/* Library functions to manipulate initial condition values */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "common.h"
#include "fatal.h"
#include "param_types.h"
#include "expr_types.h"
#include "init_cond_types.h"
#include "init_cond.h"
#include "splaytree_types.h"
#include "splaytree.h"
char init_cond_string_buffer[STRING_BUFFER_SIZE];
int init_cond_string_buffer_index = 0;
void init_cond_to_string(init_cond_t * init_cond);
/* Frees initial condition structure */
void free_init_cond(init_cond_t * init_cond) {
free(init_cond);
}
/* Evaluate an initial conditon */
void eval_init_cond(init_cond_t * init_cond) {
if (init_cond == NULL)
return;
/* Parameter is of boolean type, either a 1 or 0 value integer */
/* Set matrix flag to zero. This ensures
its constant value will be used rather than a matrix value
*/
init_cond->param->matrix_flag = 0;
if (init_cond->param->type == P_TYPE_BOOL) {
if (INIT_COND_DEBUG) printf("init_cond: %s = %d (TYPE BOOL)\n", init_cond->param->name, init_cond->init_val.bool_val);
*((int*)init_cond->param->engine_val) = init_cond->init_val.bool_val;
return;
}
/* Parameter is an integer type, just like C */
if (init_cond->param->type == P_TYPE_INT) {
if (INIT_COND_DEBUG) printf("init_cond: %s = %d (TYPE INT)\n", init_cond->param->name, init_cond->init_val.int_val);
*((int*)init_cond->param->engine_val) = init_cond->init_val.int_val;
return;
}
/* Parameter is of a double type, just like C */
if (init_cond->param->type == P_TYPE_DOUBLE) {
if (INIT_COND_DEBUG) printf("init_cond: %s = %f (TYPE DOUBLE)\n", init_cond->param->name, init_cond->init_val.double_val);
*((double*)init_cond->param->engine_val) = init_cond->init_val.double_val;
return;
}
/* Unknown type of parameter */
return;
}
/* Creates a new initial condition */
init_cond_t * new_init_cond(param_t * param, value_t init_val) {
init_cond_t * init_cond;
init_cond = (init_cond_t*)malloc(sizeof(init_cond_t));
if (init_cond == NULL)
return NULL;
init_cond->param = param;
init_cond->init_val = init_val;
return init_cond;
}
/* WIP */
void init_cond_to_string(init_cond_t * init_cond) {
int string_length;
char string[MAX_TOKEN_SIZE];
if (init_cond == NULL)
return;
/* Create a string "param_name=val" */
switch (init_cond->param->type) {
lldiv_t div;
case P_TYPE_BOOL:
sprintf(string, "%s=%d\n", init_cond->param->name, init_cond->init_val.bool_val);
break;
case P_TYPE_INT:
sprintf(string, "%s=%d\n", init_cond->param->name, init_cond->init_val.int_val);
break;
case P_TYPE_DOUBLE:
div = lldiv( init_cond->init_val.double_val * 1000000,
1000000 );
sprintf(string, "%s=%"PRId64".%06u\n", init_cond->param->name, div.quot, (unsigned int) div.rem );
break;
default:
return;
}
/* Compute the length of the string */
string_length = strlen(string);
/* Buffer overflow check */
if ((init_cond_string_buffer_index + string_length + 1) > (STRING_BUFFER_SIZE - 1))
return;
/* Copy the string into the initial condition string buffer */
strncpy(init_cond_string_buffer + init_cond_string_buffer_index, string, string_length);
/* Increment the string buffer, offset by one for the null terminator, which will be
overwritten by the next call to this function */
init_cond_string_buffer_index+= string_length + 1;
}
char * create_init_cond_string_buffer(splaytree_t * init_cond_tree) {
if (init_cond_tree == NULL)
return NULL;
init_cond_string_buffer_index = 0;
splay_traverse(init_cond_to_string, init_cond_tree);
return init_cond_string_buffer;
}
#ifndef INIT_COND_H
#define INIT_COND_H
#define INIT_COND_DEBUG 0
#include "param_types.h"
#include "init_cond_types.h"
#include "splaytree_types.h"
void eval_init_cond(init_cond_t * init_cond);
init_cond_t * new_init_cond(param_t * param, value_t init_val);
void free_init_cond(init_cond_t * init_cond);
char * create_init_cond_string_buffer(splaytree_t * init_cond_tree);
#endif
#ifndef INIT_COND_TYPES_H
#define INIT_COND_TYPES_H
#include "param_types.h"
#include "expr_types.h"
typedef struct INIT_COND_T {
struct PARAM_T * param;
value_t init_val;
} init_cond_t;
#endif
#ifndef INTERFACE_TYPES_H
#define INTERFACE_TYPES_H
typedef enum {
MENU_INTERFACE,
SHELL_INTERFACE,
EDITOR_INTERFACE,
DEFAULT_INTERFACE,
BROWSER_INTERFACE
} interface_t;
#endif
/*****************************************************************************
* main.c:
*****************************************************************************
* Copyright (C) 2004 the VideoLAN team
* $Id$
*
* Authors: Cyril Deguet <asmax@videolan.org>
* Adapted from projectM (http://xmms-projectm.sourceforge.net/)
*
* 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#include "plugin.h"
#include <GL/gl.h>
#include <GL/glu.h>
#include <unistd.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include "common.h"
#include "preset_types.h"
#include "preset.h"
#include "engine_vars.h"
#include "per_pixel_eqn_types.h"
#include "per_pixel_eqn.h"
#include "interface_types.h"
#include "video_init.h" //Video Init Routines, resizing/fullscreen, creating pbuffers
#include "PCM.h" //Sound data handler (buffering, FFT, etc.)
#include "beat_detect.h" //beat detection routines
#include "custom_wave_types.h"
#include "custom_wave.h"
#include "custom_shape_types.h"
#include "custom_shape.h"
#include "splaytree.h"
//#include <dmalloc.h>
// Forward declarations
void read_cfg();
void modulate_opacity_by_volume();
void maximize_colors();
void do_per_pixel_math();
void do_per_frame();
void render_interpolation();
void render_texture_to_screen();
void render_texture_to_studio();
void draw_motion_vectors();
void draw_borders();
void draw_shapes();
void draw_waveform();
void draw_custom_waves();
void reset_per_pixel_matrices();
void init_per_pixel_matrices();
void free_per_pixel_matrices();
int noSwitch=0;
int pcmframes=1;
int freqframes=0;
int totalframes=1;
int studio=0;
extern preset_t * active_preset;
GLuint RenderTargetTextureID;
double wave_o;
//double gx=32; //size of interpolation
//double gy=24;
int texsize=512; //size of texture to do actual graphics
int vw=512; //runtime dimensions
int vh=512;
int fullscreen=0;
int maxsamples=2048; //size of PCM buffer
int numsamples; //size of new PCM info
double *pcmdataL; //holder for most recent pcm data
double *pcmdataR; //holder for most recent pcm data
int avgtime=500; //# frames per preset
char *title = NULL;
int drawtitle;
int title_font;
int other_font;
int correction=1;
double vol;
//per pixel equation variables
double **gridx; //grid containing interpolated mesh
double **gridy;
double **origtheta; //grid containing interpolated mesh reference values
double **origrad;
double **origx; //original mesh
double **origy;
char *buffer; //XXX
static inline int isPerPixelEqn(int op) {
return active_preset->per_pixel_flag[op];
}
int galaktos_init( galaktos_thread_t *p_thread )
{
init_per_pixel_matrices();
pcmdataL=(double *)malloc(maxsamples*sizeof(double));
pcmdataR=(double *)malloc(maxsamples*sizeof(double));
/* Preset loading function */
initPresetLoader();
/* Load default preset directory */
// loadPresetDir("/home/cyril/.vlc/galaktos");
loadPresetDir("/etc/projectM/presets");
initPCM(maxsamples);
initBeatDetect();
// mutex = SDL_CreateMutex();
return 0;
}
void galaktos_done( galaktos_thread_t *p_thread )
{
free(pcmdataL);
free(pcmdataR);
freeBeatDetect();
freePCM();
free_per_pixel_matrices();
closePresetDir();
// destroyPresetLoader(); XXX segfaults :(
}
int galaktos_update( galaktos_thread_t *p_thread )
{
static int nohard=0;
double vdataL[512]; //holders for FFT data (spectrum)
double vdataR[512];
avgtime=fps*18;
totalframes++; //total amount of frames since startup
Time=(double)(mdate()/1000000);
frame++; //number of frames for current preset
progress= frame/(double)avgtime;
if (progress>1.0) progress=1.0;
// printf("start:%d at:%d min:%d stop:%d on:%d %d\n",startframe, frame frame-startframe,avgtime, noSwitch,progress);
if (frame>avgtime)
{
if (noSwitch==0) switchPreset(RANDOM_NEXT,0);
}
evalInitConditions();
evalPerFrameEquations();
evalCustomWaveInitConditions();
evalCustomShapeInitConditions();
// printf("%f %d\n",Time,frame);
reset_per_pixel_matrices();
numsamples = getPCMnew(pcmdataR,1,0,fWaveSmoothing,0,0);
getPCMnew(pcmdataL,0,0,fWaveSmoothing,0,1);
getPCM(vdataL,512,0,1,0,0);
getPCM(vdataR,512,1,1,0,0);
bass=0;mid=0;treb=0;
getBeatVals(vdataL,vdataR,&vol);
nohard--;
if(vol>8.0 && nohard<0 && noSwitch==0)
{
switchPreset(RANDOM_NEXT, HARD_CUT);
nohard=100;
}
//BEGIN PASS 1
//
//This pass is used to render our texture
//the texture is drawn to a subsection of the framebuffer
//and then we perform our manipulations on it
//in pass 2 we will copy the texture into texture memory
// galaktos_glx_activate_pbuffer( p_thread );
glPushAttrib( GL_ALL_ATTRIB_BITS ); /* Overkill, but safe */
// if (RenderTarget) glViewport( 0, 0, RenderTarget->w, RenderTarget->h );
if (0) {}
else glViewport( 0, 0, texsize, texsize );
glMatrixMode( GL_MODELVIEW );
glPushMatrix();
glLoadIdentity();
glMatrixMode( GL_PROJECTION );
glPushMatrix();
glLoadIdentity();
glOrtho(0.0, texsize, 0.0,texsize,10,40);
do_per_pixel_math();
do_per_frame(); //apply per-frame effects
render_interpolation(); //apply per-pixel effects
draw_motion_vectors(); //draw motion vectors
draw_borders(); //draw borders
draw_waveform();
draw_shapes();
draw_custom_waves();
glMatrixMode( GL_MODELVIEW );
glPopMatrix();
glMatrixMode( GL_PROJECTION );
glPopMatrix();
glPopAttrib();
//if ( RenderTarget ) SDL_GL_UnlockRenderTarget(RenderTarget);
/* Copy our rendering to the fake render target texture */
glBindTexture( GL_TEXTURE_2D, RenderTargetTextureID );
glCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, texsize, texsize);
// galaktos_glx_activate_window( p_thread );
//BEGIN PASS 2
//
//end of texture rendering
//now we copy the texture from the framebuffer to
//video texture memory and render fullscreen on a quad surface.
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-vw*.5, vw*.5, -vh*.5,vh*.5,10,40);
glLineWidth(texsize/512.0);
if(studio%2)render_texture_to_studio();
else render_texture_to_screen();
glFinish();
glFlush();
// printf("Flush %d\n",(SDL_GetTicks()-timestart));
p_thread->p_opengl->pf_swap( p_thread->p_opengl );
/* Process events */
if( p_thread->p_opengl->pf_manage &&
p_thread->p_opengl->pf_manage( p_thread->p_opengl ) )
{
return 1;
}
return 0;
}
void free_per_pixel_matrices()
{
int x;
for(x = 0; x < gx; x++)
{
free(gridx[x]);
free(gridy[x]);
free(origtheta[x]);
free(origrad[x]);
free(origx[x]);
free(origy[x]);
free(x_mesh[x]);
free(y_mesh[x]);
free(rad_mesh[x]);
free(theta_mesh[x]);
}
free(origx);
free(origy);
free(gridx);
free(gridy);
free(x_mesh);
free(y_mesh);
free(rad_mesh);
free(theta_mesh);
}
void init_per_pixel_matrices()
{
int x,y;
gridx=(double **)malloc(gx * sizeof(double *));
gridy=(double **)malloc(gx * sizeof(double *));
origx=(double **)malloc(gx * sizeof(double *));
origy=(double **)malloc(gx * sizeof(double *));
origrad=(double **)malloc(gx * sizeof(double *));
origtheta=(double **)malloc(gx * sizeof(double *));
x_mesh=(double **)malloc(gx * sizeof(double *));
y_mesh=(double **)malloc(gx * sizeof(double *));
rad_mesh=(double **)malloc(gx * sizeof(double *));
theta_mesh=(double **)malloc(gx * sizeof(double *));
sx_mesh=(double **)malloc(gx * sizeof(double *));
sy_mesh=(double **)malloc(gx * sizeof(double *));
dx_mesh=(double **)malloc(gx * sizeof(double *));
dy_mesh=(double **)malloc(gx * sizeof(double *));
cx_mesh=(double **)malloc(gx * sizeof(double *));
cy_mesh=(double **)malloc(gx * sizeof(double *));
zoom_mesh=(double **)malloc(gx * sizeof(double *));
zoomexp_mesh=(double **)malloc(gx * sizeof(double *));
rot_mesh=(double **)malloc(gx * sizeof(double *));
for(x = 0; x < gx; x++)
{
gridx[x] = (double *)malloc(gy * sizeof(double));
gridy[x] = (double *)malloc(gy * sizeof(double));
origtheta[x] = (double *)malloc(gy * sizeof(double));
origrad[x] = (double *)malloc(gy * sizeof(double));
origx[x] = (double *)malloc(gy * sizeof(double));
origy[x] = (double *)malloc(gy * sizeof(double));
x_mesh[x] = (double *)malloc(gy * sizeof(double));
y_mesh[x] = (double *)malloc(gy * sizeof(double));
rad_mesh[x] = (double *)malloc(gy * sizeof(double));
theta_mesh[x] = (double *)malloc(gy * sizeof(double));
sx_mesh[x] = (double *)malloc(gy * sizeof(double));
sy_mesh[x] = (double *)malloc(gy * sizeof(double));
dx_mesh[x] = (double *)malloc(gy * sizeof(double));
dy_mesh[x] = (double *)malloc(gy * sizeof(double));
cx_mesh[x] = (double *)malloc(gy * sizeof(double));
cy_mesh[x] = (double *)malloc(gy * sizeof(double));
zoom_mesh[x] = (double *)malloc(gy * sizeof(double));
zoomexp_mesh[x] = (double *)malloc(gy * sizeof(double));
rot_mesh[x] = (double *)malloc(gy * sizeof(double));
}
//initialize reference grid values
for (x=0;x<gx;x++)
{
for(y=0;y<gy;y++)
{
origx[x][y]=x/(double)(gx-1);
origy[x][y]=-((y/(double)(gy-1))-1);
origrad[x][y]=hypot((origx[x][y]-.5)*2,(origy[x][y]-.5)*2) * .7071067;
origtheta[x][y]=atan2(((origy[x][y]-.5)*2),((origx[x][y]-.5)*2));
gridx[x][y]=origx[x][y]*texsize;
gridy[x][y]=origy[x][y]*texsize;
}
}
}
//calculate matrices for per_pixel
void do_per_pixel_math()
{
int x,y;
double rotx=0,roty=0;
evalPerPixelEqns();
if(!isPerPixelEqn(CX_OP))
{
for (x=0;x<gx;x++)
{
for(y=0;y<gy;y++){
cx_mesh[x][y]=cx;
}
}
}
if(!isPerPixelEqn(CY_OP))
{
for (x=0;x<gx;x++)
{
for(y=0;y<gy;y++)
{
cy_mesh[x][y]=cy;
}
}
}
if(isPerPixelEqn(ROT_OP))
{
for (x=0;x<gx;x++)
{
for(y=0;y<gy;y++)
{
x_mesh[x][y]=x_mesh[x][y]-cx_mesh[x][y];
y_mesh[x][y]=y_mesh[x][y]-cy_mesh[x][y];
rotx=(x_mesh[x][y])*cos(rot_mesh[x][y])-(y_mesh[x][y])*sin(rot_mesh[x][y]);
roty=(x_mesh[x][y])*sin(rot_mesh[x][y])+(y_mesh[x][y])*cos(rot_mesh[x][y]);
x_mesh[x][y]=rotx+cx_mesh[x][y];
y_mesh[x][y]=roty+cy_mesh[x][y];
}
}
}
if(!isPerPixelEqn(ZOOM_OP))
{
for (x=0;x<gx;x++)
{
for(y=0;y<gy;y++)
{
zoom_mesh[x][y]=zoom;
}
}
}
if(!isPerPixelEqn(ZOOMEXP_OP))
{
for (x=0;x<gx;x++)
{
for(y=0;y<gy;y++)
{
zoomexp_mesh[x][y]=zoomexp;
}
}
}
//DO ZOOM PER PIXEL
for (x=0;x<gx;x++)
{
for(y=0;y<gy;y++)
{
x_mesh[x][y]=(x_mesh[x][y]-.5)*2;
y_mesh[x][y]=(y_mesh[x][y]-.5)*2;
x_mesh[x][y]=x_mesh[x][y]/(((zoom_mesh[x][y]-1)*(pow(rad_mesh[x][y],zoomexp_mesh[x][y])/rad_mesh[x][y]))+1);
y_mesh[x][y]=y_mesh[x][y]/(((zoom_mesh[x][y]-1)*(pow(rad_mesh[x][y],zoomexp_mesh[x][y])/rad_mesh[x][y]))+1);
x_mesh[x][y]=(x_mesh[x][y]*.5)+.5;
y_mesh[x][y]=(y_mesh[x][y]*.5)+.5;
}
}
if(isPerPixelEqn(SX_OP))
{
for (x=0;x<gx;x++)
{
for(y=0;y<gy;y++)
{
x_mesh[x][y]=((x_mesh[x][y]-cx_mesh[x][y])/sx_mesh[x][y])+cx_mesh[x][y];
}
}
}
if(isPerPixelEqn(SY_OP))
{
for (x=0;x<gx;x++)
{
for(y=0;y<gy;y++)
{
y_mesh[x][y]=((y_mesh[x][y]-cy_mesh[x][y])/sy_mesh[x][y])+cy_mesh[x][y];
}
}
}
if(isPerPixelEqn(DX_OP))
{
for (x=0;x<gx;x++)
{
for(y=0;y<gy;y++)
{
x_mesh[x][y]=x_mesh[x][y]-dx_mesh[x][y];
}
}
}
if(isPerPixelEqn(DY_OP))
{
for (x=0;x<gx;x++)
{
for(y=0;y<gy;y++)
{
y_mesh[x][y]=y_mesh[x][y]-dy_mesh[x][y];
}
}
}
}
void reset_per_pixel_matrices()
{
int x,y;
for (x=0;x<gx;x++)
{
for(y=0;y<gy;y++)
{
x_mesh[x][y]=origx[x][y];
y_mesh[x][y]=origy[x][y];
rad_mesh[x][y]=origrad[x][y];
theta_mesh[x][y]=origtheta[x][y];
}
}
}
void draw_custom_waves()
{
int x;
custom_wave_t *wavecode;
glPointSize(texsize/512);
//printf("%d\n",wavecode);
// more=isMoreCustomWave();
// printf("not inner loop\n");
while ((wavecode = nextCustomWave()) != NULL)
{
//printf("begin inner loop\n");
if(wavecode->enabled==1)
{
// nextCustomWave();
//glPushMatrix();
//if(wavecode->bUseDots==1) glEnable(GL_LINE_STIPPLE);
if (wavecode->bAdditive==0) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
else glBlendFunc(GL_SRC_ALPHA, GL_ONE);
if (wavecode->bDrawThick==1) glLineWidth(2*texsize/512);
// xx= ((pcmdataL[x]-pcmdataL[x-1])*80*fWaveScale)*2;
//yy=pcmdataL[x]*80*fWaveScale,-1;
//glVertex3f( (wave_x*texsize)+(xx+yy)*cos(45), (wave_y*texsize)+(-yy+xx)*cos(45),-1);
// printf("samples: %d\n", wavecode->samples);
getPCM(wavecode->value1,wavecode->samples,0,wavecode->bSpectrum,wavecode->smoothing,0);
getPCM(wavecode->value2,wavecode->samples,1,wavecode->bSpectrum,wavecode->smoothing,0);
// printf("%f\n",pcmL[0]);
for(x=0;x<wavecode->samples;x++)
{wavecode->value1[x]=wavecode->value1[x]*wavecode->scaling;}
for(x=0;x<wavecode->samples;x++)
{wavecode->value2[x]=wavecode->value2[x]*wavecode->scaling;}
for(x=0;x<wavecode->samples;x++)
{wavecode->sample_mesh[x]=((double)x)/((double)(wavecode->samples-1));}
// printf("mid inner loop\n");
evalPerPointEqns();
/*
if(!isPerPointEquation("x"))
{for(x=0;x<wavecode->samples;x++)
{cw_x[x]=0;} }
if(!isPerPointEquation(Y_POINT_OP))
{for(x=0;x<wavecode->samples;x++)
{cw_y[x]=0;}}
if(!isPerPointEquation(R_POINT_OP))
{for(x=0;x<wavecode->samples;x++)
{cw_r[x]=wavecode->r;}}
if(!isPerPointEquation(G_POINT_OP))
{for(x=0;x<wavecode->samples;x++)
{cw_g[x]=wavecode->g;}}
if(!isPerPointEquation(B_POINT_OP))
{for(x=0;x<wavecode->samples;x++)
{cw_b[x]=wavecode->b;}}
if(!isPerPointEquation(A_POINT_OP))
{for(x=0;x<wavecode->samples;x++)
{cw_a[x]=wavecode->a;}}
*/
//put drawing code here
if (wavecode->bUseDots==1) glBegin(GL_POINTS);
else glBegin(GL_LINE_STRIP);
for(x=0;x<wavecode->samples;x++)
{
// printf("x:%f y:%f a:%f g:%f %f\n", wavecode->x_mesh[x], wavecode->y_mesh[x], wavecode->a_mesh[x], wavecode->g_mesh[x], wavecode->sample_mesh[x]);
glColor4f(wavecode->r_mesh[x],wavecode->g_mesh[x],wavecode->b_mesh[x],wavecode->a_mesh[x]);
glVertex3f(wavecode->x_mesh[x]*texsize,-(wavecode->y_mesh[x]-1)*texsize,-1);
}
glEnd();
glPointSize(texsize/512);
glLineWidth(texsize/512);
glDisable(GL_LINE_STIPPLE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// glPopMatrix();
}
}
}
void draw_shapes()
{
int i;
double theta;
double rad2;
double pi = 3.14159265;
double start,inc,xval,yval;
custom_shape_t *shapecode;
while ((shapecode = nextCustomShape()) != NULL)
{
if(shapecode->enabled==1)
{
// printf("drawing shape %f\n",shapecode->ang);
shapecode->y=-((shapecode->y)-1);
rad2=.5;
shapecode->rad=shapecode->rad*(texsize*.707*.707*.707*1.04);
//Additive Drawing or Overwrite
if (shapecode->additive==0) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
else glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
if(correction)
{
glTranslatef(texsize*.5,texsize*.5, 0);
glScalef(1.0,vw/(double)vh,1.0);
glTranslatef((-texsize*.5) ,(-texsize*.5),0);
}
start=.78539+shapecode->ang;
inc=(pi*2)/(double)shapecode->sides;
xval=shapecode->x*texsize;
yval=shapecode->y*texsize;
if (shapecode->textured)
{
glMatrixMode(GL_TEXTURE);
glPushMatrix();
glLoadIdentity();
glTranslatef(.5,.5, 0);
if (correction) glScalef(1,vw/(double)vh,1);
glRotatef((shapecode->tex_ang*360/6.280), 0, 0, 1);
glScalef(1/(shapecode->tex_zoom),1/(shapecode->tex_zoom),1);
// glScalef(1,vh/(double)vw,1);
glTranslatef((-.5) ,(-.5),0);
// glScalef(1,vw/(double)vh,1);
glEnable(GL_TEXTURE_2D);
glBegin(GL_TRIANGLE_FAN);
glColor4f(shapecode->r,shapecode->g,shapecode->b,shapecode->a);
theta=start;
glTexCoord2f(.5,.5);
glVertex3f(xval,yval,-1);
glColor4f(shapecode->r2,shapecode->g2,shapecode->b2,shapecode->a2);
for ( i=0;i<shapecode->sides+1;i++)
{
theta+=inc;
// glColor4f(shapecode->r2,shapecode->g2,shapecode->b2,shapecode->a2);
glTexCoord2f(rad2*cos(theta)+.5 ,rad2*sin(theta)+.5 );
glVertex3f(shapecode->rad*cos(theta)+xval,shapecode->rad*sin(theta)+yval,-1);
}
glEnd();
glDisable(GL_TEXTURE_2D);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}
else
{//Untextured (use color values)
//printf("untextured %f %f %f @:%f,%f %f %f\n",shapecode->a2,shapecode->a,shapecode->border_a, shapecode->x,shapecode->y,shapecode->rad,shapecode->ang);
//draw first n-1 triangular pieces
glBegin(GL_TRIANGLE_FAN);
glColor4f(shapecode->r,shapecode->g,shapecode->b,shapecode->a);
theta=start;
// glTexCoord2f(.5,.5);
glVertex3f(xval,yval,-1);
glColor4f(shapecode->r2,shapecode->g2,shapecode->b2,shapecode->a2);
for ( i=0;i<shapecode->sides+1;i++)
{
theta+=inc;
// glColor4f(shapecode->r2,shapecode->g2,shapecode->b2,shapecode->a2);
// glTexCoord2f(rad2*cos(theta)+.5 ,rad2*sin(theta)+.5 );
glVertex3f(shapecode->rad*cos(theta)+xval,shapecode->rad*sin(theta)+yval,-1);
}
glEnd();
}
if (bWaveThick==1) glLineWidth(2*texsize/512);
glBegin(GL_LINE_LOOP);
glColor4f(shapecode->border_r,shapecode->border_g,shapecode->border_b,shapecode->border_a);
for ( i=0;i<shapecode->sides;i++)
{
theta+=inc;
glVertex3f(shapecode->rad*cos(theta)+xval,shapecode->rad*sin(theta)+yval,-1);
}
glEnd();
if (bWaveThick==1) glLineWidth(texsize/512);
glPopMatrix();
}
}
}
void draw_waveform()
{
int x;
double r,theta;
double offset,scale,dy2_adj;
double co;
double wave_x_temp=0;
double wave_y_temp=0;
modulate_opacity_by_volume();
maximize_colors();
if(bWaveDots==1) glEnable(GL_LINE_STIPPLE);
offset=(wave_x-.5)*texsize;
scale=texsize/505.0;
//Thick wave drawing
if (bWaveThick==1) glLineWidth(2*texsize/512);
//Additive wave drawing (vice overwrite)
if (bAdditiveWaves==0) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
else glBlendFunc(GL_SRC_ALPHA, GL_ONE);
switch(nWaveMode)
{
case 8://monitor
glPushMatrix();
glTranslatef(texsize*.5,texsize*.5, 0);
glRotated(-wave_mystery*90,0,0,1);
glTranslatef(-texsize*.5,-texsize*.825, 0);
/*
for (x=0;x<16;x++)
{
glBegin(GL_LINE_STRIP);
glColor4f(1.0-(x/15.0),.5,x/15.0,1.0);
glVertex3f((totalframes%256)*2*scale, -beat_val[x]*fWaveScale+texsize*wave_y,-1);
glColor4f(.5,.5,.5,1.0);
glVertex3f((totalframes%256)*2*scale, texsize*wave_y,-1);
glColor4f(1.0,1.0,0,1.0);
//glVertex3f((totalframes%256)*scale*2, beat_val_att[x]*fWaveScale+texsize*wave_y,-1);
glEnd();
glTranslatef(0,texsize*(1/36.0), 0);
}
*/
glTranslatef(0,texsize*(1/18.0), 0);
glBegin(GL_LINE_STRIP);
glColor4f(1.0,1.0,0.5,1.0);
glVertex3f((totalframes%256)*2*scale, treb_att*5*fWaveScale+texsize*wave_y,-1);
glColor4f(.2,.2,.2,1.0);
glVertex3f((totalframes%256)*2*scale, texsize*wave_y,-1);
glColor4f(1.0,1.0,0,1.0);
glVertex3f((totalframes%256)*scale*2, treb*-5*fWaveScale+texsize*wave_y,-1);
glEnd();
glTranslatef(0,texsize*.075, 0);
glBegin(GL_LINE_STRIP);
glColor4f(0,1.0,0.0,1.0);
glVertex3f((totalframes%256)*2*scale, mid_att*5*fWaveScale+texsize*wave_y,-1);
glColor4f(.2,.2,.2,1.0);
glVertex3f((totalframes%256)*2*scale, texsize*wave_y,-1);
glColor4f(.5,1.0,.5,1.0);
glVertex3f((totalframes%256)*scale*2, mid*-5*fWaveScale+texsize*wave_y,-1);
glEnd();
glTranslatef(0,texsize*.075, 0);
glBegin(GL_LINE_STRIP);
glColor4f(1.0,0,0,1.0);
glVertex3f((totalframes%256)*2*scale, bass_att*5*fWaveScale+texsize*wave_y,-1);
glColor4f(.2,.2,.2,1.0);
glVertex3f((totalframes%256)*2*scale, texsize*wave_y,-1);
glColor4f(1.0,.5,.5,1.0);
glVertex3f((totalframes%256)*scale*2, bass*-5*fWaveScale+texsize*wave_y,-1);
glEnd();
glPopMatrix();
break;
case 0://circular waveforms
// double co;
glPushMatrix();
glTranslatef(texsize*.5,texsize*.5, 0);
glScalef(1.0,vw/(double)vh,1.0);
glTranslatef((-texsize*.5) ,(-texsize*.5),0);
wave_y=-1*(wave_y-1.0);
glBegin(GL_LINE_STRIP);
for ( x=0;x<numsamples;x++)
{
co= -(abs(x-((numsamples*.5)-1))/numsamples)+1;
// printf("%d %f\n",x,co);
theta=x*(6.28/numsamples);
r= ((1+2*wave_mystery)*(texsize/5.0)+
( co*pcmdataL[x]+ (1-co)*pcmdataL[-(x-(numsamples-1))])
*25*fWaveScale);
glVertex3f(r*cos(theta)+(wave_x*texsize),r*sin(theta)+(wave_y*texsize),-1);
}
r= ( (1+2*wave_mystery)*(texsize/5.0)+
(0.5*pcmdataL[0]+ 0.5*pcmdataL[numsamples-1])
*20*fWaveScale);
glVertex3f(r*cos(0)+(wave_x*texsize),r*sin(0)+(wave_y*texsize),-1);
glEnd();
/*
glBegin(GL_LINE_LOOP);
for ( x=0;x<(512/pcmbreak);x++)
{
theta=(blockstart+x)*((6.28*pcmbreak)/512.0);
r= ((1+2*wave_mystery)*(texsize/5.0)+fdata_buffer[fbuffer][0][blockstart+x]*.0025*fWaveScale);
glVertex3f(r*cos(theta)+(wave_x*texsize),r*sin(theta)+(wave_y*texsize),-1);
}
glEnd();
*/
glPopMatrix();
break;
case 1://circularly moving waveform
// double co;
glPushMatrix();
glTranslatef(texsize*.5,texsize*.5, 0);
glScalef(1.0,vw/(double)vh,1.0);
glTranslatef((-texsize*.5) ,(-texsize*.5),0);
wave_y=-1*(wave_y-1.0);
glBegin(GL_LINE_STRIP);
//theta=(frame%512)*(6.28/512.0);
for ( x=1;x<512;x++)
{
co= -(abs(x-255)/512.0)+1;
// printf("%d %f\n",x,co);
theta=((frame%256)*(2*6.28/512.0))+pcmdataL[x]*.2*fWaveScale;
r= ((1+2*wave_mystery)*(texsize/5.0)+
(pcmdataL[x]-pcmdataL[x-1])*80*fWaveScale);
glVertex3f(r*cos(theta)+(wave_x*texsize),r*sin(theta)+(wave_y*texsize),-1);
}
glEnd();
glPopMatrix();
break;
case 2://EXPERIMENTAL
wave_y=-1*(wave_y-1.0);
glPushMatrix();
glBegin(GL_LINE_STRIP);
double xx,yy;
// double xr= (wave_x*texsize), yr=(wave_y*texsize);
xx=0;
for ( x=1;x<512;x++)
{
//xx = ((pcmdataL[x]-pcmdataL[x-1])*80*fWaveScale)*2;
xx += (pcmdataL[x]*fWaveScale);
yy= pcmdataL[x]*80*fWaveScale;
// glVertex3f( (wave_x*texsize)+(xx+yy)*2, (wave_y*texsize)+(xx-yy)*2,-1);
glVertex3f( (wave_x*texsize)+(xx)*2, (wave_y*texsize)+(yy)*2,-1);
// xr+=fdata_buffer[fbuffer][0][x] *.0005* fWaveScale;
//yr=(fdata_buffer[fbuffer][0][x]-fdata_buffer[fbuffer][0][x-1])*.05*fWaveScale+(wave_y*texsize);
//glVertex3f(xr,yr,-1);
}
glEnd();
glPopMatrix();
break;
case 3://EXPERIMENTAL
glPushMatrix();
wave_y=-1*(wave_y-1.0);
glBegin(GL_LINE_STRIP);
for ( x=1;x<512;x++)
{
xx= ((pcmdataL[x]-pcmdataL[x-1])*80*fWaveScale)*2;
yy=pcmdataL[x]*80*fWaveScale,-1;
glVertex3f( (wave_x*texsize)+(xx+yy)*cos(45), (wave_y*texsize)+(-yy+xx)*cos(45),-1);
}
glEnd();
glPopMatrix();
break;
case 4://single x-axis derivative waveform
glPushMatrix();
wave_y=-1*(wave_y-1.0);
glTranslatef(texsize*.5,texsize*.5, 0);
glRotated(-wave_mystery*90,0,0,1);
glTranslatef(-texsize*.5,-texsize*.5, 0);
wave_x=(wave_x*.75)+.125; wave_x=-(wave_x-1);
glBegin(GL_LINE_STRIP);
double dy_adj;
for ( x=1;x<512;x++)
{
dy_adj= pcmdataL[x]*20*fWaveScale-pcmdataL[x-1]*20*fWaveScale;
glVertex3f((x*scale)+dy_adj, pcmdataL[x]*20*fWaveScale+texsize*wave_x,-1);
}
glEnd();
glPopMatrix();
break;
case 5://EXPERIMENTAL
glPushMatrix();
wave_y=-1*(wave_y-1.0);
wave_x_temp=(wave_x*.75)+.125;
wave_x_temp=-(wave_x_temp-1);
glBegin(GL_LINE_STRIP);
for ( x=1;x<(512);x++)
{
dy2_adj= (pcmdataL[x]-pcmdataL[x-1])*20*fWaveScale;
glVertex3f((wave_x_temp*texsize)+dy2_adj*2, pcmdataL[x]*20*fWaveScale+texsize*wave_y,-1);
}
glEnd();
glPopMatrix();
break;
case 6://single waveform
glTranslatef(0,0, -1);
//glMatrixMode(GL_MODELVIEW);
glPushMatrix();
// glLoadIdentity();
glTranslatef(texsize*.5,texsize*.5, 0);
glRotated(-wave_mystery*90,0,0,1);
wave_x_temp=-2*0.4142*(abs(abs(wave_mystery)-.5)-.5);
glScalef(1.0+wave_x_temp,1.0,1.0);
glTranslatef(-texsize*.5,-texsize*.5, 0);
wave_x_temp=-1*(wave_x-1.0);
glBegin(GL_LINE_STRIP);
// wave_x_temp=(wave_x*.75)+.125;
// wave_x_temp=-(wave_x_temp-1);
for ( x=0;x<numsamples;x++)
{
//glVertex3f(x*scale, fdata_buffer[fbuffer][0][blockstart+x]*.0012*fWaveScale+texsize*wave_x_temp,-1);
glVertex3f(x*texsize/(double)numsamples, pcmdataR[x]*20*fWaveScale+texsize*wave_x_temp,-1);
//glVertex3f(x*scale, texsize*wave_y_temp,-1);
}
// printf("%f %f\n",texsize*wave_y_temp,wave_y_temp);
glEnd();
glPopMatrix();
break;
case 7://dual waveforms
glPushMatrix();
glTranslatef(texsize*.5,texsize*.5, 0);
glRotated(-wave_mystery*90,0,0,1);
wave_x_temp=-2*0.4142*(abs(abs(wave_mystery)-.5)-.5);
glScalef(1.0+wave_x_temp,1.0,1.0);
glTranslatef(-texsize*.5,-texsize*.5, 0);
wave_y_temp=-1*(wave_x-1);
glBegin(GL_LINE_STRIP);
for ( x=0;x<numsamples;x++)
{
glVertex3f((x*texsize)/(double)numsamples, pcmdataL[x]*20*fWaveScale+texsize*(wave_y_temp+(wave_y*wave_y*.5)),-1);
}
glEnd();
glBegin(GL_LINE_STRIP);
for ( x=0;x<numsamples;x++)
{
glVertex3f((x*texsize)/(double)numsamples, pcmdataR[x]*20*fWaveScale+texsize*(wave_y_temp-(wave_y*wave_y*.5)),-1);
}
glEnd();
glPopMatrix();
break;
default:
glBegin(GL_LINE_LOOP);
for ( x=0;x<512;x++)
{
theta=(x)*(6.28/512.0);
r= (texsize/5.0+pcmdataL[x]*.002);
glVertex3f(r*cos(theta)+(wave_x*texsize),r*sin(theta)+(wave_y*texsize),-1);
}
glEnd();
glBegin(GL_LINE_STRIP);
for ( x=0;x<512;x++)
{
glVertex3f(x*scale, pcmdataL[x]*20*fWaveScale+(texsize*(wave_x+.1)),-1);
}
glEnd();
glBegin(GL_LINE_STRIP);
for ( x=0;x<512;x++)
{
glVertex3f(x*scale, pcmdataR[x]*20*fWaveScale+(texsize*(wave_x-.1)),-1);
}
glEnd();
break;
if (bWaveThick==1) glLineWidth(2*texsize/512);
}
glLineWidth(texsize/512);
glDisable(GL_LINE_STIPPLE);
}
void maximize_colors()
{
float wave_r_switch=0,wave_g_switch=0,wave_b_switch=0;
//wave color brightening
//
//forces max color value to 1.0 and scales
// the rest accordingly
if (bMaximizeWaveColor==1)
{
if(wave_r>=wave_g && wave_r>=wave_b) //red brightest
{
wave_b_switch=wave_b*(1/wave_r);
wave_g_switch=wave_g*(1/wave_r);
wave_r_switch=1.0;
}
else if (wave_b>=wave_g && wave_b>=wave_r) //blue brightest
{
wave_r_switch=wave_r*(1/wave_b);
wave_g_switch=wave_g*(1/wave_b);
wave_b_switch=1.0;
}
else if (wave_g>=wave_b && wave_g>=wave_r) //green brightest
{
wave_b_switch=wave_b*(1/wave_g);
wave_r_switch=wave_r*(1/wave_g);
wave_g_switch=1.0;
}
glColor4f(wave_r_switch, wave_g_switch, wave_b_switch, wave_o);
}
else
{
glColor4f(wave_r, wave_g, wave_b, wave_o);
}
}
void modulate_opacity_by_volume()
{
//modulate volume by opacity
//
//set an upper and lower bound and linearly
//calculate the opacity from 0=lower to 1=upper
//based on current volume
if (bModWaveAlphaByVolume==1)
{if (vol<=fModWaveAlphaStart) wave_o=0.0;
else if (vol>=fModWaveAlphaEnd) wave_o=fWaveAlpha;
else wave_o=fWaveAlpha*((vol-fModWaveAlphaStart)/(fModWaveAlphaEnd-fModWaveAlphaStart));}
else wave_o=fWaveAlpha;
}
void draw_motion_vectors()
{
int x,y;
double offsetx=mv_dx*texsize, intervalx=texsize/(double)mv_x;
double offsety=mv_dy*texsize, intervaly=texsize/(double)mv_y;
glPointSize(mv_l);
glColor4f(mv_r, mv_g, mv_b, mv_a);
glBegin(GL_POINTS);
for (x=0;x<mv_x;x++){
for(y=0;y<mv_y;y++){
glVertex3f(offsetx+x*intervalx,offsety+y*intervaly,-1);
}}
glEnd();
}
void draw_borders()
{
//no additive drawing for borders
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glTranslatef(0,0,-1);
//Draw Borders
double of=texsize*ob_size*.5;
double iff=(texsize*ib_size*.5);
double texof=texsize-of;
glColor4d(ob_r,ob_g,ob_b,ob_a);
glRectd(0,0,of,texsize);
glRectd(of,0,texof,of);
glRectd(texof,0,texsize,texsize);
glRectd(of,texsize,texof,texof);
glColor4d(ib_r,ib_g,ib_b,ib_a);
glRectd(of,of,of+iff,texof);
glRectd(of+iff,of,texof-iff,of+iff);
glRectd(texof-iff,of,texof,texof);
glRectd(of+iff,texof,texof-iff,texof-iff);
}
//Here we render the interpolated mesh, and then apply the texture to it.
//Well, we actually do the inverse, but its all the same.
void render_interpolation()
{
int x,y;
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslated(0, 0, -9);
glColor4f(0.0, 0.0, 0.0,decay);
glEnable(GL_TEXTURE_2D);
for (x=0;x<gx-1;x++)
{
glBegin(GL_TRIANGLE_STRIP);
for(y=0;y<gy;y++)
{
glTexCoord4f(x_mesh[x][y], y_mesh[x][y],-1,1); glVertex4f(gridx[x][y], gridy[x][y],-1,1);
glTexCoord4f(x_mesh[x+1][y], y_mesh[x+1][y],-1,1); glVertex4f(gridx[x+1][y], gridy[x+1][y],-1,1);
}
glEnd();
}
glDisable(GL_TEXTURE_2D);
}
void do_per_frame()
{
//Texture wrapping( clamp vs. wrap)
if (bTexWrap==0)
{
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
}
else
{
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
}
// glRasterPos2i(0,0);
// glClear(GL_COLOR_BUFFER_BIT);
// glColor4d(0.0, 0.0, 0.0,1.0);
// glMatrixMode(GL_TEXTURE);
// glLoadIdentity();
glRasterPos2i(0,0);
glClear(GL_COLOR_BUFFER_BIT);
glColor4d(0.0, 0.0, 0.0,1.0);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glTranslatef(cx,cy, 0);
if(correction) glScalef(1,vw/(double)vh,1);
if(!isPerPixelEqn(ROT_OP))
{
// printf("ROTATING: rot = %f\n", rot);
glRotatef(rot*90, 0, 0, 1);
}
if(!isPerPixelEqn(SX_OP)) glScalef(1/sx,1,1);
if(!isPerPixelEqn(SY_OP)) glScalef(1,1/sy,1);
if(correction) glScalef(1,vh/(double)vw,1);
glTranslatef((-cx) ,(-cy),0);
if(!isPerPixelEqn(DX_OP)) glTranslatef(-dx,0,0);
if(!isPerPixelEqn(DY_OP)) glTranslatef(0 ,-dy,0);
}
//Actually draws the texture to the screen
//
//The Video Echo effect is also applied here
void render_texture_to_screen()
{
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0, 0, -9);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
// glClear(GL_ACCUM_BUFFER_BIT);
glColor4d(0.0, 0.0, 0.0,1.0f);
glBegin(GL_QUADS);
glVertex4d(-vw*.5,-vh*.5,-1,1);
glVertex4d(-vw*.5, vh*.5,-1,1);
glVertex4d(vw*.5, vh*.5,-1,1);
glVertex4d(vw*.5, -vh*.5,-1,1);
glEnd();
// glBindTexture( GL_TEXTURE_2D, tex2 );
glEnable(GL_TEXTURE_2D);
// glAccum(GL_LOAD,0);
// if (bDarken==1) glBlendFunc(GL_SRC_COLOR,GL_ZERO);
//Draw giant rectangle and texture it with our texture!
glBegin(GL_QUADS);
glTexCoord4d(0, 1,0,1); glVertex4d(-vw*.5,-vh*.5,-1,1);
glTexCoord4d(0, 0,0,1); glVertex4d(-vw*.5, vh*.5,-1,1);
glTexCoord4d(1, 0,0,1); glVertex4d(vw*.5, vh*.5,-1,1);
glTexCoord4d(1, 1,0,1); glVertex4d(vw*.5, -vh*.5,-1,1);
glEnd();
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
// if (bDarken==1) glBlendFunc(GL_SRC_COLOR,GL_ONE_MINUS_SRC_ALPHA);
// if (bDarken==1) { glAccum(GL_ACCUM,1-fVideoEchoAlpha); glBlendFunc(GL_SRC_COLOR,GL_ZERO); }
glMatrixMode(GL_TEXTURE);
//draw video echo
glColor4f(0.0, 0.0, 0.0,fVideoEchoAlpha);
glTranslated(.5,.5,0);
glScaled(1/fVideoEchoZoom,1/fVideoEchoZoom,1);
glTranslated(-.5,-.5,0);
int flipx=1,flipy=1;
switch (((int)nVideoEchoOrientation))
{
case 0: flipx=1;flipy=1;break;
case 1: flipx=-1;flipy=1;break;
case 2: flipx=1;flipy=-1;break;
case 3: flipx=-1;flipy=-1;break;
default: flipx=1;flipy=1; break;
}
glBegin(GL_QUADS);
glTexCoord4d(0, 1,0,1); glVertex4f(-vw*.5*flipx,-vh*.5*flipy,-1,1);
glTexCoord4d(0, 0,0,1); glVertex4f(-vw*.5*flipx, vh*.5*flipy,-1,1);
glTexCoord4d(1, 0,0,1); glVertex4f(vw*.5*flipx, vh*.5*flipy,-1,1);
glTexCoord4d(1, 1,0,1); glVertex4f(vw*.5*flipx, -vh*.5*flipy,-1,1);
glEnd();
glDisable(GL_TEXTURE_2D);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
// if (bDarken==1) { glAccum(GL_ACCUM,fVideoEchoAlpha); glAccum(GL_RETURN,1);}
if (bInvert==1)
{
glColor4f(1.0, 1.0, 1.0,1.0);
glBlendFunc(GL_ONE_MINUS_DST_COLOR,GL_ZERO);
glBegin(GL_QUADS);
glVertex4f(-vw*.5*flipx,-vh*.5*flipy,-1,1);
glVertex4f(-vw*.5*flipx, vh*.5*flipy,-1,1);
glVertex4f(vw*.5*flipx, vh*.5*flipy,-1,1);
glVertex4f(vw*.5*flipx, -vh*.5*flipy,-1,1);
glEnd();
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
}
}
void render_texture_to_studio()
{
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0, 0, -9);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
// glClear(GL_ACCUM_BUFFER_BIT);
glColor4f(0.0, 0.0, 0.0,0.04);
glVertex4d(-vw*.5,-vh*.5,-1,1);
glVertex4d(-vw*.5, vh*.5,-1,1);
glVertex4d(vw*.5, vh*.5,-1,1);
glVertex4d(vw*.5, -vh*.5,-1,1);
glEnd();
glColor4f(0.0, 0.0, 0.0,1.0);
glBegin(GL_QUADS);
glVertex4d(-vw*.5,0,-1,1);
glVertex4d(-vw*.5, vh*.5,-1,1);
glVertex4d(vw*.5, vh*.5,-1,1);
glVertex4d(vw*.5, 0,-1,1);
glEnd();
glBegin(GL_QUADS);
glVertex4d(0,-vh*.5,-1,1);
glVertex4d(0, vh*.5,-1,1);
glVertex4d(vw*.5, vh*.5,-1,1);
glVertex4d(vw*.5, -vh*.5,-1,1);
glEnd();
glPushMatrix();
glTranslatef(.25*vw, .25*vh, 0);
glScalef(.5,.5,1);
// glBindTexture( GL_TEXTURE_2D, tex2 );
glEnable(GL_TEXTURE_2D);
// glAccum(GL_LOAD,0);
// if (bDarken==1) glBlendFunc(GL_SRC_COLOR,GL_ZERO);
//Draw giant rectangle and texture it with our texture!
glBegin(GL_QUADS);
glTexCoord4d(0, 1,0,1); glVertex4d(-vw*.5,-vh*.5,-1,1);
glTexCoord4d(0, 0,0,1); glVertex4d(-vw*.5, vh*.5,-1,1);
glTexCoord4d(1, 0,0,1); glVertex4d(vw*.5, vh*.5,-1,1);
glTexCoord4d(1, 1,0,1); glVertex4d(vw*.5, -vh*.5,-1,1);
glEnd();
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
// if (bDarken==1) glBlendFunc(GL_SRC_COLOR,GL_ONE_MINUS_SRC_ALPHA);
// if (bDarken==1) { glAccum(GL_ACCUM,1-fVideoEchoAlpha); glBlendFunc(GL_SRC_COLOR,GL_ZERO); }
glMatrixMode(GL_TEXTURE);
//draw video echo
glColor4f(0.0, 0.0, 0.0,fVideoEchoAlpha);
glTranslated(.5,.5,0);
glScaled(1/fVideoEchoZoom,1/fVideoEchoZoom,1);
glTranslated(-.5,-.5,0);
int flipx=1,flipy=1;
switch (((int)nVideoEchoOrientation))
{
case 0: flipx=1;flipy=1;break;
case 1: flipx=-1;flipy=1;break;
case 2: flipx=1;flipy=-1;break;
case 3: flipx=-1;flipy=-1;break;
default: flipx=1;flipy=1; break;
}
glBegin(GL_QUADS);
glTexCoord4d(0, 1,0,1); glVertex4f(-vw*.5*flipx,-vh*.5*flipy,-1,1);
glTexCoord4d(0, 0,0,1); glVertex4f(-vw*.5*flipx, vh*.5*flipy,-1,1);
glTexCoord4d(1, 0,0,1); glVertex4f(vw*.5*flipx, vh*.5*flipy,-1,1);
glTexCoord4d(1, 1,0,1); glVertex4f(vw*.5*flipx, -vh*.5*flipy,-1,1);
glEnd();
glDisable(GL_TEXTURE_2D);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
// if (bDarken==1) { glAccum(GL_ACCUM,fVideoEchoAlpha); glAccum(GL_RETURN,1);}
if (bInvert==1)
{
glColor4f(1.0, 1.0, 1.0,1.0);
glBlendFunc(GL_ONE_MINUS_DST_COLOR,GL_ZERO);
glBegin(GL_QUADS);
glVertex4f(-vw*.5*flipx,-vh*.5*flipy,-1,1);
glVertex4f(-vw*.5*flipx, vh*.5*flipy,-1,1);
glVertex4f(vw*.5*flipx, vh*.5*flipy,-1,1);
glVertex4f(vw*.5*flipx, -vh*.5*flipy,-1,1);
glEnd();
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
}
// glTranslated(.5,.5,0);
// glScaled(1/fVideoEchoZoom,1/fVideoEchoZoom,1);
// glTranslated(-.5,-.5,0);
//glTranslatef(0,.5*vh,0);
//per_pixel monitor
//glBlendFunc(GL_ONE_MINUS_DST_COLOR,GL_ZERO);
int x,y;
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glPushMatrix();
glTranslatef(.25*vw, -.25*vh, 0);
glScalef(.5,.5,1);
glColor4f(1,1,1,.6);
for (x=0;x<gx;x++)
{
glBegin(GL_LINE_STRIP);
for(y=0;y<gy;y++)
{
glVertex4f((x_mesh[x][y]-.5)* vw, (y_mesh[x][y]-.5)*vh,-1,1);
//glVertex4f((origx[x+1][y]-.5) * vw, (origy[x+1][y]-.5) *vh ,-1,1);
}
glEnd();
}
for (y=0;y<gy;y++)
{
glBegin(GL_LINE_STRIP);
for(x=0;x<gx;x++)
{
glVertex4f((x_mesh[x][y]-.5)* vw, (y_mesh[x][y]-.5)*vh,-1,1);
//glVertex4f((origx[x+1][y]-.5) * vw, (origy[x+1][y]-.5) *vh ,-1,1);
}
glEnd();
}
/*
for (x=0;x<gx-1;x++){
glBegin(GL_POINTS);
for(y=0;y<gy;y++){
glVertex4f((origx[x][y]-.5)* vw, (origy[x][y]-.5)*vh,-1,1);
glVertex4f((origx[x+1][y]-.5) * vw, (origy[x+1][y]-.5) *vh ,-1,1);
}
glEnd();
}
*/
// glTranslated(-.5,-.5,0); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glPushMatrix();
glTranslatef(-.5*vw,0, 0);
glTranslatef(0,-vh*.10, 0);
glBegin(GL_LINE_STRIP);
glColor4f(0,1.0,1.0,1.0);
glVertex3f((((totalframes%256)/551.0))*vw, treb_att*-7,-1);
glColor4f(1.0,1.0,1.0,1.0);
glVertex3f((((totalframes%256)/551.0))*vw,0 ,-1);
glColor4f(.5,1.0,1.0,1.0);
glVertex3f((((totalframes%256)/551.0))*vw, treb*7,-1);
glEnd();
glTranslatef(0,-vh*.13, 0);
glBegin(GL_LINE_STRIP);
glColor4f(0,1.0,0.0,1.0);
glVertex3f((((totalframes%256)/551.0))*vw, mid_att*-7,-1);
glColor4f(1.0,1.0,1.0,1.0);
glVertex3f((((totalframes%256)/551.0))*vw,0 ,-1);
glColor4f(.5,1.0,0.0,0.5);
glVertex3f((((totalframes%256)/551.0))*vw, mid*7,-1);
glEnd();
glTranslatef(0,-vh*.13, 0);
glBegin(GL_LINE_STRIP);
glColor4f(1.0,0.0,0.0,1.0);
glVertex3f((((totalframes%256)/551.0))*vw, bass_att*-7,-1);
glColor4f(1.0,1.0,1.0,1.0);
glVertex3f((((totalframes%256)/551.0))*vw,0 ,-1);
glColor4f(.7,0.2,0.2,1.0);
glVertex3f((((totalframes%256)/551.0))*vw, bass*7,-1);
glEnd();
glTranslatef(0,-vh*.13, 0);
glBegin(GL_LINES);
glColor4f(1.0,1.0,1.0,1.0);
glVertex3f((((totalframes%256)/551.0))*vw,0 ,-1);
glColor4f(1.0,0.6,1.0,1.0);
glVertex3f((((totalframes%256)/551.0))*vw, vol*7,-1);
glEnd();
glPopMatrix();
}
/*****************************************************************************
* main.h:
*****************************************************************************
* Copyright (C) 2004 the VideoLAN team
* $Id$
*
* Authors: Cyril Deguet <asmax@videolan.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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifndef _GALAKTOS_MAIN_H_
#define _GALAKTOS_MAIN_H_
int galaktos_init( galaktos_thread_t *p_thread );
void galaktos_done( galaktos_thread_t *p_thread );
int galaktos_update( galaktos_thread_t *p_thread );
#endif
/*****************************************************************************
* param.c:
*****************************************************************************
* Copyright (C) 2004 the VideoLAN team
* $Id$
*
* Authors: Cyril Deguet <asmax@videolan.org>
* code from projectM http://xmms-projectm.sourceforge.net
*
* 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/* Basic Parameter Functions */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "fatal.h"
#include "common.h"
#include "splaytree_types.h"
#include "splaytree.h"
#include "tree_types.h"
#include "param_types.h"
#include "param.h"
#include "expr_types.h"
#include "eval.h"
#include "engine_vars.h"
void reset_param(param_t * param);
int is_valid_param_string(char * string); /* true if string is valid variable or function name */
/* A splay tree of builtin parameters */
splaytree_t * builtin_param_tree = NULL;
int insert_param_alt_name(param_t * param, const char * alt_name);
int insert_builtin_param(param_t * param);
/* Private function prototypes */
int compare_param(char * name, char * name2);
int load_builtin_param_double(const char * name, void * engine_val, void * matrix, short int flags,
double init_val, double upper_bound, double lower_bound, const char * alt_name);
int load_builtin_param_int(const char * name, void * engine_val, short int flags,
int init_val, int upper_bound, int lower_bound, const char * alt_name);
int load_builtin_param_bool(const char * name, void * engine_val, short int flags,
int init_val, const char * alt_name);
param_t * create_param (const char * name, short int type, short int flags, void * engine_val, void * matrix,
value_t default_init_val, value_t upper_bound, value_t lower_bound) {
param_t * param = NULL;
param = (param_t*)malloc(sizeof(param_t));
if (param == NULL) {
printf("create_param: out of memory!!!\n");
return NULL;
}
/* Clear name space, think the strncpy statement makes this redundant */
//memset(param->name, 0, MAX_TOKEN_SIZE);
/* Copy given name into parameter structure */
strncpy(param->name, name, MAX_TOKEN_SIZE-1);
/* Assign other entries in a constructor like fashion */
param->type = type;
param->flags = flags;
param->matrix_flag = 0;
param->matrix = matrix;
param->engine_val = engine_val;
param->default_init_val = default_init_val;
//*param->init_val = default_init_val;
param->upper_bound = upper_bound;
param->lower_bound = lower_bound;
/* Return instantiated parameter */
return param;
}
/* Creates a user defined parameter */
param_t * create_user_param(char * name) {
param_t * param;
value_t iv;
value_t ub;
value_t lb;
double * engine_val;
/* Set initial values to default */
iv.double_val = DEFAULT_DOUBLE_IV;
ub.double_val = DEFAULT_DOUBLE_UB;
lb.double_val = DEFAULT_DOUBLE_LB;
/* Argument checks */
if (name == NULL)
return NULL;
/* Allocate space for the engine variable */
if ((engine_val = (double*)malloc(sizeof(double))) == NULL)
return NULL;
(*engine_val) = iv.double_val; /* set some default init value */
/* Create the new user parameter */
if ((param = create_param(name, P_TYPE_DOUBLE, P_FLAG_USERDEF, engine_val, NULL, iv, ub, lb)) == NULL) {
free(engine_val);
return NULL;
}
if (PARAM_DEBUG) printf("create_param: \"%s\" initialized\n", param->name);
/* Return the instantiated parameter */
return param;
}
/* Initialize the builtin parameter database.
Should only be necessary once */
int init_builtin_param_db() {
/* Create the builtin parameter splay tree (go Sleator...) */
if ((builtin_param_tree = create_splaytree(compare_string, copy_string, free_string)) == NULL) {
if (PARAM_DEBUG) printf("init_builtin_param_db: failed to initialize database (FATAL)\n");
return OUTOFMEM_ERROR;
}
if (PARAM_DEBUG) {
printf("init_builtin_param: loading database...");
fflush(stdout);
}
/* Loads all builtin parameters into the database */
if (load_all_builtin_param() < 0) {
if (PARAM_DEBUG) printf("failed loading builtin parameters (FATAL)\n");
return ERROR;
}
if (PARAM_DEBUG) printf("success!\n");
/* Finished, no errors */
return SUCCESS;
}
/* Destroy the builtin parameter database.
Generally, do this on projectm exit */
int destroy_builtin_param_db() {
splay_traverse(free_param, builtin_param_tree);
destroy_splaytree(builtin_param_tree);
builtin_param_tree = NULL;
return SUCCESS;
}
/* Insert a parameter into the database with an alternate name */
int insert_param_alt_name(param_t * param, const char * alt_name) {
if (param == NULL)
return ERROR;
if (alt_name == NULL)
return ERROR;
splay_insert_link(alt_name, param->name, builtin_param_tree);
return SUCCESS;
}
param_t * find_builtin_param(char * name) {
/* Null argument checks */
if (name == NULL)
return NULL;
return splay_find(name, builtin_param_tree);
}
/* Find a parameter given its name, will create one if not found */
param_t * find_param(char * name, preset_t * preset, int flags) {
param_t * param = NULL;
/* Null argument checks */
if (name == NULL)
return NULL;
if (preset == NULL)
return NULL;
/* First look in the builtin database */
param = (param_t *)splay_find(name, builtin_param_tree);
/* If the search failed, check the user database */
if (param == NULL) {
param = (param_t*)splay_find(name, preset->user_param_tree);
}
/* If it doesn't exist in the user (or builtin) database and
create_flag is set, then make it and insert into the database
*/
if ((param == NULL) && (flags & P_CREATE)) {
/* Check if string is valid */
if (!is_valid_param_string(name)) {
if (PARAM_DEBUG) printf("find_param: invalid parameter name:\"%s\"\n", name);
return NULL;
}
/* Now, create the user defined parameter given the passed name */
if ((param = create_user_param(name)) == NULL) {
if (PARAM_DEBUG) printf("find_param: failed to create a new user parameter!\n");
return NULL;
}
/* Finally, insert the new parameter into this preset's proper splaytree */
if (splay_insert(param, param->name, preset->user_param_tree) < 0) {
if (PARAM_DEBUG) printf("PARAM \"%s\" already exists in user parameter tree!\n", param->name);
free_param(param);
return NULL;
}
}
/* Return the found (or created) parameter. Note that if P_CREATE is not set, this could be null */
return param;
}
/* Compare string name with parameter name */
int compare_param(char * name, char * name2) {
int cmpval;
printf("am i used\n");
/* Uses string comparison function */
cmpval = strncmp(name, name2, MAX_TOKEN_SIZE-1);
return cmpval;
}
/* Loads all builtin parameters, limits are also defined here */
int load_all_builtin_param() {
load_builtin_param_double("fRating", (void*)&fRating, NULL, P_FLAG_NONE, 0.0 , 5.0, 0.0, NULL);
load_builtin_param_double("fWaveScale", (void*)&fWaveScale, NULL, P_FLAG_NONE, 0.0, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, NULL);
load_builtin_param_double("gamma", (void*)&fGammaAdj, NULL, P_FLAG_NONE, 0.0, MAX_DOUBLE_SIZE, 0, "fGammaAdj");
load_builtin_param_double("echo_zoom", (void*)&fVideoEchoZoom, NULL, P_FLAG_NONE, 0.0, MAX_DOUBLE_SIZE, 0, "fVideoEchoZoom");
load_builtin_param_double("echo_alpha", (void*)&fVideoEchoAlpha, NULL, P_FLAG_NONE, 0.0, MAX_DOUBLE_SIZE, 0, "fVideoEchoAlpha");
load_builtin_param_double("wave_a", (void*)&fWaveAlpha, NULL, P_FLAG_NONE, 0.0, 1.0, 0, "fWaveAlpha");
load_builtin_param_double("fWaveSmoothing", (void*)&fWaveSmoothing, NULL, P_FLAG_NONE, 0.0, 1.0, -1.0, NULL);
load_builtin_param_double("fModWaveAlphaStart", (void*)&fModWaveAlphaStart, NULL, P_FLAG_NONE, 0.0, 1.0, -1.0, NULL);
load_builtin_param_double("fModWaveAlphaEnd", (void*)&fModWaveAlphaEnd, NULL, P_FLAG_NONE, 0.0, 1.0, -1.0, NULL);
load_builtin_param_double("fWarpAnimSpeed", (void*)&fWarpAnimSpeed, NULL, P_FLAG_NONE, 0.0, 1.0, -1.0, NULL);
// load_builtin_param_double("warp", (void*)&warp, warp_mesh, P_FLAG_NONE, 0.0, MAX_DOUBLE_SIZE, 0, NULL);
load_builtin_param_double("fShader", (void*)&fShader, NULL, P_FLAG_NONE, 0.0, 1.0, -1.0, NULL);
load_builtin_param_double("decay", (void*)&decay, NULL, P_FLAG_NONE, 0.0, 1.0, 0, "fDecay");
load_builtin_param_int("echo_orient", (void*)&nVideoEchoOrientation, P_FLAG_NONE, 0, 3, 0, "nVideoEchoOrientation");
load_builtin_param_int("wave_mode", (void*)&nWaveMode, P_FLAG_NONE, 0, 7, 0, "nWaveMode");
load_builtin_param_bool("wave_additive", (void*)&bAdditiveWaves, P_FLAG_NONE, FALSE, "bAdditiveWaves");
load_builtin_param_bool("bModWaveAlphaByVolume", (void*)&bModWaveAlphaByVolume, P_FLAG_NONE, FALSE, NULL);
load_builtin_param_bool("wave_brighten", (void*)&bMaximizeWaveColor, P_FLAG_NONE, FALSE, "bMaximizeWaveColor");
load_builtin_param_bool("wrap", (void*)&bTexWrap, P_FLAG_NONE, FALSE, "bTexWrap");
load_builtin_param_bool("darken_center", (void*)&bDarkenCenter, P_FLAG_NONE, FALSE, "bDarkenCenter");
load_builtin_param_bool("bRedBlueStereo", (void*)&bRedBlueStereo, P_FLAG_NONE, FALSE, NULL);
load_builtin_param_bool("brighten", (void*)&bBrighten, P_FLAG_NONE, FALSE, "bBrighten");
load_builtin_param_bool("darken", (void*)&bDarken, P_FLAG_NONE, FALSE, "bDarken");
load_builtin_param_bool("solarize", (void*)&bSolarize, P_FLAG_NONE, FALSE, "bSolarize");
load_builtin_param_bool("invert", (void*)&bInvert, P_FLAG_NONE, FALSE, "bInvert");
load_builtin_param_bool("bMotionVectorsOn", (void*)&bMotionVectorsOn, P_FLAG_NONE, FALSE, NULL);
load_builtin_param_bool("wave_dots", (void*)&bWaveDots, P_FLAG_NONE, FALSE, "bWaveDots");
load_builtin_param_bool("wave_thick", (void*)&bWaveThick, P_FLAG_NONE, FALSE, "bWaveThick");
load_builtin_param_double("zoom", (void*)&zoom, zoom_mesh, P_FLAG_PER_PIXEL |P_FLAG_DONT_FREE_MATRIX, 0.0, MAX_DOUBLE_SIZE, 0, NULL);
load_builtin_param_double("rot", (void*)&rot, rot_mesh, P_FLAG_PER_PIXEL |P_FLAG_DONT_FREE_MATRIX, 0.0, MAX_DOUBLE_SIZE, MIN_DOUBLE_SIZE, NULL);
load_builtin_param_double("zoomexp", (void*)&zoomexp, zoomexp_mesh, P_FLAG_PER_PIXEL |P_FLAG_NONE, 0.0, MAX_DOUBLE_SIZE, 0, "fZoomExponent");
load_builtin_param_double("cx", (void*)&cx, cx_mesh, P_FLAG_PER_PIXEL | P_FLAG_DONT_FREE_MATRIX, 0.0, 1.0, 0, NULL);
load_builtin_param_double("cy", (void*)&cy, cy_mesh, P_FLAG_PER_PIXEL | P_FLAG_DONT_FREE_MATRIX, 0.0, 1.0, 0, NULL);
load_builtin_param_double("dx", (void*)&dx, dx_mesh, P_FLAG_PER_PIXEL | P_FLAG_DONT_FREE_MATRIX, 0.0, MAX_DOUBLE_SIZE, MIN_DOUBLE_SIZE, NULL);
load_builtin_param_double("dy", (void*)&dy, dy_mesh, P_FLAG_PER_PIXEL |P_FLAG_DONT_FREE_MATRIX, 0.0, MAX_DOUBLE_SIZE, MIN_DOUBLE_SIZE, NULL);
load_builtin_param_double("sx", (void*)&sx, sx_mesh, P_FLAG_PER_PIXEL |P_FLAG_DONT_FREE_MATRIX, 0.0, MAX_DOUBLE_SIZE, 0, NULL);
load_builtin_param_double("sy", (void*)&sy, sy_mesh, P_FLAG_PER_PIXEL |P_FLAG_DONT_FREE_MATRIX, 0.0, MAX_DOUBLE_SIZE, 0, NULL);
load_builtin_param_double("wave_r", (void*)&wave_r, NULL, P_FLAG_NONE, 0.0, 1.0, 0.0, NULL);
load_builtin_param_double("wave_g", (void*)&wave_g, NULL, P_FLAG_NONE, 0.0, 1.0, 0.0, NULL);
load_builtin_param_double("wave_b", (void*)&wave_b, NULL, P_FLAG_NONE, 0.0, 1.0, 0.0, NULL);
load_builtin_param_double("wave_x", (void*)&wave_x, NULL, P_FLAG_NONE, 0.0, 1.0, 0.0, NULL);
load_builtin_param_double("wave_y", (void*)&wave_y, NULL, P_FLAG_NONE, 0.0, 1.0, 0.0, NULL);
load_builtin_param_double("wave_mystery", (void*)&wave_mystery, NULL, P_FLAG_NONE, 0.0, 1.0, -1.0, "fWaveParam");
load_builtin_param_double("ob_size", (void*)&ob_size, NULL, P_FLAG_NONE, 0.0, 0.5, 0, NULL);
load_builtin_param_double("ob_r", (void*)&ob_r, NULL, P_FLAG_NONE, 0.0, 1.0, 0.0, NULL);
load_builtin_param_double("ob_g", (void*)&ob_g, NULL, P_FLAG_NONE, 0.0, 1.0, 0.0, NULL);
load_builtin_param_double("ob_b", (void*)&ob_b, NULL, P_FLAG_NONE, 0.0, 1.0, 0.0, NULL);
load_builtin_param_double("ob_a", (void*)&ob_a, NULL, P_FLAG_NONE, 0.0, 1.0, 0.0, NULL);
load_builtin_param_double("ib_size", (void*)&ib_size, NULL,P_FLAG_NONE, 0.0, .5, 0.0, NULL);
load_builtin_param_double("ib_r", (void*)&ib_r, NULL,P_FLAG_NONE, 0.0, 1.0, 0.0, NULL);
load_builtin_param_double("ib_g", (void*)&ib_g, NULL,P_FLAG_NONE, 0.0, 1.0, 0.0, NULL);
load_builtin_param_double("ib_b", (void*)&ib_b, NULL,P_FLAG_NONE, 0.0, 1.0, 0.0, NULL);
load_builtin_param_double("ib_a", (void*)&ib_a, NULL,P_FLAG_NONE, 0.0, 1.0, 0.0, NULL);
load_builtin_param_double("mv_r", (void*)&mv_r, NULL,P_FLAG_NONE, 0.0, 1.0, 0.0, NULL);
load_builtin_param_double("mv_g", (void*)&mv_g, NULL,P_FLAG_NONE, 0.0, 1.0, 0.0, NULL);
load_builtin_param_double("mv_b", (void*)&mv_b, NULL,P_FLAG_NONE, 0.0, 1.0, 0.0, NULL);
load_builtin_param_double("mv_x", (void*)&mv_x, NULL,P_FLAG_NONE, 0.0, 64.0, 0.0, "nMotionVectorsX");
load_builtin_param_double("mv_y", (void*)&mv_y, NULL,P_FLAG_NONE, 0.0, 48.0, 0.0, "nMotionVectorsY");
load_builtin_param_double("mv_l", (void*)&mv_l, NULL,P_FLAG_NONE, 0.0, 5.0, 0.0, NULL);
load_builtin_param_double("mv_dy", (void*)&mv_dy, NULL, P_FLAG_NONE, 0.0, 1.0, -1.0, NULL);
load_builtin_param_double("mv_dx", (void*)&mv_dx, NULL,P_FLAG_NONE, 0.0, 1.0, -1.0, NULL);
load_builtin_param_double("mv_a", (void*)&mv_a, NULL,P_FLAG_NONE, 0.0, 1.0, 0.0, NULL);
load_builtin_param_double("time", (void*)&Time, NULL,P_FLAG_READONLY, 0.0, MAX_DOUBLE_SIZE, 0.0, NULL);
load_builtin_param_double("bass", (void*)&bass, NULL,P_FLAG_READONLY, 0.0, MAX_DOUBLE_SIZE, 0.0, NULL);
load_builtin_param_double("mid", (void*)&mid, NULL,P_FLAG_READONLY, 0.0, MAX_DOUBLE_SIZE, 0, NULL);
load_builtin_param_double("bass_att", (void*)&bass_att, NULL,P_FLAG_READONLY, 0.0, MAX_DOUBLE_SIZE, 0, NULL);
load_builtin_param_double("mid_att", (void*)&mid_att, NULL,P_FLAG_READONLY, 0.0, MAX_DOUBLE_SIZE, 0, NULL);
load_builtin_param_double("treb_att", (void*)&treb_att, NULL,P_FLAG_READONLY, 0.0, MAX_DOUBLE_SIZE, 0, NULL);
load_builtin_param_int("frame", (void*)&frame, P_FLAG_READONLY, 0, MAX_INT_SIZE, 0, NULL);
load_builtin_param_double("progress", (void*)&progress, NULL,P_FLAG_READONLY, 0.0, 1, 0, NULL);
load_builtin_param_int("fps", (void*)&fps, P_FLAG_NONE, 15, MAX_INT_SIZE, 0, NULL);
load_builtin_param_double("x", (void*)&x_per_pixel, x_mesh, P_FLAG_PER_PIXEL |P_FLAG_ALWAYS_MATRIX | P_FLAG_READONLY | P_FLAG_DONT_FREE_MATRIX,
0, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, NULL);
load_builtin_param_double("y", (void*)&y_per_pixel, y_mesh, P_FLAG_PER_PIXEL |P_FLAG_ALWAYS_MATRIX |P_FLAG_READONLY | P_FLAG_DONT_FREE_MATRIX,
0, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, NULL);
load_builtin_param_double("ang", (void*)&ang_per_pixel, theta_mesh, P_FLAG_PER_PIXEL |P_FLAG_ALWAYS_MATRIX | P_FLAG_READONLY | P_FLAG_DONT_FREE_MATRIX,
0, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, NULL);
load_builtin_param_double("rad", (void*)&rad_per_pixel, rad_mesh, P_FLAG_PER_PIXEL |P_FLAG_ALWAYS_MATRIX | P_FLAG_READONLY | P_FLAG_DONT_FREE_MATRIX,
0, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, NULL);
load_builtin_param_double("q1", (void*)&q1, NULL, P_FLAG_PER_PIXEL |P_FLAG_QVAR, 0, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, NULL);
load_builtin_param_double("q2", (void*)&q2, NULL, P_FLAG_PER_PIXEL |P_FLAG_QVAR, 0, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, NULL);
load_builtin_param_double("q3", (void*)&q3, NULL, P_FLAG_PER_PIXEL |P_FLAG_QVAR, 0, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, NULL);
load_builtin_param_double("q4", (void*)&q4, NULL, P_FLAG_PER_PIXEL |P_FLAG_QVAR, 0, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, NULL);
load_builtin_param_double("q5", (void*)&q5, NULL, P_FLAG_PER_PIXEL |P_FLAG_QVAR, 0, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, NULL);
load_builtin_param_double("q6", (void*)&q6, NULL, P_FLAG_PER_PIXEL |P_FLAG_QVAR, 0, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, NULL);
load_builtin_param_double("q7", (void*)&q7, NULL, P_FLAG_PER_PIXEL |P_FLAG_QVAR, 0, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, NULL);
load_builtin_param_double("q8", (void*)&q8, NULL, P_FLAG_PER_PIXEL |P_FLAG_QVAR, 0, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, NULL);
/* variables added in 1.04 */
load_builtin_param_int("meshx", (void*)&gx, P_FLAG_READONLY, 32, 96, 8, NULL);
load_builtin_param_int("meshy", (void*)&gy, P_FLAG_READONLY, 24, 72, 6, NULL);
return SUCCESS;
}
/* Free's a parameter type */
void free_param(param_t * param) {
int x;
if (param == NULL)
return;
if (param->flags & P_FLAG_USERDEF) {
free(param->engine_val);
}
if (!(param->flags & P_FLAG_DONT_FREE_MATRIX)) {
if (param->flags & P_FLAG_PER_POINT)
free(param->matrix);
else if (param->flags & P_FLAG_PER_PIXEL) {
for(x = 0; x < gx; x++)
free(((double**)param->matrix)[x]);
free(param->matrix);
}
}
if (PARAM_DEBUG) printf("free_param: freeing \"%s\".\n", param->name);
free(param);
}
/* Loads a double parameter into the builtin database */
int load_builtin_param_double(const char * name, void * engine_val, void * matrix, short int flags,
double init_val, double upper_bound, double lower_bound, const char * alt_name) {
param_t * param = NULL;
value_t iv, ub, lb;
iv.double_val = init_val;
ub.double_val = upper_bound;
lb.double_val = lower_bound;
/* Create new parameter of type double */
if (PARAM_DEBUG == 2) {
printf("load_builtin_param_double: (name \"%s\") (alt_name = \"%s\") ", name, alt_name);
fflush(stdout);
}
if ((param = create_param(name, P_TYPE_DOUBLE, flags, engine_val, matrix, iv, ub, lb)) == NULL) {
return OUTOFMEM_ERROR;
}
if (PARAM_DEBUG == 2) {
printf("created...");
fflush(stdout);
}
/* Insert the paremeter into the database */
if (insert_builtin_param(param) < 0) {
free_param(param);
return ERROR;
}
if (PARAM_DEBUG == 2) {
printf("inserted...");
fflush(stdout);
}
/* If this parameter has an alternate name, insert it into the database as link */
if (alt_name != NULL) {
insert_param_alt_name(param, alt_name);
if (PARAM_DEBUG == 2) {
printf("alt_name inserted...");
fflush(stdout);
}
}
if (PARAM_DEBUG == 2) printf("finished\n");
/* Finished, return success */
return SUCCESS;
}
/* Loads a double parameter into the builtin database */
param_t * new_param_double(const char * name, short int flags, void * engine_val, void * matrix,
double upper_bound, double lower_bound, double init_val) {
param_t * param;
value_t iv, ub, lb;
iv.double_val = init_val;
ub.double_val = upper_bound;
lb.double_val = lower_bound;
if ((param = create_param(name, P_TYPE_DOUBLE, flags, engine_val, matrix,iv, ub, lb)) == NULL)
return NULL;
/* Finished, return success */
return param;
}
/* Creates a new parameter of type int */
param_t * new_param_int(const char * name, short int flags, void * engine_val,
int upper_bound, int lower_bound, int init_val) {
param_t * param;
value_t iv, ub, lb;
iv.int_val = init_val;
ub.int_val = upper_bound;
lb.int_val = lower_bound;
if ((param = create_param(name, P_TYPE_INT, flags, engine_val, NULL, iv, ub, lb)) == NULL)
return NULL;
/* Finished, return success */
return param;
}
/* Creates a new parameter of type bool */
param_t * new_param_bool(const char * name, short int flags, void * engine_val,
int upper_bound, int lower_bound, int init_val) {
param_t * param;
value_t iv, ub, lb;
iv.bool_val = init_val;
ub.bool_val = upper_bound;
lb.bool_val = lower_bound;
if ((param = create_param(name, P_TYPE_BOOL, flags, engine_val, NULL, iv, ub, lb)) == NULL)
return NULL;
/* Finished, return success */
return param;
}
/* Loads a integer parameter into the builtin database */
int load_builtin_param_int(const char * name, void * engine_val, short int flags,
int init_val, int upper_bound, int lower_bound, const char * alt_name) {
param_t * param;
value_t iv, ub, lb;
iv.int_val = init_val;
ub.int_val = upper_bound;
lb.int_val = lower_bound;
param = create_param(name, P_TYPE_INT, flags, engine_val, NULL, iv, ub, lb);
if (param == NULL) {
return OUTOFMEM_ERROR;
}
if (insert_builtin_param(param) < 0) {
free_param(param);
return ERROR;
}
if (alt_name != NULL) {
insert_param_alt_name(param, alt_name);
}
return SUCCESS;
}
/* Loads a boolean parameter */
int load_builtin_param_bool(const char * name, void * engine_val, short int flags,
int init_val, const char * alt_name) {
param_t * param;
value_t iv, ub, lb;
iv.int_val = init_val;
ub.int_val = TRUE;
lb.int_val = FALSE;
param = create_param(name, P_TYPE_BOOL, flags, engine_val, NULL, iv, ub, lb);
if (param == NULL) {
return OUTOFMEM_ERROR;
}
if (insert_builtin_param(param) < 0) {
free_param(param);
return ERROR;
}
if (alt_name != NULL) {
insert_param_alt_name(param, alt_name);
}
return SUCCESS;
}
/* Returns nonzero if the string is valid parameter name */
int is_valid_param_string(char * string) {
if (string == NULL)
return FALSE;
/* This ensures the first character is non numeric */
if( ((*string) >= 48) && ((*string) <= 57))
return FALSE;
/* These probably should never happen */
if (*string == '.')
return FALSE;
if (*string == '+')
return FALSE;
if (*string == '-')
return FALSE;
/* Could also add checks for other symbols. May do later */
return TRUE;
}
/* Inserts a parameter into the builtin database */
int insert_builtin_param(param_t * param) {
if (param == NULL)
return FAILURE;
return splay_insert(param, param->name, builtin_param_tree);
}
/* Inserts a parameter into the builtin database */
int insert_param(param_t * param, splaytree_t * database) {
if (param == NULL)
return FAILURE;
if (database == NULL)
return FAILURE;
return splay_insert(param, param->name, database);
}
/* Sets the parameter engine value to value val.
clipping occurs if necessary */
void set_param(param_t * param, double val) {
switch (param->type) {
case P_TYPE_BOOL:
if (val < 0)
*((int*)param->engine_val) = 0;
else if (val > 0)
*((int*)param->engine_val) = 1;
else
*((int*)param->engine_val) = 0;
break;
case P_TYPE_INT:
/* Make sure value is an integer */
val = floor(val);
if (val < param->lower_bound.int_val)
*((int*)param->engine_val) = param->lower_bound.int_val;
else if (val > param->upper_bound.int_val)
*((int*)param->engine_val) = param->upper_bound.int_val;
else
*((int*)param->engine_val) = val;
break;
case P_TYPE_DOUBLE:
/* Make sure value is an integer */
if (val < param->lower_bound.double_val)
*((double*)param->engine_val) = param->lower_bound.double_val;
else if (val > param->upper_bound.double_val)
*((double*)param->engine_val) = param->upper_bound.double_val;
else
*((double*)param->engine_val) = val;
break;
default:
break;
}
return;
}
/* Search for parameter 'name' in 'database', if create_flag is true, then generate the parameter
and insert it into 'database' */
param_t * find_param_db(char * name, splaytree_t * database, int create_flag) {
param_t * param = NULL;
/* Null argument checks */
if (name == NULL)
return NULL;
if (database == NULL)
return NULL;
/* First look in the builtin database */
param = (param_t *)splay_find(name, database);
if (((param = (param_t *)splay_find(name, database)) == NULL) && (create_flag == TRUE)) {
/* Check if string is valid */
if (!is_valid_param_string(name))
return NULL;
/* Now, create the user defined parameter given the passed name */
if ((param = create_user_param(name)) == NULL)
return NULL;
/* Finally, insert the new parameter into this preset's proper splaytree */
if (splay_insert(param, param->name, database) < 0) {
free_param(param);
return NULL;
}
}
/* Return the found (or created) parameter. Note that this could be null */
return param;
}
#ifndef PARAM_H
#define PARAM_H
#include "preset_types.h"
#include "splaytree_types.h"
/* Debug level, zero for none */
#define PARAM_DEBUG 0
/* Used to store a number of decidable type */
/* Function prototypes */
param_t * create_param (const char * name, short int type, short int flags, void * eqn_val, void * matrix,
value_t default_init_val, value_t upper_bound, value_t lower_bound);
param_t * create_user_param(char * name);
int init_builtin_param_db();
int init_user_param_db();
int destroy_user_param_db();
int destroy_builtin_param_db();
void set_param(param_t * param, double val);
int remove_param(param_t * param);
param_t * find_param(char * name, struct PRESET_T * preset, int flags);
void free_param(param_t * param);
int load_all_builtin_param();
int insert_param(param_t * param, splaytree_t * database);
param_t * find_builtin_param(char * name);
param_t * new_param_double(const char * name, short int flags, void * engine_val, void * matrix,
double upper_bound, double lower_bound, double init_val);
param_t * new_param_int(const char * name, short int flags, void * engine_val,
int upper_bound, int lower_bound, int init_val);
param_t * new_param_bool(const char * name, short int flags, void * engine_val,
int upper_bound, int lower_bound, int init_val);
param_t * find_param_db(char * name, splaytree_t * database, int create_flag);
#endif
#ifndef PARAM_TYPES_H
#define PARAM_TYPES_H
#include "expr_types.h"
#define P_CREATE 1
#define P_NONE 0
#define P_TYPE_BOOL 0
#define P_TYPE_INT 1
#define P_TYPE_DOUBLE 2
#define P_FLAG_NONE 0
#define P_FLAG_READONLY 1
#define P_FLAG_USERDEF (1 << 1)
#define P_FLAG_QVAR (1 << 2)
#define P_FLAG_TVAR (1 << 3)
#define P_FLAG_ALWAYS_MATRIX (1 << 4)
#define P_FLAG_DONT_FREE_MATRIX (1 << 5)
#define P_FLAG_PER_PIXEL (1 << 6)
#define P_FLAG_PER_POINT (1 << 7)
typedef union VALUE_T {
int bool_val;
int int_val;
double double_val;
} value_t;
/* Parameter Type */
typedef struct PARAM_T {
char name[MAX_TOKEN_SIZE]; /* name of the parameter, not necessary but useful neverthless */
short int type; /* parameter number type (int, bool, or double) */
short int flags; /* read, write, user defined, etc */
short int matrix_flag; /* for optimization purposes */
void * engine_val; /* pointer to the engine variable */
void * matrix; /* per pixel / per point matrix for this variable */
value_t default_init_val; /* a default initial condition value */
value_t upper_bound; /* this parameter's upper bound */
value_t lower_bound; /* this parameter's lower bound */
} param_t;
#endif
/*****************************************************************************
* parser.c:
*****************************************************************************
* Copyright (C) 2004 the VideoLAN team
* $Id$
*
* Authors: Cyril Deguet <asmax@videolan.org>
* code from projectM http://xmms-projectm.sourceforge.net
*
* 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/* parser.c */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "common.h"
#include "fatal.h"
#include "splaytree_types.h"
#include "splaytree.h"
#include "tree_types.h"
#include "expr_types.h"
#include "eval.h"
#include "param_types.h"
#include "param.h"
#include "func_types.h"
#include "func.h"
#include "preset_types.h"
#include "builtin_funcs.h"
#include "per_pixel_eqn_types.h"
#include "per_pixel_eqn.h"
#include "init_cond_types.h"
#include "init_cond.h"
#include "per_frame_eqn_types.h"
#include "per_frame_eqn.h"
#include "parser.h"
#include "engine_vars.h"
#include "custom_wave_types.h"
#include "custom_wave.h"
#include "custom_shape_types.h"
#include "custom_shape.h"
/* Strings that prefix (and denote the type of) equations */
#define PER_FRAME_STRING "per_frame_"
#define PER_FRAME_STRING_LENGTH 10
#define PER_PIXEL_STRING "per_pixel_"
#define PER_PIXEL_STRING_LENGTH 10
#define PER_FRAME_INIT_STRING "per_frame_init_"
#define PER_FRAME_INIT_STRING_LENGTH 15
#define WAVECODE_STRING "wavecode_"
#define WAVECODE_STRING_LENGTH 9
#define WAVE_STRING "wave_"
#define WAVE_STRING_LENGTH 5
#define PER_POINT_STRING "per_point"
#define PER_POINT_STRING_LENGTH 9
#define PER_FRAME_STRING_NO_UNDERSCORE "per_frame"
#define PER_FRAME_STRING_NO_UNDERSCORE_LENGTH 9
#define SHAPECODE_STRING "shapecode_"
#define SHAPECODE_STRING_LENGTH 10
#define SHAPE_STRING "shape_"
#define SHAPE_STRING_LENGTH 6
#define SHAPE_INIT_STRING "init"
#define SHAPE_INIT_STRING_LENGTH 4
#define WAVE_INIT_STRING "init"
#define WAVE_INIT_STRING_LENGTH 4
/* Stores a line of a file as its being parsed */
char string_line_buffer[STRING_LINE_SIZE];
/* The current position of the string line buffer (see above) */
int string_line_buffer_index = 0;
/* All infix operators (except '=') are prototyped here */
extern infix_op_t * infix_add, * infix_minus, * infix_div, * infix_mult,
* infix_or, * infix_and, * infix_mod, * infix_positive, * infix_negative;
/* If the parser reads a line with a custom wave, this pointer is set to
the custom wave of concern */
custom_wave_t * current_wave = NULL;
custom_shape_t * current_shape = NULL;
/* Counts the number of lines parsed */
unsigned int line_count = 1;
int per_frame_eqn_count = 0;
int per_frame_init_eqn_count = 0;
typedef enum {
NORMAL_LINE_MODE,
PER_FRAME_LINE_MODE,
PER_PIXEL_LINE_MODE,
INIT_COND_LINE_MODE,
CUSTOM_WAVE_PER_POINT_LINE_MODE,
CUSTOM_WAVE_PER_FRAME_LINE_MODE,
CUSTOM_WAVE_WAVECODE_LINE_MODE,
CUSTOM_SHAPE_SHAPECODE_LINE_MODE,
} line_mode_t;
line_mode_t line_mode = NORMAL_LINE_MODE;
/* Token enumeration type */
typedef enum {
tEOL, /* end of a line, usually a '/n' or '/r' */
tEOF, /* end of file */
tLPr, /* ( */
tRPr, /* ) */
tLBr, /* [ */
tRBr, /* ] */
tEq, /* = */
tPlus, /* + */
tMinus, /* - */
tMult, /* * */
tMod, /* % */
tDiv, /* / */
tOr, /* | */
tAnd, /* & */
tComma, /* , */
tPositive, /* + as a prefix operator */
tNegative, /* - as a prefix operator */
tSemiColon, /* ; */
tStringTooLong, /* special token to indicate an invalid string length */
tStringBufferFilled /* the string buffer for this line is maxed out */
} token_t;
int get_string_prefix_len(char * string);
tree_expr_t * insert_gen_expr(gen_expr_t * gen_expr, tree_expr_t ** root);
tree_expr_t * insert_infix_op(infix_op_t * infix_op, tree_expr_t ** root);
token_t parseToken(FILE * fs, char * string);
gen_expr_t ** parse_prefix_args(FILE * fs, int num_args, struct PRESET_T * preset);
gen_expr_t * parse_infix_op(FILE * fs, token_t token, tree_expr_t * tree_expr, struct PRESET_T * preset);
gen_expr_t * parse_sign_arg(FILE * fs);
int parse_float(FILE * fs, double * float_ptr);
int parse_int(FILE * fs, int * int_ptr);
int insert_gen_rec(gen_expr_t * gen_expr, tree_expr_t * root);
int insert_infix_rec(infix_op_t * infix_op, tree_expr_t * root);
gen_expr_t * parse_gen_expr(FILE * fs, tree_expr_t * tree_expr, struct PRESET_T * preset);
per_frame_eqn_t * parse_implicit_per_frame_eqn(FILE * fs, char * param_string, int index, struct PRESET_T * preset);
init_cond_t * parse_per_frame_init_eqn(FILE * fs, struct PRESET_T * preset, splaytree_t * database);
int parse_wavecode_prefix(char * token, int * id, char ** var_string);
int parse_wavecode(char * token, FILE * fs, preset_t * preset);
int parse_wave_prefix(char * token, int * id, char ** eqn_string);
int parse_shapecode(char * eqn_string, FILE * fs, preset_t * preset);
int parse_shapecode_prefix(char * token, int * id, char ** var_string);
int parse_wave(char * eqn_string, FILE * fs, preset_t * preset);
int parse_shape(char * eqn_string, FILE * fs, preset_t * preset);
int parse_shape_prefix(char * token, int * id, char ** eqn_string);
int update_string_buffer(char * buffer, int * index);
int string_to_float(char * string, double * float_ptr);
/* Grabs the next token from the file. The second argument points
to the raw string */
token_t parseToken(FILE * fs, char * string) {
char c;
int i;
if (string != NULL)
memset(string, 0, MAX_TOKEN_SIZE);
/* Loop until a delimiter is found, or the maximum string size is found */
for (i = 0; i < MAX_TOKEN_SIZE;i++) {
c = fgetc(fs);
/* If the string line buffer is full, quit */
if (string_line_buffer_index == (STRING_LINE_SIZE - 1))
return tStringBufferFilled;
/* Otherwise add this character to the string line buffer */
string_line_buffer[string_line_buffer_index++] = c;
/* Now interpret the character */
switch (c) {
case '+':
return tPlus;
case '-':
return tMinus;
case '%':
return tMod;
case '/':
/* check for line comment here */
if ((c = fgetc(fs)) == '/') {
while(1) {
c = fgetc(fs);
if (c == EOF) {
line_mode = NORMAL_LINE_MODE;
return tEOF;
}
if (c == '\n') {
line_mode = NORMAL_LINE_MODE;
return tEOL;
}
}
}
/* Otherwise, just a regular division operator */
ungetc(c, fs);
return tDiv;
case '*':
return tMult;
case '|':
return tOr;
case '&':
return tAnd;
case '(':
return tLPr;
case ')':
return tRPr;
case '[':
return tLBr;
case ']':
return tRBr;
case '=':
return tEq;
// case '\r':
//break;
case '\n':
line_count++;
line_mode = NORMAL_LINE_MODE;
return tEOL;
case ',':
return tComma;
case ';':
return tSemiColon;
case ' ': /* space, skip the character */
i--;
break;
case EOF:
line_count = 1;
line_mode = NORMAL_LINE_MODE;
return tEOF;
default:
if (string != NULL)
string[i] = c;
}
}
/* String reached maximum length, return special token error */
return tStringTooLong;
}
/* Parse input in the form of "exp, exp, exp, ...)"
Returns a general expression list */
gen_expr_t ** parse_prefix_args(FILE * fs, int num_args, struct PRESET_T * preset) {
int i, j;
gen_expr_t ** expr_list; /* List of arguments to function */
gen_expr_t * gen_expr;
/* Malloc the expression list */
expr_list = (gen_expr_t**)malloc(sizeof(gen_expr_t*)*num_args);
/* Malloc failed */
if (expr_list == NULL)
return NULL;
i = 0;
while (i < num_args) {
//if (PARSE_DEBUG) printf("parse_prefix_args: parsing argument %d...\n", i+1);
/* Parse the ith expression in the list */
if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
//if (PARSE_DEBUG) printf("parse_prefix_args: failed to get parameter # %d for function (LINE %d)\n", i+1, line_count);
for (j = 0; j < i; j++)
free_gen_expr(expr_list[j]);
free(expr_list);
return NULL;
}
/* Assign entry in expression list */
expr_list[i++] = gen_expr;
}
//if (PARSE_DEBUG) printf("parse_prefix_args: finished parsing %d arguments (LINE %d)\n", num_args, line_count);
/* Finally, return the resulting expression list */
return expr_list;
}
/* Parses a comment at the top of the file. Stops when left bracket is found */
int parse_top_comment(FILE * fs) {
char string[MAX_TOKEN_SIZE];
token_t token;
/* Process tokens until left bracket is found */
while ((token = parseToken(fs, string)) != tLBr) {
if (token == tEOF)
return PARSE_ERROR;
}
/* Done, return success */
return SUCCESS;
}
/* Right Bracket is parsed by this function.
puts a new string into name */
int parse_preset_name(FILE * fs, char * name) {
token_t token;
if (name == NULL)
return FAILURE;
if ((token = parseToken(fs, name)) != tRBr)
return PARSE_ERROR;
//if (PARSE_DEBUG) printf("parse_preset_name: parsed preset (name = \"%s\")\n", name);
return SUCCESS;
}
/* Parses per pixel equations */
int parse_per_pixel_eqn(FILE * fs, preset_t * preset) {
char string[MAX_TOKEN_SIZE];
gen_expr_t * gen_expr;
if (PARSE_DEBUG) printf("parse_per_pixel: per_pixel equation parsing start...(LINE %d)\n", line_count);
if (parseToken(fs, string) != tEq) { /* parse per pixel operator name */
if (PARSE_DEBUG) printf("parse_per_pixel: equal operator expected after per pixel operator \"%s\", but not found (LINE %d)\n",
string, line_count);
return PARSE_ERROR;
}
/* Parse right side of equation as an expression */
if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
if (PARSE_DEBUG) printf("parse_per_pixel: equation evaluated to null? (LINE %d)\n", line_count);
return PARSE_ERROR;
}
/* Add the per pixel equation */
if (add_per_pixel_eqn(string, gen_expr, preset) < 0) {
free_gen_expr(gen_expr);
return PARSE_ERROR;
}
return SUCCESS;
}
/* Parses an equation line, this function is way too big, should add some helper functions */
int parse_line(FILE * fs, struct PRESET_T * preset) {
char eqn_string[MAX_TOKEN_SIZE];
token_t token;
init_cond_t * init_cond;
per_frame_eqn_t * per_frame_eqn;
/* Clear the string line buffer */
memset(string_line_buffer, 0, STRING_LINE_SIZE);
string_line_buffer_index = 0;
switch (token = parseToken(fs, eqn_string)) {
/* Invalid Cases */
case tRBr:
case tLPr:
case tRPr:
case tComma:
case tLBr:
case tPlus:
case tMinus:
case tMod:
case tMult:
case tOr:
case tAnd:
case tDiv:
// if (PARSE_DEBUG) printf("parse_line: invalid token found at start of line (LINE %d)\n", line_count);
/* Invalid token found, return a parse error */
return PARSE_ERROR;
case tEOL: /* Empty line */
line_mode = NORMAL_LINE_MODE;
return SUCCESS;
case tEOF: /* End of File */
line_mode = NORMAL_LINE_MODE;
line_count = 1;
return EOF;
case tSemiColon: /* Indicates end of expression */
return SUCCESS;
/* Valid Case, either an initial condition or equation should follow */
case tEq:
/* CASE: PER FRAME INIT EQUATION */
if (!strncmp(eqn_string, PER_FRAME_INIT_STRING, PER_FRAME_INIT_STRING_LENGTH)) {
//if (PARSE_DEBUG) printf("parse_line: per frame init equation found...(LINE %d)\n", line_count);
/* Set the line mode to normal */
line_mode = NORMAL_LINE_MODE;
/* Parse the per frame equation */
if ((init_cond = parse_per_frame_init_eqn(fs, preset, NULL)) == NULL) {
//if (PARSE_DEBUG) printf("parse_line: per frame init equation parsing failed (LINE %d)\n", line_count);
return PARSE_ERROR;
}
/* Insert the equation in the per frame equation tree */
if (splay_insert(init_cond, init_cond->param->name, preset->per_frame_init_eqn_tree) < 0) {
//if (PARSE_DEBUG) printf("parse_line: failed to add a perframe equation (ERROR)\n");
free_init_cond(init_cond); /* will free the gen expr too */
return ERROR;
}
if (update_string_buffer(preset->per_frame_init_eqn_string_buffer,
&preset->per_frame_init_eqn_string_index) < 0)
{ return FAILURE;}
return SUCCESS;
}
/* Per frame equation case */
if (!strncmp(eqn_string, PER_FRAME_STRING, PER_FRAME_STRING_LENGTH)) {
/* Sometimes per frame equations are implicitly defined without the
per_frame_ prefix. This informs the parser that one could follow */
line_mode = PER_FRAME_LINE_MODE;
//if (PARSE_DEBUG) printf("parse_line: per frame equation found...(LINE %d)\n", line_count);
/* Parse the per frame equation */
if ((per_frame_eqn = parse_per_frame_eqn(fs, ++per_frame_eqn_count, preset)) == NULL) {
if (PARSE_DEBUG) printf("parse_line: per frame equation parsing failed (LINE %d)\n", line_count);
return PARSE_ERROR;
}
/* Insert the equation in the per frame equation tree */
if (splay_insert(per_frame_eqn, &per_frame_eqn_count, preset->per_frame_eqn_tree) < 0) {
if (PARSE_DEBUG) printf("parse_line: failed to add a perframe equation (ERROR)\n");
free_per_frame_eqn(per_frame_eqn); /* will free the gen expr too */
return ERROR;
}
if (update_string_buffer(preset->per_frame_eqn_string_buffer,
&preset->per_frame_eqn_string_index) < 0)
return FAILURE;
return SUCCESS;
}
/* Wavecode initial condition case */
if (!strncmp(eqn_string, WAVECODE_STRING, WAVECODE_STRING_LENGTH)) {
line_mode = CUSTOM_WAVE_WAVECODE_LINE_MODE;
//if (PARSE_DEBUG)
// printf("parse_line: wavecode prefix found: \"%s\"\n", eqn_string);
// printf("string:%d\n", 5);
//SUPER MYSTERIO-BUG - Don't Remove
printf("");
return parse_wavecode(eqn_string, fs, preset);
}
/* Custom Wave Prefix */
if ((!strncmp(eqn_string, WAVE_STRING, WAVE_STRING_LENGTH)) &&
((eqn_string[5] >= 48) && (eqn_string[5] <= 57))) {
// if (PARSE_DEBUG) printf("parse_line wave prefix found: \"%s\"\n", eqn_string);
return parse_wave(eqn_string, fs, preset);
}
/* Shapecode initial condition case */
if (!strncmp(eqn_string, SHAPECODE_STRING, SHAPECODE_STRING_LENGTH)) {
line_mode = CUSTOM_SHAPE_SHAPECODE_LINE_MODE;
if (PARSE_DEBUG) printf("parse_line: shapecode prefix found: \"%s\"\n", eqn_string);
return parse_shapecode(eqn_string, fs, preset);
}
/* Custom Shape Prefix */
if ((!strncmp(eqn_string, SHAPE_STRING, SHAPE_STRING_LENGTH)) &&
((eqn_string[6] >= 48) && (eqn_string[6] <= 57))) {
if (PARSE_DEBUG) printf("parse_line shape prefix found: \"%s\"\n", eqn_string);
return parse_shape(eqn_string, fs, preset);
}
/* Per pixel equation case */
if (!strncmp(eqn_string, PER_PIXEL_STRING, PER_PIXEL_STRING_LENGTH)) {
line_mode = PER_PIXEL_LINE_MODE;
if (parse_per_pixel_eqn(fs, preset) < 0)
return PARSE_ERROR;
if (update_string_buffer(preset->per_pixel_eqn_string_buffer,
&preset->per_pixel_eqn_string_index) < 0)
return FAILURE;
if (PARSE_DEBUG) printf("parse_line: finished parsing per pixel equation (LINE %d)\n", line_count);
return SUCCESS;
}
/* Sometimes equations are written implicitly in milkdrop files, in the form
per_frame_1 = p1 = eqn1; p2 = eqn2; p3 = eqn3;..;
which is analagous to:
per_frame_1 = p1 = eqn1; per_frame_2 = p2 = eqn2; per_frame_3 = p3 = eqn3; ...;
The following line mode hack allows such implicit declaration of the
prefix that specifies the equation type. An alternative method
may be to associate each equation line as list of equations separated
by semicolons (and a new line ends the list). Instead, however, a global
variable called "line_mode" specifies the last type of equation found,
and bases any implicitly typed input on this fact
Note added by Carmelo Piccione (cep@andrew.cmu.edu) 10/19/03
*/
/* Per frame line mode previously, try to parse the equation implicitly */
if (line_mode == PER_FRAME_LINE_MODE) {
if ((per_frame_eqn = parse_implicit_per_frame_eqn(fs, eqn_string, ++per_frame_eqn_count, preset)) == NULL)
return PARSE_ERROR;
/* Insert the equation in the per frame equation tree */
if (splay_insert(per_frame_eqn, &per_frame_eqn_count, preset->per_frame_eqn_tree) < 0) {
if (PARSE_DEBUG) printf("parse_line: failed to add a perframe equation (ERROR)\n");
free_per_frame_eqn(per_frame_eqn); /* will free the gen expr too */
return ERROR;
}
if (update_string_buffer(preset->per_frame_eqn_string_buffer,
&preset->per_frame_eqn_string_index) < 0)
return FAILURE;
return SUCCESS;
}
//if (PARSE_DEBUG) printf("parse_line: found initial condition: name = \"%s\" (LINE %d)\n", eqn_string, line_count);
/* Evaluate the initial condition */
if ((init_cond = parse_init_cond(fs, eqn_string, preset)) == NULL) {
if (PARSE_DEBUG) printf("parse_line: failed to parse initial condition (LINE %d)\n", line_count);
return PARSE_ERROR;
}
/* Add equation to initial condition tree */
if (splay_insert(init_cond, init_cond->param->name, preset->init_cond_tree) < 0) {
if (PARSE_DEBUG) printf("parse_line: failed to add initial condition \"%s\" to equation tree (LINE %d)\n",
init_cond->param->name, line_count);
free_init_cond(init_cond);
return FAILURE;
}
/* Finished with initial condition line */
// if (PARSE_DEBUG) printf("parse_line: initial condition parsed successfully\n");
return SUCCESS;
/* END INITIAL CONDITIONING PARSING */
default: /* an uncaught type or an error has occurred */
if (PARSE_DEBUG) printf("parse_line: uncaught case, token val = %d\n", token);
return PARSE_ERROR;
}
/* Because of the default in the case statement,
control flow should never actually reach here */
return PARSE_ERROR;
}
/* Parses a general expression, this function is the meat of the parser */
gen_expr_t * parse_gen_expr (FILE * fs, tree_expr_t * tree_expr, struct PRESET_T * preset) {
int i;
char string[MAX_TOKEN_SIZE];
token_t token;
gen_expr_t * gen_expr;
double val;
param_t * param = NULL;
func_t * func;
gen_expr_t ** expr_list;
switch (token = parseToken(fs,string)) {
/* Left Parentice Case */
case tLPr:
/* CASE 1 (Left Parentice): See if the previous string before this parentice is a function name */
if ((func = find_func(string)) != NULL) {
if (PARSE_DEBUG) printf("parse_gen_expr: found prefix function (name = %s) (LINE %d)\n", func->name, line_count);
/* Parse the functions arguments */
if ((expr_list = parse_prefix_args(fs, func->num_args, preset)) == NULL) {
if (PARSE_DEBUG) printf("parse_prefix_args: failed to generate an expresion list! (LINE %d) \n", line_count);
free_tree_expr(tree_expr);
return NULL;
}
/* Convert function to expression */
if ((gen_expr = prefun_to_expr((void*)func->func_ptr, expr_list, func->num_args)) == NULL) {
if (PARSE_DEBUG) printf("parse_prefix_args: failed to convert prefix function to general expression (LINE %d) \n",
line_count);
free_tree_expr(tree_expr);
for (i = 0; i < func->num_args;i++)
free_gen_expr(expr_list[i]);
free(expr_list);
return NULL;
}
token = parseToken(fs, string);
if (*string != 0) {
if (PARSE_DEBUG) printf("parse_prefix_args: empty string expected, but not found...(LINE %d)\n", line_count);
/* continue anyway for now, could be implicit multiplication */
}
return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
}
/* Case 2: (Left Parentice), a string coupled with a left parentice. Either an error or implicit
multiplication operator. For now treat it as an error */
if (*string != 0) {
if (PARSE_DEBUG) printf("parse_gen_expr: implicit multiplication case unimplemented!\n");
free_tree_expr(tree_expr);
return NULL;
}
/* CASE 3 (Left Parentice): the following is enclosed parentices to change order
of operations. So we create a new expression tree */
if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
//if (PARSE_DEBUG) printf("parse_gen_expr: found left parentice, but failed to create new expression tree \n");
free_tree_expr(tree_expr);
return NULL;
}
if (PARSE_DEBUG) printf("parse_gen_expr: finished enclosed expression tree...\n");
token = parseToken(fs, string);
return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
/* Plus is a prefix operator check */
case tPlus:
if (*string == 0) {
//if (PARSE_DEBUG) printf("parse_gen_expr: plus used as prefix (LINE %d)\n", line_count);
/* Treat prefix plus as implict 0 preceding operator */
gen_expr = const_to_expr(0);
return parse_infix_op(fs, tPositive, insert_gen_expr(gen_expr, &tree_expr), preset);
}
/* Minus is a prefix operator check */
case tMinus:
if (*string == 0) {
/* Use the negative infix operator, but first add an implicit zero to the operator tree */
gen_expr = const_to_expr(0);
//return parse_gen_expr(fs, insert_gen_expr(gen_expr, &tree_expr), preset);
return parse_infix_op(fs, tNegative, insert_gen_expr(gen_expr, &tree_expr), preset);
}
/* All the following cases are strings followed by an infix operator or terminal */
case tRPr:
case tEOL:
case tEOF:
case tSemiColon:
case tComma:
/* CASE 1 (terminal): string is empty, but not null. Not sure if this will actually happen
any more. */
if (*string == 0) {
//if (PARSE_DEBUG) printf("parse_gen_expr: empty string coupled with terminal (LINE %d) \n", line_count);
return parse_infix_op(fs, token, tree_expr, preset);
}
default:
/* CASE 0: Empty string, parse error */
if (*string == 0) {
if (PARSE_DEBUG) printf("parse_gen_expr: empty string coupled with infix op (ERROR!) (LINE %d) \n", line_count);
free_tree_expr(tree_expr);
return NULL;
}
/* CASE 1: Check if string is a just a floating point number */
if (string_to_float(string, &val) != PARSE_ERROR) {
if ((gen_expr = const_to_expr(val)) == NULL) {
free_tree_expr(tree_expr);
return NULL;
}
/* Parse the rest of the line */
return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
}
/* CASE 4: custom shape variable */
if (current_shape != NULL) {
if ((param = find_param_db(string, current_shape->param_tree, FALSE)) == NULL) {
if ((param = find_builtin_param(string)) == NULL)
if ((param = find_param_db(string, current_shape->param_tree, TRUE)) == NULL) {
free_tree_expr(tree_expr);
return NULL;
}
}
if (PARSE_DEBUG) {
printf("parse_gen_expr: custom shape parameter (name = %s)... ", param->name);
fflush(stdout);
}
/* Convert parameter to an expression */
if ((gen_expr = param_to_expr(param)) == NULL) {
free_tree_expr(tree_expr);
return NULL;
}
//if (PARSE_DEBUG) printf("converted to expression (LINE %d)\n", line_count);
/* Parse the rest of the line */
return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
}
/* CASE 5: custom wave variable */
if (current_wave != NULL) {
if ((param = find_param_db(string, current_wave->param_tree, FALSE)) == NULL) {
if ((param = find_builtin_param(string)) == NULL)
if ((param = find_param_db(string, current_wave->param_tree, TRUE)) == NULL) {
free_tree_expr(tree_expr);
return NULL;
}
}
if (PARSE_DEBUG) {
printf("parse_gen_expr: custom wave parameter (name = %s)... ", param->name);
fflush(stdout);
}
/* Convert parameter to an expression */
if ((gen_expr = param_to_expr(param)) == NULL) {
free_tree_expr(tree_expr);
return NULL;
}
if (PARSE_DEBUG) printf("converted to expression (LINE %d)\n", line_count);
/* Parse the rest of the line */
return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
}
/* CASE 6: regular parameter. Will be created if necessary and the string has no invalid characters */
if ((param = find_param(string, preset, P_CREATE)) != NULL) {
if (PARSE_DEBUG) {
printf("parse_gen_expr: parameter (name = %s)... ", param->name);
fflush(stdout);
}
/* Convert parameter to an expression */
if ((gen_expr = param_to_expr(param)) == NULL) {
free_tree_expr(tree_expr);
return NULL;
}
if (PARSE_DEBUG) printf("converted to expression (LINE %d)\n", line_count);
/* Parse the rest of the line */
return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
}
/* CASE 7: Bad string, give up */
if (PARSE_DEBUG) printf("parse_gen_expr: syntax error [string = \"%s\"] (LINE %d)\n", string, line_count);
free_tree_expr(tree_expr);
return NULL;
}
}
/* Inserts expressions into tree according to operator precedence.
If root is null, a new tree is created, with gen_expr as only element */
tree_expr_t * insert_infix_op(infix_op_t * infix_op, tree_expr_t **root) {
tree_expr_t * new_root;
/* Sanity check */
if (infix_op == NULL)
return NULL;
/* The root is null, so make this operator
the new root */
if (*root == NULL) {
new_root = new_tree_expr(infix_op, NULL, NULL, NULL);
*root = new_root;
return new_root;
}
/* The root node is not an infix function,
so we make this infix operator the new root */
if ((*root)->infix_op == NULL) {
new_root = new_tree_expr(infix_op, NULL, *root, NULL);
(*root) = new_root;
return new_root;
}
/* The root is an infix function. If the precedence
of the item to be inserted is greater than the root's
precedence, then make gen_expr the root */
if (infix_op->precedence > (*root)->infix_op->precedence) {
new_root = new_tree_expr(infix_op, NULL, *root, NULL);
(*root) = new_root;
return new_root;
}
/* If control flow reaches here, use a recursive helper
with the knowledge that the root is higher precedence
than the item to be inserted */
insert_infix_rec(infix_op, *root);
return *root;
}
tree_expr_t * insert_gen_expr(gen_expr_t * gen_expr, tree_expr_t ** root) {
tree_expr_t * new_root;
/* If someone foolishly passes a null
pointer to insert, return the original tree */
if (gen_expr == NULL) {
return *root;
}
/* If the root is null, generate a new expression tree,
using the passed expression as the root element */
if (*root == NULL) {
new_root = new_tree_expr(NULL, gen_expr, NULL, NULL);
*root = new_root;
return new_root;
}
/* Otherwise. the new element definitely will not replace the current root.
Use a recursive helper function to do insertion */
insert_gen_rec(gen_expr, *root);
return *root;
}
/* A recursive helper function to insert general expression elements into the operator tree */
int insert_gen_rec(gen_expr_t * gen_expr, tree_expr_t * root) {
/* Trivial Case: root is null */
if (root == NULL) {
////if (PARSE_DEBUG) printf("insert_gen_rec: root is null, returning failure\n");
return FAILURE;
}
/* The current node's left pointer is null, and this
current node is an infix operator, so insert the
general expression at the left pointer */
if ((root->left == NULL) && (root->infix_op != NULL)) {
root->left = new_tree_expr(NULL, gen_expr, NULL, NULL);
return SUCCESS;
}
/* The current node's right pointer is null, and this
current node is an infix operator, so insert the
general expression at the right pointer */
if ((root->right == NULL) && (root->infix_op != NULL)) {
root->right = new_tree_expr(NULL, gen_expr, NULL, NULL);
return SUCCESS;
}
/* Otherwise recurse down to the left. If
this succeeds then return. If it fails, try
recursing down to the right */
if (insert_gen_rec(gen_expr, root->left) == FAILURE)
return insert_gen_rec(gen_expr, root->right);
/* Impossible for control flow to reach here, but in
the world of C programming, who knows... */
//if (PARSE_DEBUG) printf("insert_gen_rec: should never reach here!\n");
return FAILURE;
}
/* A recursive helper function to insert infix arguments by operator precedence */
int insert_infix_rec(infix_op_t * infix_op, tree_expr_t * root) {
/* Shouldn't happen, implies a parse error */
if (root == NULL)
return FAILURE;
/* Also shouldn't happen, also implies a (different) parse error */
if (root->infix_op == NULL)
return FAILURE;
/* Left tree is empty, attach this operator to it.
I don't think this will ever happen */
if (root->left == NULL) {
root->left = new_tree_expr(infix_op, NULL, root->left, NULL);
return SUCCESS;
}
/* Right tree is empty, attach this operator to it */
if (root->right == NULL) {
root->right = new_tree_expr(infix_op, NULL, root->right, NULL);
return SUCCESS;
}
/* The left element can now be ignored, since there is no way for this
operator to use those expressions */
/* If the right element is not an infix operator,
then insert the expression here, attaching the old right branch
to the left of the new expression */
if (root->right->infix_op == NULL) {
root->right = new_tree_expr(infix_op, NULL, root->right, NULL);
return SUCCESS;
}
/* Traverse deeper if the inserting operator precedence is less than the
the root's right operator precedence */
if (infix_op->precedence < root->right->infix_op->precedence)
return insert_infix_rec(infix_op, root->right);
/* Otherwise, insert the operator here */
root->right = new_tree_expr(infix_op, NULL, root->right, NULL);
return SUCCESS;
}
/* Parses an infix operator */
gen_expr_t * parse_infix_op(FILE * fs, token_t token, tree_expr_t * tree_expr, struct PRESET_T * preset) {
gen_expr_t * gen_expr;
switch (token) {
/* All the infix operators */
case tPlus:
//if (PARSE_DEBUG) printf("parse_infix_op: found addition operator (LINE %d)\n", line_count);
return parse_gen_expr(fs, insert_infix_op(infix_add, &tree_expr), preset);
case tMinus:
//if (PARSE_DEBUG) printf("parse_infix_op: found subtraction operator (LINE %d)\n", line_count);
return parse_gen_expr(fs, insert_infix_op(infix_minus, &tree_expr), preset);
case tMult:
//if (PARSE_DEBUG) printf("parse_infix_op: found multiplication operator (LINE %d)\n", line_count);
return parse_gen_expr(fs, insert_infix_op(infix_mult, &tree_expr), preset);
case tDiv:
//if (PARSE_DEBUG) printf("parse_infix_op: found division operator (LINE %d)\n", line_count);
return parse_gen_expr(fs, insert_infix_op(infix_div, &tree_expr), preset);
case tMod:
//if (PARSE_DEBUG) printf("parse_infix_op: found modulo operator (LINE %d)\n", line_count);
return parse_gen_expr(fs, insert_infix_op(infix_mod, &tree_expr), preset);
case tOr:
//if (PARSE_DEBUG) printf("parse_infix_op: found bitwise or operator (LINE %d)\n", line_count);
return parse_gen_expr(fs, insert_infix_op(infix_or, &tree_expr), preset);
case tAnd:
//if (PARSE_DEBUG) printf("parse_infix_op: found bitwise and operator (LINE %d)\n", line_count);
return parse_gen_expr(fs, insert_infix_op(infix_and, &tree_expr), preset);
case tPositive:
//if (PARSE_DEBUG) printf("parse_infix_op: found positive operator (LINE %d)\n", line_count);
return parse_gen_expr(fs, insert_infix_op(infix_positive, &tree_expr), preset);
case tNegative:
//if (PARSE_DEBUG) printf("parse_infix_op: found negative operator (LINE %d)\n", line_count);
return parse_gen_expr(fs, insert_infix_op(infix_negative, &tree_expr), preset);
case tEOL:
case tEOF:
case tSemiColon:
case tRPr:
case tComma:
//if (PARSE_DEBUG) printf("parse_infix_op: terminal found (LINE %d)\n", line_count);
gen_expr = new_gen_expr(TREE_T, (void*)tree_expr);
return gen_expr;
default:
//if (PARSE_DEBUG) printf("parse_infix_op: operator or terminal expected, but not found (LINE %d)\n", line_count);
free_tree_expr(tree_expr);
return NULL;
}
/* Will never happen */
return NULL;
}
/* Parses an integer, checks for +/- prefix */
int parse_int(FILE * fs, int * int_ptr) {
char string[MAX_TOKEN_SIZE];
token_t token;
int sign;
char * end_ptr = " ";
token = parseToken(fs, string);
switch (token) {
case tMinus:
sign = -1;
token = parseToken(fs, string);
break;
case tPlus:
sign = 1;
token = parseToken(fs, string);
break;
default:
sign = 1;
break;
}
if (string[0] == 0)
return PARSE_ERROR;
/* Convert the string to an integer. *end_ptr
should end up pointing to null terminator of 'string'
if the conversion was successful. */
// printf("STRING: \"%s\"\n", string);
(*int_ptr) = sign*strtol(string, &end_ptr, 10);
/* If end pointer is a return character or null terminator, all is well */
if ((*end_ptr == '\r') || (*end_ptr == '\0'))
return SUCCESS;
return PARSE_ERROR;
}
/* Parses a floating point number */
int string_to_float(char * string, double * float_ptr) {
char ** error_ptr;
if (*string == 0)
return PARSE_ERROR;
error_ptr = malloc(sizeof(char**));
(*float_ptr) = strtod(string, error_ptr);
/* These imply a succesful parse of the string */
if ((**error_ptr == '\0') || (**error_ptr == '\r')) {
free(error_ptr);
return SUCCESS;
}
(*float_ptr) = 0;
free(error_ptr);
return PARSE_ERROR;
}
/* Parses a floating point number */
int parse_float(FILE * fs, double * float_ptr) {
char string[MAX_TOKEN_SIZE];
char ** error_ptr;
token_t token;
int sign;
error_ptr = malloc(sizeof(char**));
token = parseToken(fs, string);
switch (token) {
case tMinus:
sign = -1;
token = parseToken(fs, string);
break;
case tPlus:
sign = 1;
token = parseToken(fs, string);
break;
default:
sign = 1;
}
if (string[0] == 0) {
free(error_ptr);
return PARSE_ERROR;
}
(*float_ptr) = sign*strtod(string, error_ptr);
/* No conversion was performed */
if ((**error_ptr == '\0') || (**error_ptr == '\r')) {
free(error_ptr);
return SUCCESS;
}
//if (PARSE_DEBUG) printf("parse_float: double conversion failed for string \"%s\"\n", string);
(*float_ptr) = 0;
free(error_ptr);
return PARSE_ERROR;
}
/* Parses a per frame equation. That is, interprets a stream of data as a per frame equation */
per_frame_eqn_t * parse_per_frame_eqn(FILE * fs, int index, struct PRESET_T * preset) {
char string[MAX_TOKEN_SIZE];
param_t * param;
per_frame_eqn_t * per_frame_eqn;
gen_expr_t * gen_expr;
if (parseToken(fs, string) != tEq) {
//if (PARSE_DEBUG) printf("parse_per_frame_eqn: no equal sign after string \"%s\" (LINE %d)\n", string, line_count);
return NULL;
}
/* Find the parameter associated with the string, create one if necessary */
if ((param = find_param(string, preset, P_CREATE)) == NULL) {
return NULL;
}
/* Make sure parameter is writable */
if (param->flags & P_FLAG_READONLY) {
//if (PARSE_DEBUG) printf("parse_per_frame_eqn: parameter %s is marked as read only (LINE %d)\n", param->name, line_count);
return NULL;
}
/* Parse right side of equation as an expression */
if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
//if (PARSE_DEBUG) printf("parse_per_frame_eqn: equation evaluated to null (LINE %d)\n", line_count);
return NULL;
}
//if (PARSE_DEBUG) printf("parse_per_frame_eqn: finished per frame equation evaluation (LINE %d)\n", line_count);
/* Create a new per frame equation */
if ((per_frame_eqn = new_per_frame_eqn(index, param, gen_expr)) == NULL) {
//if (PARSE_DEBUG) printf("parse_per_frame_eqn: failed to create a new per frame eqn, out of memory?\n");
free_gen_expr(gen_expr);
return NULL;
}
//if (PARSE_DEBUG) printf("parse_per_frame_eqn: per_frame eqn parsed succesfully\n");
return per_frame_eqn;
}
/* Parses an 'implicit' per frame equation. That is, interprets a stream of data as a per frame equation without a prefix */
per_frame_eqn_t * parse_implicit_per_frame_eqn(FILE * fs, char * param_string, int index, struct PRESET_T * preset) {
param_t * param;
per_frame_eqn_t * per_frame_eqn;
gen_expr_t * gen_expr;
if (fs == NULL)
return NULL;
if (param_string == NULL)
return NULL;
if (preset == NULL)
return NULL;
//rintf("param string: %s\n", param_string);
/* Find the parameter associated with the string, create one if necessary */
if ((param = find_param(param_string, preset, P_CREATE)) == NULL) {
return NULL;
}
//printf("parse_implicit_per_frame_eqn: param is %s\n", param->name);
/* Make sure parameter is writable */
if (param->flags & P_FLAG_READONLY) {
//if (PARSE_DEBUG) printf("parse_implicit_per_frame_eqn: parameter %s is marked as read only (LINE %d)\n", param->name, line_count);
return NULL;
}
/* Parse right side of equation as an expression */
if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
//if (PARSE_DEBUG) printf("parse_implicit_per_frame_eqn: equation evaluated to null (LINE %d)\n", line_count);
return NULL;
}
//if (PARSE_DEBUG) printf("parse_implicit_per_frame_eqn: finished per frame equation evaluation (LINE %d)\n", line_count);
/* Create a new per frame equation */
if ((per_frame_eqn = new_per_frame_eqn(index, param, gen_expr)) == NULL) {
//if (PARSE_DEBUG) printf("parse_implicit_per_frame_eqn: failed to create a new per frame eqn, out of memory?\n");
free_gen_expr(gen_expr);
return NULL;
}
//if (PARSE_DEBUG) printf("parse_implicit_per_frame_eqn: per_frame eqn parsed succesfully\n");
return per_frame_eqn;
}
/* Parses an initial condition */
init_cond_t * parse_init_cond(FILE * fs, char * name, struct PRESET_T * preset) {
param_t * param;
value_t init_val;
init_cond_t * init_cond;
if (name == NULL)
return NULL;
if (preset == NULL)
return NULL;
/* Search for the paramater in the database, creating it if necessary */
if ((param = find_param(name, preset, P_CREATE)) == NULL) {
return NULL;
}
//if (PARSE_DEBUG) printf("parse_init_cond: parameter = \"%s\" (LINE %d)\n", param->name, line_count);
if (param->flags & P_FLAG_READONLY) {
//if (PARSE_DEBUG) printf("parse_init_cond: builtin parameter \"%s\" marked as read only!\n", param->name);
return NULL;
}
/* At this point, a parameter has been created or was found
in the database. */
//if (PARSE_DEBUG) printf("parse_init_cond: parsing initial condition value... (LINE %d)\n", line_count);
/* integer value (boolean is an integer in C) */
if ((param->type == P_TYPE_INT) || (param->type == P_TYPE_BOOL)) {
if ((parse_int(fs, (int*)&init_val.int_val)) == PARSE_ERROR) {
//if (PARSE_DEBUG) printf("parse_init_cond: error parsing integer!\n");
return NULL;
}
}
/* double value */
else if (param->type == P_TYPE_DOUBLE) {
if ((parse_float(fs, (double*)&init_val.double_val)) == PARSE_ERROR) {
//if (PARSE_DEBUG) printf("parse_init_cond: error parsing double!\n");
return NULL;
}
}
/* Unknown value */
else {
//if (PARSE_DEBUG) printf("parse_init_cond: unknown parameter type!\n");
return NULL;
}
/* Create new initial condition */
if ((init_cond = new_init_cond(param, init_val)) == NULL) {
//if (PARSE_DEBUG) printf("parse_init_cond: new_init_cond failed!\n");
return NULL;
}
/* Finished */
return init_cond;
}
/* Parses a per frame init equation, not sure if this works right now */
init_cond_t * parse_per_frame_init_eqn(FILE * fs, struct PRESET_T * preset, splaytree_t * database) {
char name[MAX_TOKEN_SIZE];
param_t * param = NULL;
value_t init_val;
init_cond_t * init_cond;
gen_expr_t * gen_expr;
double val;
token_t token;
if (preset == NULL)
return NULL;
if (fs == NULL)
return NULL;
if ((token = parseToken(fs, name)) != tEq)
return NULL;
/* If a database was specified,then use find_param_db instead */
if ((database != NULL) && ((param = find_param_db(name, database, TRUE)) == NULL)) {
return NULL;
}
/* Otherwise use the builtin parameter and user databases. This is confusing. Sorry. */
if ((param == NULL) && ((param = find_param(name, preset, P_CREATE)) == NULL)) {
return NULL;
}
//if (PARSE_DEBUG) printf("parse_per_frame_init_eqn: parameter = \"%s\" (LINE %d)\n", param->name, line_count);
if (param->flags & P_FLAG_READONLY) {
//if (PARSE_DEBUG) printf("pars_per_frame_init_eqn: builtin parameter \"%s\" marked as read only!\n", param->name);
return NULL;
}
/* At this point, a parameter has been created or was found
in the database. */
//if (PARSE_DEBUG) printf("parse_per_frame_init_eqn: parsing right hand side of per frame init equation.. (LINE %d)\n", line_count);
if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
//if (PARSE_DEBUG) printf("parse_per_frame_init_eqn: failed to parse general expresion!\n");
return NULL;
}
/* Compute initial condition value */
val = eval_gen_expr(gen_expr);
/* Free the general expression now that we are done with it */
free_gen_expr(gen_expr);
/* integer value (boolean is an integer in C) */
if ((param->type == P_TYPE_INT) || (param->type == P_TYPE_BOOL)) {
init_val.int_val = (int)val;
}
/* double value */
else if (param->type == P_TYPE_DOUBLE) {
init_val.double_val = val;
}
/* Unknown value */
else {
//if (PARSE_DEBUG) printf("parse_per_frame_init_eqn: unknown parameter type!\n");
return NULL;
}
/* Create new initial condition */
if ((init_cond = new_init_cond(param, init_val)) == NULL) {
//if (PARSE_DEBUG) printf("parse_per_frame_init_eqn: new_init_cond failed!\n");
return NULL;
}
/* Finished */
return init_cond;
}
int parse_wavecode(char * token, FILE * fs, preset_t * preset) {
char * var_string;
init_cond_t * init_cond;
custom_wave_t * custom_wave;
int id;
value_t init_val;
param_t * param;
/* Null argument checks */
if (preset == NULL)
return FAILURE;
if (fs == NULL)
return FAILURE;
if (token == NULL)
return FAILURE;
/* token should be in the form wavecode_N_var, such as wavecode_1_samples */
/* Get id and variable name from token string */
if (parse_wavecode_prefix(token, &id, &var_string) < 0)
return PARSE_ERROR;
//if (PARSE_DEBUG) printf("parse_wavecode: wavecode id = %d, parameter = \"%s\"\n", id, var_string);
/* Retrieve custom wave information from preset. The 3rd argument
if true creates a custom wave if one does not exist */
if ((custom_wave = find_custom_wave(id, preset, TRUE)) == NULL) {
//if (PARSE_DEBUG) printf("parse_wavecode: failed to load (or create) custom wave (id = %d)!\n", id);
return FAILURE;
}
//if (PARSE_DEBUG) printf("parse_wavecode: custom wave found (id = %d)\n", custom_wave->id);
/* Retrieve parameter from this custom waves parameter db */
if ((param = find_param_db(var_string, custom_wave->param_tree, TRUE)) == NULL)
return FAILURE;
//if (PARSE_DEBUG) printf("parse_wavecode: custom wave parameter found (name = %s)\n", param->name);
/* integer value (boolean is an integer in C) */
if ((param->type == P_TYPE_INT) || (param->type == P_TYPE_BOOL)) {
if ((parse_int(fs, (int*)&init_val.int_val)) == PARSE_ERROR) {
//if (PARSE_DEBUG) printf("parse_wavecode: error parsing integer!\n");
return PARSE_ERROR;
}
}
/* double value */
else if (param->type == P_TYPE_DOUBLE) {
if ((parse_float(fs, (double*)&init_val.double_val)) == PARSE_ERROR) {
//if (PARSE_DEBUG) printf("parse_wavecode: error parsing double!\n");
return PARSE_ERROR;
}
}
/* Unknown value */
else {
//if (PARSE_DEBUG) printf("parse_wavecode: unknown parameter type!\n");
return PARSE_ERROR;
}
/* Create new initial condition */
if ((init_cond = new_init_cond(param, init_val)) == NULL) {
//if (PARSE_DEBUG) printf("parse_wavecode: new_init_cond failed!\n");
return FAILURE;
}
if (splay_insert(init_cond, param->name, custom_wave->init_cond_tree) < 0) {
free_init_cond(init_cond);
return PARSE_ERROR;
}
//if (PARSE_DEBUG) printf("parse_wavecode: [success]\n");
return SUCCESS;
}
int parse_shapecode(char * token, FILE * fs, preset_t * preset) {
char * var_string;
init_cond_t * init_cond;
custom_shape_t * custom_shape;
int id;
value_t init_val;
param_t * param;
/* Null argument checks */
if (preset == NULL)
return FAILURE;
if (fs == NULL)
return FAILURE;
if (token == NULL)
return FAILURE;
/* token should be in the form shapecode_N_var, such as shapecode_1_samples */
/* Get id and variable name from token string */
if (parse_shapecode_prefix(token, &id, &var_string) < 0)
return PARSE_ERROR;
//if (PARSE_DEBUG) printf("parse_shapecode: shapecode id = %d, parameter = \"%s\"\n", id, var_string);
/* Retrieve custom shape information from preset. The 3rd argument
if true creates a custom shape if one does not exist */
if ((custom_shape = find_custom_shape(id, preset, TRUE)) == NULL) {
//if (PARSE_DEBUG) printf("parse_shapecode: failed to load (or create) custom shape (id = %d)!\n", id);
return FAILURE;
}
//if (PARSE_DEBUG) printf("parse_shapecode: custom shape found (id = %d)\n", custom_shape->id);
/* Retrieve parameter from this custom shapes parameter db */
if ((param = find_param_db(var_string, custom_shape->param_tree, TRUE)) == NULL) {
//if (PARSE_DEBUG) printf("parse_shapecode: failed to create parameter.\n");
return FAILURE;
}
//if (PARSE_DEBUG) printf("parse_shapecode: custom shape parameter found (name = %s)\n", param->name);
/* integer value (boolean is an integer in C) */
if ((param->type == P_TYPE_INT) || (param->type == P_TYPE_BOOL)) {
if ((parse_int(fs, (int*)&init_val.int_val)) == PARSE_ERROR) {
//if (PARSE_DEBUG) printf("parse_shapecode: error parsing integer!\n");
return PARSE_ERROR;
}
}
/* double value */
else if (param->type == P_TYPE_DOUBLE) {
if ((parse_float(fs, (double*)&init_val.double_val)) == PARSE_ERROR) {
//if (PARSE_DEBUG) printf("parse_shapecode: error parsing double!\n");
return PARSE_ERROR;
}
}
/* Unknown value */
else {
//if (PARSE_DEBUG) printf("parse_shapecode: unknown parameter type!\n");
return PARSE_ERROR;
}
/* Create new initial condition */
if ((init_cond = new_init_cond(param, init_val)) == NULL) {
//if (PARSE_DEBUG) printf("parse_shapecode: new_init_cond failed!\n");
return FAILURE;
}
if (splay_insert(init_cond, param->name, custom_shape->init_cond_tree) < 0) {
free_init_cond(init_cond);
//if (PARSE_DEBUG) printf("parse_shapecode: initial condition already set, not reinserting it (param = \"%s\")\n", param->name);
return PARSE_ERROR;
}
//if (PARSE_DEBUG) printf("parse_shapecode: [success]\n");
return SUCCESS;
}
int parse_wavecode_prefix(char * token, int * id, char ** var_string) {
int len, i, j;
if (token == NULL)
return FAILURE;
if (*var_string == NULL)
return FAILURE;
if (id == NULL)
return FAILURE;
len = strlen(token);
/* Move pointer passed "wavecode_" prefix */
if (len <= WAVECODE_STRING_LENGTH)
return FAILURE;
i = WAVECODE_STRING_LENGTH;
j = 0;
(*id) = 0;
/* This loop grabs the integer id for this custom wave */
while ((i < len) && (token[i] >= 48) && (token[i] <= 57)) {
if (j >= MAX_TOKEN_SIZE)
return FAILURE;
(*id) = 10*(*id) + (token[i]-48);
j++;
i++;
}
if (i > (len - 2))
return FAILURE;
*var_string = token + i + 1;
return SUCCESS;
}
int parse_shapecode_prefix(char * token, int * id, char ** var_string) {
int len, i, j;
if (token == NULL)
return FAILURE;
if (*var_string == NULL)
return FAILURE;
if (id == NULL)
return FAILURE;
len = strlen(token);
/* Move pointer passed "shapecode_" prefix */
if (len <= SHAPECODE_STRING_LENGTH)
return FAILURE;
i = SHAPECODE_STRING_LENGTH;
j = 0;
(*id) = 0;
/* This loop grabs the integer id for this custom shape */
while ((i < len) && (token[i] >= 48) && (token[i] <= 57)) {
if (j >= MAX_TOKEN_SIZE)
return FAILURE;
(*id) = 10*(*id) + (token[i]-48);
j++;
i++;
}
if (i > (len - 2))
return FAILURE;
*var_string = token + i + 1;
return SUCCESS;
}
int parse_wave_prefix(char * token, int * id, char ** eqn_string) {
int len, i, j;
if (token == NULL)
return FAILURE;
if (eqn_string == NULL)
return FAILURE;
if (id == NULL)
return FAILURE;
len = strlen(token);
if (len <= WAVE_STRING_LENGTH)
return FAILURE;
i = WAVE_STRING_LENGTH;
j = 0;
(*id) = 0;
/* This loop grabs the integer id for this custom wave */
while ((i < len) && (token[i] >= 48) && (token[i] <= 57)) {
if (j >= MAX_TOKEN_SIZE)
return FAILURE;
(*id) = 10*(*id) + (token[i]-48);
j++;
i++;
}
if (i > (len - 2))
return FAILURE;
*eqn_string = token + i + 1;
return SUCCESS;
}
int parse_shape_prefix(char * token, int * id, char ** eqn_string) {
int len, i, j;
if (token == NULL)
return FAILURE;
if (eqn_string == NULL)
return FAILURE;
if (id == NULL)
return FAILURE;
len = strlen(token);
if (len <= SHAPE_STRING_LENGTH)
return FAILURE;
i = SHAPE_STRING_LENGTH;
j = 0;
(*id) = 0;
/* This loop grabs the integer id for this custom wave */
while ((i < len) && (token[i] >= 48) && (token[i] <= 57)) {
if (j >= MAX_TOKEN_SIZE)
return FAILURE;
(*id) = 10*(*id) + (token[i]-48);
j++;
i++;
}
if (i > (len - 2))
return FAILURE;
*eqn_string = token + i + 1;
return SUCCESS;
}
/* Parses custom wave equations */
int parse_wave(char * token, FILE * fs, preset_t * preset) {
int id;
char * eqn_type;
char string[MAX_TOKEN_SIZE];
param_t * param;
per_frame_eqn_t * per_frame_eqn;
gen_expr_t * gen_expr;
custom_wave_t * custom_wave;
init_cond_t * init_cond;
if (token == NULL)
return FAILURE;
if (fs == NULL)
return FAILURE;
if (preset == NULL)
return FAILURE;
/* Grab custom wave id and equation type (per frame or per point) from string token */
if (parse_wave_prefix(token, &id, &eqn_type) < 0) {
//if (PARSE_DEBUG) printf("parse_wave: syntax error in custom wave prefix!\n");
return FAILURE;
}
/* Retrieve custom wave associated with this id */
if ((custom_wave = find_custom_wave(id, preset, TRUE)) == NULL)
return FAILURE;
/* per frame init equation case */
if (!strncmp(eqn_type, WAVE_INIT_STRING, WAVE_INIT_STRING_LENGTH)) {
//if (PARSE_DEBUG) printf("parse_wave (per frame init): [begin] (LINE %d)\n", line_count);
/* Parse the per frame equation */
if ((init_cond = parse_per_frame_init_eqn(fs, preset, custom_wave->param_tree)) == NULL) {
//if (PARSE_DEBUG) printf("parse_wave (per frame init): equation parsing failed (LINE %d)\n", line_count);
return PARSE_ERROR;
}
/* Insert the equation in the per frame equation tree */
if (splay_insert(init_cond, init_cond->param->name, custom_wave->per_frame_init_eqn_tree) < 0) {
//if (PARSE_DEBUG) printf("parse_wave (per frame init): failed to add equation (ERROR)\n");
free_init_cond(init_cond); /* will free the gen expr too */
return FAILURE;
}
if (update_string_buffer(custom_wave->per_frame_init_eqn_string_buffer,
&custom_wave->per_frame_init_eqn_string_index) < 0)
return FAILURE;
return SUCCESS;
}
/* per frame equation case */
if (!strncmp(eqn_type, PER_FRAME_STRING_NO_UNDERSCORE, PER_FRAME_STRING_NO_UNDERSCORE_LENGTH)) {
//if (PARSE_DEBUG) printf("parse_wave (per_frame): [start] (custom wave id = %d)\n", custom_wave->id);
if (parseToken(fs, string) != tEq) {
//if (PARSE_DEBUG) printf("parse_wave (per_frame): no equal sign after string \"%s\" (LINE %d)\n", string, line_count);
return PARSE_ERROR;
}
/* Find the parameter associated with the string in the custom wave database */
if ((param = find_param_db(string, custom_wave->param_tree, TRUE)) == NULL) {
//if (PARSE_DEBUG) printf("parse_wave (per_frame): parameter \"%s\" not found or cannot be malloc'ed!!\n", string);
return FAILURE;
}
/* Make sure parameter is writable */
if (param->flags & P_FLAG_READONLY) {
//if (PARSE_DEBUG) printf("parse_wave (per_frame): parameter %s is marked as read only (LINE %d)\n", param->name, line_count);
return FAILURE;
}
/* Parse right side of equation as an expression */
current_wave = custom_wave;
if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
//if (PARSE_DEBUG) printf("parse_wave (per_frame): equation evaluated to null (LINE %d)\n", line_count);
current_wave = NULL;
return PARSE_ERROR;
}
current_wave = NULL;
//if (PARSE_DEBUG) printf("parse_wave (per_frame): [finished parsing equation] (LINE %d)\n", line_count);
/* Create a new per frame equation */
if ((per_frame_eqn = new_per_frame_eqn(custom_wave->per_frame_count++, param, gen_expr)) == NULL) {
//if (PARSE_DEBUG) printf("parse_wave (per_frame): failed to create a new per frame eqn, out of memory?\n");
free_gen_expr(gen_expr);
return FAILURE;
}
if (splay_insert(per_frame_eqn, &per_frame_eqn->index, custom_wave->per_frame_eqn_tree) < 0) {
free_per_frame_eqn(per_frame_eqn);
return FAILURE;
}
//if (PARSE_DEBUG) printf("parse_wave (per_frame): equation %d associated with custom wave %d [success]\n",
// per_frame_eqn->index, custom_wave->id);
/* Need to add stuff to string buffer so the editor can read the equations.
Why not make a nice little helper function for this? - here it is: */
if (update_string_buffer(custom_wave->per_frame_eqn_string_buffer, &custom_wave->per_frame_eqn_string_index) < 0)
return FAILURE;
return SUCCESS;
}
/* per point equation case */
if (!strncmp(eqn_type, PER_POINT_STRING, PER_POINT_STRING_LENGTH)) {
//if (PARSE_DEBUG) printf("parse_wave (per_point): per_pixel equation parsing start...(LINE %d)\n", line_count);
if (parseToken(fs, string) != tEq) { /* parse per pixel operator name */
//if (PARSE_DEBUG) printf("parse_wave (per_point): equal operator missing after per pixel operator! (LINE %d)\n", line_count);
return PARSE_ERROR;
}
/* Parse right side of equation as an expression */
current_wave = custom_wave;
if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
//if (PARSE_DEBUG) printf("parse_wave (per_point): equation evaluated to null? (LINE %d)\n", line_count);
return PARSE_ERROR;
}
current_wave = NULL;
/* Add the per point equation */
if (add_per_point_eqn(string, gen_expr, custom_wave) < 0) {
free_gen_expr(gen_expr);
return PARSE_ERROR;
}
if (update_string_buffer(custom_wave->per_point_eqn_string_buffer, &custom_wave->per_point_eqn_string_index) < 0)
return FAILURE;
//if (PARSE_DEBUG) printf("parse_wave (per_point): [finished] (custom wave id = %d)\n", custom_wave->id);
return SUCCESS;
}
/* Syntax error, return parse error */
return PARSE_ERROR;
}
/* Parses custom shape equations */
int parse_shape(char * token, FILE * fs, preset_t * preset) {
int id;
char * eqn_type;
char string[MAX_TOKEN_SIZE];
param_t * param;
per_frame_eqn_t * per_frame_eqn;
gen_expr_t * gen_expr;
custom_shape_t * custom_shape;
init_cond_t * init_cond;
if (token == NULL)
return FAILURE;
if (fs == NULL)
return FAILURE;
if (preset == NULL)
return FAILURE;
/* Grab custom shape id and equation type (per frame or per point) from string token */
if (parse_shape_prefix(token, &id, &eqn_type) < 0) {
//if (PARSE_DEBUG) printf("parse_shape: syntax error in custom shape prefix!\n");
return PARSE_ERROR;
}
/* Retrieve custom shape associated with this id */
if ((custom_shape = find_custom_shape(id, preset, TRUE)) == NULL)
return FAILURE;
/* per frame init equation case */
if (!strncmp(eqn_type, SHAPE_INIT_STRING, SHAPE_INIT_STRING_LENGTH)) {
//if (PARSE_DEBUG) printf("parse_shape (per frame init): [begin] (LINE %d)\n", line_count);
/* Parse the per frame equation */
if ((init_cond = parse_per_frame_init_eqn(fs, preset, custom_shape->param_tree)) == NULL) {
//if (PARSE_DEBUG) printf("parse_shape (per frame init): equation parsing failed (LINE %d)\n", line_count);
return PARSE_ERROR;
}
/* Insert the equation in the per frame equation tree */
if (splay_insert(init_cond, init_cond->param->name, custom_shape->per_frame_init_eqn_tree) < 0) {
//if (PARSE_DEBUG) printf("parse_shape (per frame init): failed to add equation (ERROR)\n");
free_init_cond(init_cond); /* will free the gen expr too */
return ERROR;
}
if (update_string_buffer(custom_shape->per_frame_init_eqn_string_buffer,
&custom_shape->per_frame_init_eqn_string_index) < 0)
return FAILURE;
return SUCCESS;
}
/* per frame equation case */
if (!strncmp(eqn_type, PER_FRAME_STRING_NO_UNDERSCORE, PER_FRAME_STRING_NO_UNDERSCORE_LENGTH)) {
//if (PARSE_DEBUG) printf("parse_shape (per_frame): [start] (custom shape id = %d)\n", custom_shape->id);
if (parseToken(fs, string) != tEq) {
//if (PARSE_DEBUG) printf("parse_shape (per_frame): no equal sign after string \"%s\" (LINE %d)\n", string, line_count);
return PARSE_ERROR;
}
/* Find the parameter associated with the string in the custom shape database */
if ((param = find_param_db(string, custom_shape->param_tree, TRUE)) == NULL) {
//if (PARSE_DEBUG) printf("parse_shape (per_frame): parameter \"%s\" not found or cannot be malloc'ed!!\n", string);
return FAILURE;
}
/* Make sure parameter is writable */
if (param->flags & P_FLAG_READONLY) {
//if (PARSE_DEBUG) printf("parse_shape (per_frame): parameter %s is marked as read only (LINE %d)\n", param->name, line_count);
return FAILURE;
}
/* Parse right side of equation as an expression */
current_shape = custom_shape;
if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
//if (PARSE_DEBUG) printf("parse_shape (per_frame): equation evaluated to null (LINE %d)\n", line_count);
current_shape = NULL;
return PARSE_ERROR;
}
current_shape = NULL;
//if (PARSE_DEBUG) printf("parse_shape (per_frame): [finished parsing equation] (LINE %d)\n", line_count);
/* Create a new per frame equation */
if ((per_frame_eqn = new_per_frame_eqn(custom_shape->per_frame_count++, param, gen_expr)) == NULL) {
//if (PARSE_DEBUG) printf("parse_shape (per_frame): failed to create a new per frame eqn, out of memory?\n");
free_gen_expr(gen_expr);
return FAILURE;
}
if (splay_insert(per_frame_eqn, &per_frame_eqn->index, custom_shape->per_frame_eqn_tree) < 0) {
free_per_frame_eqn(per_frame_eqn);
return FAILURE;
}
//if (PARSE_DEBUG) printf("parse_shape (per_frame): equation %d associated with custom shape %d [success]\n",
// per_frame_eqn->index, custom_shape->id);
/* Need to add stuff to string buffer so the editor can read the equations.
Why not make a nice little helper function for this? - here it is: */
if (update_string_buffer(custom_shape->per_frame_eqn_string_buffer, &custom_shape->per_frame_eqn_string_index) < 0)
return FAILURE;
return SUCCESS;
}
/* Syntax error, return parse error */
return PARSE_ERROR;
}
/* Helper function to update the string buffers used by the editor */
int update_string_buffer(char * buffer, int * index) {
int string_length;
int skip_size;
if (!buffer)
return FAILURE;
if (!index)
return FAILURE;
/* If the string line buffer used by the parser is already full then quit */
if (string_line_buffer_index == (STRING_LINE_SIZE-1))
return FAILURE;
if ((skip_size = get_string_prefix_len(string_line_buffer)) == FAILURE)
return FAILURE;
string_line_buffer[string_line_buffer_index++] = '\n';
// string_length = strlen(string_line_buffer + strlen(eqn_string)+1);
if (skip_size >= STRING_LINE_SIZE)
return FAILURE;
string_length = strlen(string_line_buffer + skip_size);
if (skip_size > (STRING_LINE_SIZE-1))
return FAILURE;
/* Add line to string buffer */
strncpy(buffer + (*index),
string_line_buffer + skip_size, string_length);
/* Buffer full, quit */
if ((*index) > (STRING_BUFFER_SIZE - 1)) {
//if (PARSE_DEBUG) printf("update_string_buffer: string buffer full!\n");
return FAILURE;
}
/* Otherwise, increment string index by the added string length */
(*index)+=string_length;
return SUCCESS;
}
/* Helper function: returns the length of the prefix portion in the line
buffer (the passed string here). In other words, given
the string 'per_frame_1 = x = ....', return the length of 'per_frame_1 = '
Returns -1 if syntax error
*/
int get_string_prefix_len(char * string) {
int i = 0;
/* Null argument check */
if (string == NULL)
return FAILURE;
/* First find the equal sign */
while (string[i] != '=') {
if (string[i] == 0)
return FAILURE;
i++;
}
/* If the string already ends at the next char then give up */
if (string[i+1] == 0)
return FAILURE;
/* Move past the equal sign */
i++;
/* Now found the start of the LHS variable, ie skip the spaces */
while(string[i] == ' ') {
i++;
}
/* If this is the end of the string then its a syntax error */
if (string[i] == 0)
return FAILURE;
/* Finished succesfully, return the length */
return i;
}
#ifndef PARSER_H
#define PARSER_H
#define PARSE_DEBUG 0
#include "expr_types.h"
#include "per_frame_eqn_types.h"
#include "init_cond_types.h"
#include "preset_types.h"
#include <stdio.h>
per_frame_eqn_t * parse_per_frame_eqn(FILE * fs, int index, struct PRESET_T * preset);
int parse_per_pixel_eqn(FILE * fs, preset_t * preset);
init_cond_t * parse_init_cond(FILE * fs, char * name, struct PRESET_T * preset);
int parse_preset_name(FILE * fs, char * name);
int parse_top_comment(FILE * fs);
int parse_line(FILE * fs, struct PRESET_T * preset);
#endif
/*****************************************************************************
* per_frame_eqn.c:
*****************************************************************************
* Copyright (C) 2004 the VideoLAN team
* $Id$
*
* Authors: Cyril Deguet <asmax@videolan.org>
* code from projectM http://xmms-projectm.sourceforge.net
*
* 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "fatal.h"
#include "common.h"
#include "param.h"
#include "per_frame_eqn_types.h"
#include "per_frame_eqn.h"
#include "expr_types.h"
#include "eval.h"
/* Evaluate an equation */
void eval_per_frame_eqn(per_frame_eqn_t * per_frame_eqn) {
if (per_frame_eqn == NULL)
return;
if (PER_FRAME_EQN_DEBUG) {
printf("per_frame_%d=%s= ", per_frame_eqn->index, per_frame_eqn->param->name);
fflush(stdout);
}
//*((double*)per_frame_eqn->param->engine_val) = eval_gen_expr(per_frame_eqn->gen_expr);
set_param(per_frame_eqn->param, eval_gen_expr(per_frame_eqn->gen_expr));
if (PER_FRAME_EQN_DEBUG) printf(" = %.4f\n", *((double*)per_frame_eqn->param->engine_val));
}
/*
void eval_per_frame_init_eqn(per_frame_eqn_t * per_frame_eqn) {
double val;
init_cond_t * init_cond;
if (per_frame_eqn == NULL)
return;
if (PER_FRAME_EQN_DEBUG) {
printf("per_frame_init: %s = ", per_frame_eqn->param->name);
fflush(stdout);
}
val = *((double*)per_frame_eqn->param->engine_val) = eval_gen_expr(per_frame_eqn->gen_expr);
if (PER_FRAME_EQN_DEBUG) printf(" = %f\n", *((double*)per_frame_eqn->param->engine_val));
if (per_frame_eqn->param->flags & P_FLAG_QVAR) {
per_frame_eqn->param->init_val.double_val = val;
if ((init_cond = new_init_cond(per_frame_eqn->param)) == NULL)
return;
if ((list_append(init_cond_list, init_cond)) < 0) {
free_init_cond(init_cond);
return;
}
}
}
*/
/* Frees perframe equation structure */
void free_per_frame_eqn(per_frame_eqn_t * per_frame_eqn) {
if (per_frame_eqn == NULL)
return;
free_gen_expr(per_frame_eqn->gen_expr);
free(per_frame_eqn);
}
/* Create a new per frame equation */
per_frame_eqn_t * new_per_frame_eqn(int index, param_t * param, gen_expr_t * gen_expr) {
per_frame_eqn_t * per_frame_eqn;
per_frame_eqn = (per_frame_eqn_t*)malloc(sizeof(per_frame_eqn_t));
if (per_frame_eqn == NULL)
return NULL;
per_frame_eqn->param = param;
per_frame_eqn->gen_expr = gen_expr;
per_frame_eqn->index = index;
/* Set per frame eqn name */
// memset(per_frame_eqn->name, 0, MAX_TOKEN_SIZE);
//strncpy(per_frame_eqn->name, name, MAX_TOKEN_SIZE-1);
return per_frame_eqn;
}
#ifndef PER_FRAME_EQN_H
#define PER_FRAME_EQN_H
#define PER_FRAME_EQN_DEBUG 0
per_frame_eqn_t * new_per_frame_eqn(int index, param_t * param, struct GEN_EXPR_T * gen_expr);
void eval_per_frame_eqn(per_frame_eqn_t * per_frame_eqn);
void free_per_frame_eqn(per_frame_eqn_t * per_frame_eqn);
void eval_per_frame_init_eqn(per_frame_eqn_t * per_frame_eqn);
#endif
#ifndef PER_FRAME_EQN_TYPES_H
#define PER_FRAME_EQN_TYPES_H
#include "param_types.h"
#include "expr_types.h"
typedef struct PER_FRAME_EQN_T {
int index;
struct PARAM_T * param; /* parameter to be assigned a value */
struct GEN_EXPR_T * gen_expr; /* expression that paremeter is equal to */
} per_frame_eqn_t;
#endif
/*****************************************************************************
* per_pixel_eqn.c:
*****************************************************************************
* Copyright (C) 2004 the VideoLAN team
* $Id$
*
* Authors: Cyril Deguet <asmax@videolan.org>
* code from projectM http://xmms-projectm.sourceforge.net
*
* 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "fatal.h"
#include "common.h"
#include "expr_types.h"
#include "eval.h"
#include "splaytree_types.h"
#include "splaytree.h"
#include "param_types.h"
#include "param.h"
#include "per_pixel_eqn.h"
#include "per_pixel_eqn_types.h"
#include "engine_vars.h"
extern preset_t * active_preset;
extern int mesh_i;
extern int mesh_j;
/* Evaluates a per pixel equation */
void evalPerPixelEqn(per_pixel_eqn_t * per_pixel_eqn) {
double ** param_matrix = NULL;
gen_expr_t * eqn_ptr = NULL;
int x,y;
eqn_ptr = per_pixel_eqn->gen_expr;
if (per_pixel_eqn->param->matrix == NULL) {
if (PER_PIXEL_EQN_DEBUG) printf("evalPerPixelEqn: [begin initializing matrix] (index = %d) (name = %s)\n",
per_pixel_eqn->index, per_pixel_eqn->param->name);
param_matrix = per_pixel_eqn->param->matrix = (double**)malloc(gx*sizeof(double*));
for(x = 0; x < gx; x++)
param_matrix[x] = (double *)malloc(gy * sizeof(double));
for (x = 0; x < gx; x++)
for (y = 0; y < gy; y++)
param_matrix[x][y] = 0.0;
if (per_pixel_eqn->param->name == NULL)
printf("null parameter?\n");
// printf("PARAM MATRIX: \"%s\" initialized.\n", per_pixel_eqn->param->name);
}
else
param_matrix = (double**)per_pixel_eqn->param->matrix;
if (eqn_ptr == NULL)
printf("something is seriously wrong...\n");
for (mesh_i = 0; mesh_i < gx; mesh_i++) {
for (mesh_j = 0; mesh_j < gy; mesh_j++) {
param_matrix[mesh_i][mesh_j] = eval_gen_expr(eqn_ptr);
}
}
/* Now that this parameter has been referenced with a per
pixel equation, we let the evaluator know by setting
this flag */
per_pixel_eqn->param->matrix_flag = 1;
}
void evalPerPixelEqns() {
/* Evaluate all per pixel equations using splay traversal */
splay_traverse(evalPerPixelEqn, active_preset->per_pixel_eqn_tree);
/* Set mesh i / j values to -1 so engine vars are used by default again */
mesh_i = mesh_j = -1;
}
/* Adds a per pixel equation according to its string name. This
will be used only by the parser */
int add_per_pixel_eqn(char * name, gen_expr_t * gen_expr, preset_t * preset) {
per_pixel_eqn_t * per_pixel_eqn;
int index;
param_t * param = NULL;
/* Argument checks */
if (preset == NULL)
return FAILURE;
if (gen_expr == NULL)
return FAILURE;
if (name == NULL)
return FAILURE;
if (PER_PIXEL_EQN_DEBUG) printf("add_per_pixel_eqn: per pixel equation (name = \"%s\")\n", name);
if (!strncmp(name, "dx", strlen("dx")))
preset->per_pixel_flag[DX_OP] = TRUE;
else if (!strncmp(name, "dy", strlen("dy")))
preset->per_pixel_flag[DY_OP] = TRUE;
else if (!strncmp(name, "cx", strlen("cx")))
preset->per_pixel_flag[CX_OP] = TRUE;
else if (!strncmp(name, "cy", strlen("cy")))
preset->per_pixel_flag[CX_OP] = TRUE;
else if (!strncmp(name, "zoom", strlen("zoom")))
preset->per_pixel_flag[ZOOM_OP] = TRUE;
else if (!strncmp(name, "zoomexp", strlen("zoomexp")))
preset->per_pixel_flag[ZOOMEXP_OP] = TRUE;
else if (!strncmp(name, "rot", strlen("rot")))
preset->per_pixel_flag[ROT_OP] = TRUE;
else if (!strncmp(name, "sx", strlen("sx")))
preset->per_pixel_flag[SX_OP] = TRUE;
else if (!strncmp(name, "sy", strlen("sy")))
preset->per_pixel_flag[SY_OP] = TRUE;
/* Search for the parameter so we know what matrix the per pixel equation is referencing */
if ((param = find_param(name, preset, TRUE)) == NULL) {
if (PER_PIXEL_EQN_DEBUG) printf("add_per_pixel_eqn: failed to allocate a new parameter!\n");
return FAILURE;
}
/* Find most largest index in the splaytree */
// if ((per_pixel_eqn = splay_find_max(active_preset->per_pixel_eqn_tree)) == NULL)
// index = 0;
// else
index = splay_size(preset->per_pixel_eqn_tree);
/* Create the per pixel equation given the index, parameter, and general expression */
if ((per_pixel_eqn = new_per_pixel_eqn(index, param, gen_expr)) == NULL) {
if (PER_PIXEL_EQN_DEBUG) printf("add_per_pixel_eqn: failed to create new per pixel equation!\n");
return FAILURE;
}
if (PER_PIXEL_EQN_DEBUG) printf("add_per_pixel_eqn: new equation (index = %d) (param = \"%s\")\n",
per_pixel_eqn->index, per_pixel_eqn->param->name);
/* Insert the per pixel equation into the preset per pixel database */
if (splay_insert(per_pixel_eqn, &per_pixel_eqn->index, preset->per_pixel_eqn_tree) < 0) {
free_per_pixel_eqn(per_pixel_eqn);
printf("failed to add per pixel eqn!\n");
return FAILURE;
}
/* Done */
return SUCCESS;
}
per_pixel_eqn_t * new_per_pixel_eqn(int index, param_t * param, gen_expr_t * gen_expr) {
per_pixel_eqn_t * per_pixel_eqn;
if (index < 0)
return NULL;
if (param == NULL)
return NULL;
if (gen_expr == NULL)
return NULL;
if ((per_pixel_eqn = (per_pixel_eqn_t*)malloc(sizeof(per_pixel_eqn_t))) == NULL)
return NULL;
per_pixel_eqn->index = index;
per_pixel_eqn->param = param;
per_pixel_eqn->gen_expr = gen_expr;
return per_pixel_eqn;
}
void free_per_pixel_eqn(per_pixel_eqn_t * per_pixel_eqn) {
if (per_pixel_eqn == NULL)
return;
free_gen_expr(per_pixel_eqn->gen_expr);
free(per_pixel_eqn);
return;
}
static inline int resetPerPixelEqnFlags(preset_t * preset) {
int i;
for (i = 0; i < NUM_OPS;i++)
preset->per_pixel_flag[i] = FALSE;
return SUCCESS;
}
#ifndef PER_PIXEL_EQN_H
#define PER_PIXEL_EQN_H
#include "expr_types.h"
#include "preset_types.h"
#define PER_PIXEL_EQN_DEBUG 0
void evalPerPixelEqns();
int add_per_pixel_eqn(char * name, gen_expr_t * gen_expr, struct PRESET_T * preset);
void free_per_pixel_eqn(per_pixel_eqn_t * per_pixel_eqn);
per_pixel_eqn_t * new_per_pixel_eqn(int index, param_t * param, gen_expr_t * gen_expr);
inline int resetPerPixelEqnFlags();
#endif
#ifndef PER_PIXEL_EQN_TYPES_H
#define PER_PIXEL_EQN_TYPES_H
/* This is sort of ugly, but it is also the fastest way to access the per pixel equations */
#include "common.h"
#include "expr_types.h"
typedef struct PER_PIXEL_EQN_T {
int index; /* used for splay tree ordering. */
int flags; /* primarily to specify if this variable is user-defined */
param_t * param;
gen_expr_t * gen_expr;
} per_pixel_eqn_t;
#define ZOOM_OP 0
#define ZOOMEXP_OP 1
#define ROT_OP 2
#define CX_OP 3
#define CY_OP 4
#define SX_OP 5
#define SY_OP 6
#define DX_OP 7
#define DY_OP 8
#define WARP_OP 9
#define NUM_OPS 10 /* obviously, this number is dependent on the number of existing per pixel operations */
#endif
#ifndef PER_POINT_EQN_TYPES_H
#define PER_POINT_EQN_TYPES_H
#include "custom_wave_types.h"
typedef struct PER_POINT_EQN {
custom_wave_t * custom_wave;
} per_point_eqn_t;
#endif
/*****************************************************************************
* plugin.c:
*****************************************************************************
* Copyright (C) 2004 the VideoLAN team
* $Id$
*
* Authors: Cyril Deguet <asmax@videolan.org>
* Implementation of the winamp plugin MilkDrop
* based on projectM http://xmms-projectm.sourceforge.net
* and SciVi http://xmms-scivi.sourceforge.net
*
* 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include "plugin.h"
#include "main.h"
#include "PCM.h"
#include "video_init.h"
#include <GL/glu.h>
#include <vlc_input.h>
#include <vlc_playlist.h>
#include <vlc_plugin.h>
/*****************************************************************************
* Module descriptor
*****************************************************************************/
static int Open ( vlc_object_t * );
static void Close ( vlc_object_t * );
#define WIDTH_TEXT N_("Video width")
#define WIDTH_LONGTEXT N_("The width of the video window, in pixels.")
#define HEIGHT_TEXT N_("Video height")
#define HEIGHT_LONGTEXT N_("The height of the video window, in pixels.")
vlc_module_begin ()
set_description( N_("GaLaktos visualization") )
set_capability( "visualization", 0 )
set_callbacks( Open, Close )
add_shortcut( "galaktos" )
add_integer( "galaktos-width", 640, NULL, WIDTH_TEXT, WIDTH_LONGTEXT,
false )
add_integer( "galaktos-height", 480, NULL, HEIGHT_TEXT, HEIGHT_LONGTEXT,
false )
vlc_module_end ()
/*****************************************************************************
* Local prototypes
*****************************************************************************/
struct aout_filter_sys_t
{
galaktos_thread_t *p_thread;
};
static void DoWork ( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
aout_buffer_t * );
static void* Thread ( vlc_object_t * );
static char *TitleGet( vlc_object_t * );
extern GLuint RenderTargetTextureID;
/*****************************************************************************
* Open: open a scope effect plugin
*****************************************************************************/
static int Open( vlc_object_t *p_this )
{
aout_filter_t *p_filter = (aout_filter_t *)p_this;
aout_filter_sys_t *p_sys;
galaktos_thread_t *p_thread;
if( p_filter->input.i_format != VLC_CODEC_FL32 ||
p_filter->output.i_format != VLC_CODEC_FL32 )
{
msg_Warn( p_filter, "bad input or output format" );
return VLC_EGENERIC;
}
if ( !AOUT_FMTS_SIMILAR( &p_filter->input, &p_filter->output ) )
{
msg_Warn( p_filter, "input and output formats are not similar" );
return VLC_EGENERIC;
}
p_filter->pf_do_work = DoWork;
p_filter->b_in_place = 1;
/* Allocate structure */
p_sys = p_filter->p_sys = malloc( sizeof( aout_filter_sys_t ) );
/* Create galaktos thread */
p_sys->p_thread = p_thread =
vlc_object_create( p_filter, sizeof( galaktos_thread_t ) );
vlc_object_attach( p_thread, p_this );
p_thread->i_cur_sample = 0;
bzero( p_thread->p_data, 2*2*512 );
p_thread->i_width = var_CreateGetInteger( p_thread, "galaktos-width" );
p_thread->i_height = var_CreateGetInteger( p_thread, "galaktos-height" );
p_thread->b_fullscreen = 0;
galaktos_init( p_thread );
p_thread->i_channels = aout_FormatNbChannels( &p_filter->input );
p_thread->psz_title = TitleGet( VLC_OBJECT( p_filter ) );
if( vlc_thread_create( p_thread, "galaktos update thread", Thread,
VLC_THREAD_PRIORITY_LOW ) )
{
msg_Err( p_filter, "cannot lauch galaktos thread" );
free( p_thread->psz_title );
vlc_object_detach( p_thread );
vlc_object_release( p_thread );
free( p_sys );
return VLC_EGENERIC;
}
return VLC_SUCCESS;
}
/*****************************************************************************
* float to s16 conversion
*****************************************************************************/
static inline int16_t FloatToInt16( float f )
{
if( f >= 1.0 )
return 32767;
else if( f < -1.0 )
return -32768;
else
return (int16_t)( f * 32768.0 );
}
/*****************************************************************************
* DoWork: process samples buffer
*****************************************************************************
* This function queues the audio buffer to be processed by the galaktos thread
*****************************************************************************/
static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
{
int i_samples;
int i_channels;
float *p_float;
galaktos_thread_t *p_thread = p_filter->p_sys->p_thread;
p_float = (float *)p_in_buf->p_buffer;
i_channels = p_thread->i_channels;
p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes;
for( i_samples = p_in_buf->i_nb_samples; i_samples > 0; i_samples-- )
{
int i_cur_sample = p_thread->i_cur_sample;
p_thread->p_data[0][i_cur_sample] = FloatToInt16( p_float[0] );
if( i_channels > 1 )
{
p_thread->p_data[1][i_cur_sample] = FloatToInt16( p_float[1] );
}
p_float += i_channels;
if( ++(p_thread->i_cur_sample) == 512 )
{
addPCM( p_thread->p_data );
p_thread->i_cur_sample = 0;
}
}
}
/*****************************************************************************
* Thread:
*****************************************************************************/
static void* Thread( vlc_object_t *p_this )
{
galaktos_thread_t *p_thread = (galaktos_thread_t*)p_this;
int count=0;
double realfps=0,fpsstart=0;
int timed=0;
int timestart=0;
int mspf=0;
int canc = vlc_savecancel ();
/* Get on OpenGL provider */
p_thread->p_opengl =
(vout_thread_t *)vlc_object_create( p_this, sizeof( vout_thread_t ) );
if( p_thread->p_opengl == NULL )
{
vlc_restorecancel (canc);
return NULL;
}
vlc_object_attach( p_thread->p_opengl, p_this );
/* Initialize vout parameters */
video_format_Setup( &p_thread->p_opengl->fmt_in,
VLC_CODEC_RGB32, p_thread->i_width, p_thread->i_height, 1 );
p_thread->p_opengl->i_window_width = p_thread->i_width;
p_thread->p_opengl->i_window_height = p_thread->i_height;
p_thread->p_opengl->render.i_width = p_thread->i_width;
p_thread->p_opengl->render.i_height = p_thread->i_width;
p_thread->p_opengl->render.i_aspect = VOUT_ASPECT_FACTOR;
p_thread->p_opengl->b_fullscreen = false;
p_thread->p_opengl->i_alignment = 0;
p_thread->p_opengl->fmt_in.i_sar_num = 1;
p_thread->p_opengl->fmt_in.i_sar_den = 1;
p_thread->p_opengl->fmt_render = p_thread->p_opengl->fmt_in;
p_thread->p_module =
module_need( p_thread->p_opengl, "opengl provider", NULL, false );
if( p_thread->p_module == NULL )
{
msg_Err( p_thread, "unable to initialize OpenGL" );
vlc_object_detach( p_thread->p_opengl );
vlc_object_release( p_thread->p_opengl );
vlc_restorecancel (canc);
return NULL;
}
p_thread->p_opengl->pf_init( p_thread->p_opengl );
setup_opengl( p_thread->i_width, p_thread->i_height );
CreateRenderTarget(512, &RenderTargetTextureID, NULL);
timestart=mdate()/1000;
while( vlc_object_alive (p_thread) )
{
mspf = 1000 / 60;
if( galaktos_update( p_thread ) == 1 )
{
vlc_object_kill( p_thread );
}
free( p_thread->psz_title );
p_thread->psz_title = NULL;
mtime_t now = mdate();
if (++count%100==0)
{
realfps=100/((now/1000-fpsstart)/1000);
// printf("%f\n",realfps);
fpsstart=now/1000;
}
//framerate limiter
timed=mspf-(now/1000-timestart);
// printf("%d,%d\n",time,mspf);
if (timed>0) msleep(1000*timed);
// printf("Limiter %d\n",(mdate()/1000-timestart));
timestart=mdate()/1000;
}
/* Free the openGL provider */
module_unneed( p_thread->p_opengl, p_thread->p_module );
vlc_object_detach( p_thread->p_opengl );
vlc_object_release( p_thread->p_opengl );
vlc_restorecancel (canc);
return NULL;
}
/*****************************************************************************
* Close: close the plugin
*****************************************************************************/
static void Close( vlc_object_t *p_this )
{
aout_filter_t *p_filter = (aout_filter_t *)p_this;
aout_filter_sys_t *p_sys = p_filter->p_sys;
/* Stop galaktos Thread */
vlc_object_kill( p_sys->p_thread );
galaktos_done( p_sys->p_thread );
vlc_thread_join( p_sys->p_thread );
/* Free data */
vlc_object_detach( p_sys->p_thread );
vlc_object_release( p_sys->p_thread );
free( p_sys );
}
static char *TitleGet( vlc_object_t *p_this )
{
char *psz_title = NULL;
input_thread_t *p_input =
vlc_object_find( p_this, VLC_OBJECT_INPUT, FIND_ANYWHERE );
if( p_input )
{
char *psz_orig = input_item_GetURI( input_GetItem( p_input ) );
char *psz = strrchr( psz_orig, '/' );
if( psz )
{
psz++;
}
else
{
psz = psz_orig;
}
if( psz && *psz )
{
psz_title = strdup( psz );
}
free( psz_orig );
vlc_object_release( p_input );
}
return psz_title;
}
/*****************************************************************************
* plugin.h:
*****************************************************************************
* Copyright (C) 2004 the VideoLAN team
* $Id$
*
* Authors: Cyril Deguet <asmax@videolan.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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifndef _GALAKTOS_PLUGIN_H_
#define _GALAKTOS_PLUGIN_H_
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <vlc_common.h>
#include <vlc_aout.h>
#include <vlc_vout.h>
#define MAX_BLOCKS 10
typedef struct
{
VLC_COMMON_MEMBERS
char *psz_title;
/* OpenGL provider */
vout_thread_t *p_opengl;
module_t *p_module;
/* Window properties */
int i_width;
int i_height;
int b_fullscreen;
/* Audio properties */
int i_channels;
/* Audio buffer */
int16_t p_data[2][512];
int i_cur_sample;
/* OS specific data */
void *p_os_data;
} galaktos_thread_t;
#endif
/*****************************************************************************
* preset.c:
*****************************************************************************
* Copyright (C) 2004 the VideoLAN team
* $Id$
*
* Authors: Cyril Deguet <asmax@videolan.org>
* code from projectM http://xmms-projectm.sourceforge.net
*
* 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc_common.h>
#include <vlc_charset.h>
#include <stdlib.h>
#include <stdio.h>
#include <dirent.h>
#include <time.h>
#include "common.h"
#include "fatal.h"
#include "preset_types.h"
#include "preset.h"
#include "parser.h"
#include "expr_types.h"
#include "eval.h"
#include "splaytree_types.h"
#include "splaytree.h"
#include "tree_types.h"
#include "per_frame_eqn_types.h"
#include "per_frame_eqn.h"
#include "per_pixel_eqn_types.h"
#include "per_pixel_eqn.h"
#include "init_cond_types.h"
#include "init_cond.h"
#include "param_types.h"
#include "param.h"
#include "func_types.h"
#include "func.h"
#include "custom_wave_types.h"
#include "custom_wave.h"
#include "custom_shape_types.h"
#include "custom_shape.h"
#include "idle_preset.h"
/* The maximum number of preset names loaded into buffer */
#define MAX_PRESETS_IN_DIR 50000
extern int per_frame_eqn_count;
extern int per_frame_init_eqn_count;
//extern int custom_per_frame_eqn_count;
extern splaytree_t * builtin_param_tree;
preset_t * active_preset = NULL;
preset_t * idle_preset = NULL;
FILE * write_stream = NULL;
int preset_index = -1;
int preset_name_buffer_size = 0;
splaytree_t * chrono_order_preset_name_tree = NULL;
int get_preset_path(char ** preset_path_ptr, char * filepath, char * filename);
preset_t * load_preset(char * pathname);
int is_valid_extension(char * name);
int load_preset_file(char * pathname, preset_t * preset);
int close_preset(preset_t * preset);
int write_preset_name(FILE * fs);
int write_per_pixel_equations(FILE * fs);
int write_per_frame_equations(FILE * fs);
int write_per_frame_init_equations(FILE * fs);
int write_init_conditions(FILE * fs);
void load_init_cond(param_t * param);
void load_init_conditions();
void write_init(init_cond_t * init_cond);
int init_idle_preset();
int destroy_idle_preset();
void load_custom_wave_init_conditions();
void load_custom_wave_init(custom_wave_t * custom_wave);
void load_custom_shape_init_conditions();
void load_custom_shape_init(custom_shape_t * custom_shape);
/* loadPresetDir: opens the directory buffer
denoted by 'dir' to load presets */
int loadPresetDir(char * dir) {
struct dirent ** name_list;
char * preset_name;
int i, j, dir_size;
if (dir == NULL)
return ERROR;
if (chrono_order_preset_name_tree != NULL) {
if (PRESET_DEBUG) printf("loadPresetDir: previous directory doesn't appear to be closed!\n");
/* Let this slide for now */
}
/* Scan the entire directory, storing each entry in a dirent struct array that needs
to be freed later. For more information, consult scandir(3) in the man pages */
if ((dir_size = scandir(dir, &name_list, 0, alphasort)) < 0) {
if (PRESET_DEBUG) printf("loadPresetDir: failed to open directory \"%s\"\n", dir);
return ERROR;
}
chrono_order_preset_name_tree = create_splaytree(compare_int, copy_int, free_int);
/* Iterate through entire dirent name list, adding to the preset name list if it
is valid */
for (i = 0; ((i < dir_size) && (i < MAX_PRESETS_IN_DIR));i++) {
/* Only perform the next set of operations if the preset name
contains a valid extension */
if (is_valid_extension(name_list[i]->d_name)) {
/* Handle the out of memory case. My guess is xmms would
crash before this program would, but whatever...*/
if ((preset_name = (char*)malloc(MAX_PATH_SIZE)) == NULL) {
if (PRESET_DEBUG) printf("loadPresetDir: out of memory! \n");
/* Free the rest of the dirent name list */
for (j = i; j < dir_size; j++)
free(name_list[j]);
destroy_splaytree(chrono_order_preset_name_tree);
return OUTOFMEM_ERROR;
}
/* Now create the full path */
if (get_preset_path(&preset_name, dir, name_list[i]->d_name) < 0) {
if (PRESET_DEBUG) printf("loadPresetDir: failed to generate full preset path name!\n");
/* Free the rest of the dirent name list */
for (j = i; j < dir_size; j++)
free(name_list[j]);
destroy_splaytree(chrono_order_preset_name_tree);
return OUTOFMEM_ERROR;
}
/* Insert the character string into the splay tree, with the key being its sequence number */
splay_insert(preset_name, &preset_name_buffer_size, chrono_order_preset_name_tree);
preset_name_buffer_size++;
}
/* Free the dirent struct */
free(name_list[i]);
}
free(name_list);
/* No valid files in directory! */
if (chrono_order_preset_name_tree->root == NULL) {
if (PRESET_DEBUG) printf("loadPresetDir: no valid files in directory \"%s\"\n", dir);
destroy_splaytree(chrono_order_preset_name_tree);
chrono_order_preset_name_tree = NULL;
return FAILURE;
}
/* Start the prefix index right before the first entry, so next preset
starts at the top of the list */
preset_index = -1;
/* Start the first preset */
switchPreset(ALPHA_NEXT, HARD_CUT);
return SUCCESS;
}
/* closePresetDir: closes the current
preset directory buffer */
int closePresetDir() {
/* No preset director appears to be loaded */
if (chrono_order_preset_name_tree == NULL)
return SUCCESS;
if (PRESET_DEBUG) {
printf("closePresetDir: freeing directory buffer...");
fflush(stdout);
}
/* Free each entry in the directory preset name tree */
splay_traverse(free_int, chrono_order_preset_name_tree);
/* Destroy the chronological order splay tree */
destroy_splaytree(chrono_order_preset_name_tree);
chrono_order_preset_name_tree = NULL;
preset_name_buffer_size = 0;
if (PRESET_DEBUG) printf("finished\n");
return SUCCESS;
}
/* Converts a preset file name to a full path */
int get_preset_path(char ** preset_path_ptr, char * filepath, char * filename) {
char * preset_path;
/* An insanely paranoid sequence of argument checks */
if (preset_path_ptr == NULL)
return ERROR;
if (*preset_path_ptr == NULL)
return ERROR;
if (filename == NULL)
return ERROR;
if (filepath == NULL)
return ERROR;
/* Mostly here for looks */
preset_path = *preset_path_ptr;
/* Clear the name space first */
memset(preset_path, 0, MAX_PATH_SIZE);
/* Now create the string "PATH/FILENAME", where path is either absolute or relative location
of the .milk file, and filename is the name of the preset file itself */
strcat(
strcat(
strncpy(
preset_path,
filepath,
MAX_PATH_SIZE-1),
"/"),
filename);
return SUCCESS;
}
/* switchPreset: loads the next preset from the directory stream.
loadPresetDir() must be called first. This is a
sequential load function */
int switchPreset(switch_mode_t switch_mode, int cut_type) {
preset_t * new_preset;
int switch_index;
/* Make sure a preset directory list is in the buffer */
if (chrono_order_preset_name_tree == NULL) {
if (PRESET_DEBUG) printf("switchPreset: it helps if you open a directory first with a loadPresetDir() call\n");
return ERROR;
}
switch (switch_mode) {
case ALPHA_NEXT:
/* An index variable that iterates through the directory
buffer, doing wrap around when it reaches the end of
the buffer */
if (preset_index == (preset_name_buffer_size - 1))
switch_index = preset_index = 0;
else
switch_index = ++preset_index;
break;
case ALPHA_PREVIOUS:
if (preset_index == 0)
switch_index = preset_index = preset_name_buffer_size - 1;
else
switch_index = --preset_index;
break;
case RANDOM_NEXT:
switch_index = (int) (preset_name_buffer_size*(rand()/(RAND_MAX+1.0)));
break;
case RESTART_ACTIVE:
switch_index = preset_index;
break;
default:
return FAILURE;
}
/* Finally, load the preset using its actual path */
if ((new_preset = load_preset((char*)splay_find(&switch_index, chrono_order_preset_name_tree))) == NULL) {
if (PRESET_DEBUG) printf("switchPreset: failed to load preset\n");
return ERROR;
}
/* Closes a preset currently loaded, if any */
if ((active_preset != NULL) && (active_preset != idle_preset))
close_preset(active_preset);
/* Sets global active_preset pointer */
active_preset = new_preset;
/* Reinitialize the engine variables to sane defaults */
reset_engine_vars();
/* Add any missing initial conditions */
load_init_conditions();
/* Add any missing initial conditions for each wave */
load_custom_wave_init_conditions();
/* Add any missing initial conditions for each shape */
load_custom_shape_init_conditions();
/* Need to evaluate the initial conditions once */
evalInitConditions();
// evalInitPerFrameEquations();
return SUCCESS;
}
/* Loads a specific preset by absolute path */
int loadPresetByFile(char * filename) {
preset_t * new_preset;
/* Finally, load the preset using its actual path */
if ((new_preset = load_preset(filename)) == NULL) {
if (PRESET_DEBUG) printf("loadPresetByFile: failed to load preset!\n");
return ERROR;
}
/* Closes a preset currently loaded, if any */
if ((active_preset != NULL) && (active_preset != idle_preset))
close_preset(active_preset);
/* Sets active preset global pointer */
active_preset = new_preset;
/* Reinitialize engine variables */
reset_engine_vars();
/* Add any missing initial conditions for each wave */
load_custom_wave_init_conditions();
/* Add any missing initial conditions for each wave */
load_custom_shape_init_conditions();
/* Add any missing initial conditions */
load_init_conditions();
/* Need to do this once for menu */
evalInitConditions();
// evalPerFrameInitEquations();
return SUCCESS;
}
int init_idle_preset() {
preset_t * preset;
/* Initialize idle preset struct */
if ((preset = (preset_t*)malloc(sizeof(preset_t))) == NULL)
return FAILURE;
strncpy(preset->name, "idlepreset", strlen("idlepreset"));
/* Initialize equation trees */
preset->init_cond_tree = create_splaytree(compare_string, copy_string, free_string);
preset->user_param_tree = create_splaytree(compare_string, copy_string, free_string);
preset->per_frame_eqn_tree = create_splaytree(compare_int, copy_int, free_int);
preset->per_pixel_eqn_tree = create_splaytree(compare_int, copy_int, free_int);
preset->per_frame_init_eqn_tree = create_splaytree(compare_string, copy_string, free_string);
preset->custom_wave_tree = create_splaytree(compare_int, copy_int, free_int);
preset->custom_shape_tree = create_splaytree(compare_int, copy_int, free_int);
/* Set file path to dummy name */
strncpy(preset->file_path, "IDLE PRESET", MAX_PATH_SIZE-1);
/* Set initial index values */
preset->per_pixel_eqn_string_index = 0;
preset->per_frame_eqn_string_index = 0;
preset->per_frame_init_eqn_string_index = 0;
memset(preset->per_pixel_flag, 0, sizeof(int)*NUM_OPS);
/* Clear string buffers */
memset(preset->per_pixel_eqn_string_buffer, 0, STRING_BUFFER_SIZE);
memset(preset->per_frame_eqn_string_buffer, 0, STRING_BUFFER_SIZE);
memset(preset->per_frame_init_eqn_string_buffer, 0, STRING_BUFFER_SIZE);
idle_preset = preset;
return SUCCESS;
}
int destroy_idle_preset() {
return close_preset(idle_preset);
}
/* initPresetLoader: initializes the preset
loading library. this should be done before
any parsing */
int initPresetLoader() {
/* Initializes the builtin parameter database */
init_builtin_param_db();
/* Initializes the builtin function database */
init_builtin_func_db();
/* Initializes all infix operators */
init_infix_ops();
/* Set the seed to the current time in seconds */
srand(time(NULL));
/* Initialize the 'idle' preset */
init_idle_preset();
reset_engine_vars();
active_preset = idle_preset;
load_init_conditions();
/* Done */
if (PRESET_DEBUG) printf("initPresetLoader: finished\n");
return SUCCESS;
}
/* Sort of experimental code here. This switches
to a hard coded preset. Useful if preset directory
was not properly loaded, or a preset fails to parse */
void switchToIdlePreset() {
/* Idle Preset already activated */
if (active_preset == idle_preset)
return;
/* Close active preset */
if (active_preset != NULL)
close_preset(active_preset);
/* Sets global active_preset pointer */
active_preset = idle_preset;
/* Reinitialize the engine variables to sane defaults */
reset_engine_vars();
/* Add any missing initial conditions */
load_init_conditions();
/* Need to evaluate the initial conditions once */
evalInitConditions();
}
/* destroyPresetLoader: closes the preset
loading library. This should be done when
projectM does cleanup */
int destroyPresetLoader() {
if ((active_preset != NULL) && (active_preset != idle_preset)) {
close_preset(active_preset);
}
active_preset = NULL;
destroy_idle_preset();
destroy_builtin_param_db();
destroy_builtin_func_db();
destroy_infix_ops();
return SUCCESS;
}
/* load_preset_file: private function that loads a specific preset denoted
by the given pathname */
int load_preset_file(char * pathname, preset_t * preset) {
FILE * fs;
int retval;
if (pathname == NULL)
return FAILURE;
if (preset == NULL)
return FAILURE;
/* Open the file corresponding to pathname */
if ((fs = utf8_fopen(pathname, "r")) == NULL) {
if (PRESET_DEBUG) printf("load_preset_file: loading of file %s failed!\n", pathname);
return ERROR;
}
if (PRESET_DEBUG) printf("load_preset_file: file stream \"%s\" opened successfully\n", pathname);
/* Parse any comments */
if (parse_top_comment(fs) < 0) {
if (PRESET_DEBUG) printf("load_preset_file: no left bracket found...\n");
fclose(fs);
return FAILURE;
}
/* Parse the preset name and a left bracket */
if (parse_preset_name(fs, preset->name) < 0) {
if (PRESET_DEBUG) printf("load_preset_file: loading of preset name in file \"%s\" failed\n", pathname);
fclose(fs);
return ERROR;
}
if (PRESET_DEBUG) printf("load_preset_file: preset \"%s\" parsed\n", preset->name);
/* Parse each line until end of file */
if (PRESET_DEBUG) printf("load_preset_file: beginning line parsing...\n");
while ((retval = parse_line(fs, preset)) != EOF) {
if (retval == PARSE_ERROR) {
if (PRESET_DEBUG > 1) printf("load_preset_file: parse error in file \"%s\"\n", pathname);
}
}
if (PRESET_DEBUG) printf("load_preset_file: finished line parsing successfully\n");
/* Now the preset has been loaded.
Evaluation calls can be made at appropiate
times in the frame loop */
fclose(fs);
if (PRESET_DEBUG) printf("load_preset_file: file \"%s\" closed, preset ready\n", pathname);
return SUCCESS;
}
void evalInitConditions() {
splay_traverse(eval_init_cond, active_preset->init_cond_tree);
splay_traverse(eval_init_cond, active_preset->per_frame_init_eqn_tree);
}
void evalPerFrameEquations() {
splay_traverse(eval_per_frame_eqn, active_preset->per_frame_eqn_tree);
}
void evalPerFrameInitEquations() {
//printf("evalPerFrameInitEquations: per frame init unimplemented!\n");
// splay_traverse(eval_per_frame_eqn, active_preset->per_frame_init_eqn_tree);
}
/* Returns nonzero if string 'name' contains .milk or
(the better) .prjm extension. Not a very strong function currently */
int is_valid_extension(char * name) {
if (PRESET_DEBUG > 1) {
printf("is_valid_extension: scanning string \"%s\"...", name);
fflush(stdout);
}
if (strstr(name, MILKDROP_FILE_EXTENSION)) {
if (PRESET_DEBUG > 1) printf("\".milk\" extension found in string [true]\n");
return TRUE;
}
if (strstr(name, PROJECTM_FILE_EXTENSION)) {
if (PRESET_DEBUG > 1) printf("\".prjm\" extension found in string [true]\n");
return TRUE;
}
if (PRESET_DEBUG > 1) printf("no valid extension found [false]\n");
return FALSE;
}
/* Private function to close a preset file */
int close_preset(preset_t * preset) {
if (preset == NULL)
return FAILURE;
splay_traverse(free_init_cond, preset->init_cond_tree);
destroy_splaytree(preset->init_cond_tree);
splay_traverse(free_init_cond, preset->per_frame_init_eqn_tree);
destroy_splaytree(preset->per_frame_init_eqn_tree);
splay_traverse(free_per_pixel_eqn, preset->per_pixel_eqn_tree);
destroy_splaytree(preset->per_pixel_eqn_tree);
splay_traverse(free_per_frame_eqn, preset->per_frame_eqn_tree);
destroy_splaytree(preset->per_frame_eqn_tree);
splay_traverse(free_param, preset->user_param_tree);
destroy_splaytree(preset->user_param_tree);
splay_traverse(free_custom_wave, preset->custom_wave_tree);
destroy_splaytree(preset->custom_wave_tree);
splay_traverse(free_custom_shape, preset->custom_shape_tree);
destroy_splaytree(preset->custom_shape_tree);
free(preset);
return SUCCESS;
}
void reloadPerPixel(char *s, preset_t * preset) {
FILE * fs;
int slen;
char c;
int i;
if (s == NULL)
return;
if (preset == NULL)
return;
/* Clear previous per pixel equations */
splay_traverse(free_per_pixel_eqn, preset->per_pixel_eqn_tree);
destroy_splaytree(preset->per_pixel_eqn_tree);
preset->per_pixel_eqn_tree = create_splaytree(compare_int, copy_int, free_int);
/* Convert string to a stream */
fs = fmemopen (s, strlen(s), "r");
while ((c = fgetc(fs)) != EOF) {
ungetc(c, fs);
parse_per_pixel_eqn(fs, preset);
}
fclose(fs);
/* Clear string space */
memset(preset->per_pixel_eqn_string_buffer, 0, STRING_BUFFER_SIZE);
/* Compute length of string */
slen = strlen(s);
/* Copy new string into buffer */
strncpy(preset->per_pixel_eqn_string_buffer, s, slen);
/* Yet again no bounds checking */
preset->per_pixel_eqn_string_index = slen;
/* Finished */
return;
}
/* Obviously unwritten */
void reloadPerFrameInit(char *s, preset_t * preset) {
}
void reloadPerFrame(char * s, preset_t * preset) {
FILE * fs;
int slen;
char c;
int eqn_count = 1;
per_frame_eqn_t * per_frame;
if (s == NULL)
return;
if (preset == NULL)
return;
/* Clear previous per frame equations */
splay_traverse(free_per_frame_eqn, preset->per_frame_eqn_tree);
destroy_splaytree(preset->per_frame_eqn_tree);
preset->per_frame_eqn_tree = create_splaytree(compare_int, copy_int, free_int);
/* Convert string to a stream */
fs = fmemopen (s, strlen(s), "r");
while ((c = fgetc(fs)) != EOF) {
ungetc(c, fs);
if ((per_frame = parse_per_frame_eqn(fs, eqn_count, preset)) != NULL) {
splay_insert(per_frame, &eqn_count, preset->per_frame_eqn_tree);
eqn_count++;
}
}
fclose(fs);
/* Clear string space */
memset(preset->per_frame_eqn_string_buffer, 0, STRING_BUFFER_SIZE);
/* Compute length of string */
slen = strlen(s);
/* Copy new string into buffer */
strncpy(preset->per_frame_eqn_string_buffer, s, slen);
/* Yet again no bounds checking */
preset->per_frame_eqn_string_index = slen;
/* Finished */
printf("reloadPerFrame: %d eqns parsed succesfully\n", eqn_count-1);
return;
}
preset_t * load_preset(char * pathname) {
preset_t * preset;
/* Initialize preset struct */
if ((preset = (preset_t*)malloc(sizeof(preset_t))) == NULL)
return NULL;
/* Initialize equation trees */
preset->init_cond_tree = create_splaytree(compare_string, copy_string, free_string);
preset->user_param_tree = create_splaytree(compare_string, copy_string, free_string);
preset->per_frame_eqn_tree = create_splaytree(compare_int, copy_int, free_int);
preset->per_pixel_eqn_tree = create_splaytree(compare_int, copy_int, free_int);
preset->per_frame_init_eqn_tree = create_splaytree(compare_string, copy_string, free_string);
preset->custom_wave_tree = create_splaytree(compare_int, copy_int, free_int);
preset->custom_shape_tree = create_splaytree(compare_int, copy_int, free_int);
memset(preset->per_pixel_flag, 0, sizeof(int)*NUM_OPS);
/* Copy file path */
strncpy(preset->file_path, pathname, MAX_PATH_SIZE-1);
/* Set initial index values */
preset->per_pixel_eqn_string_index = 0;
preset->per_frame_eqn_string_index = 0;
preset->per_frame_init_eqn_string_index = 0;
/* Clear string buffers */
memset(preset->per_pixel_eqn_string_buffer, 0, STRING_BUFFER_SIZE);
memset(preset->per_frame_eqn_string_buffer, 0, STRING_BUFFER_SIZE);
memset(preset->per_frame_init_eqn_string_buffer, 0, STRING_BUFFER_SIZE);
if (load_preset_file(pathname, preset) < 0) {
if (PRESET_DEBUG) printf("load_preset: failed to load file \"%s\"\n", pathname);
close_preset(preset);
return NULL;
}
/* It's kind of ugly to reset these values here. Should definitely be placed in the parser somewhere */
per_frame_eqn_count = 0;
per_frame_init_eqn_count = 0;
/* Finished, return new preset */
return preset;
}
void savePreset(char * filename) {
FILE * fs;
if (filename == NULL)
return;
/* Open the file corresponding to pathname */
if ((fs = utf8_fopen(filename, "w+")) == NULL) {
if (PRESET_DEBUG) printf("savePreset: failed to create filename \"%s\"!\n", filename);
return;
}
write_stream = fs;
if (write_preset_name(fs) < 0) {
write_stream = NULL;
fclose(fs);
return;
}
if (write_init_conditions(fs) < 0) {
write_stream = NULL;
fclose(fs);
return;
}
if (write_per_frame_init_equations(fs) < 0) {
write_stream = NULL;
fclose(fs);
return;
}
if (write_per_frame_equations(fs) < 0) {
write_stream = NULL;
fclose(fs);
return;
}
if (write_per_pixel_equations(fs) < 0) {
write_stream = NULL;
fclose(fs);
return;
}
write_stream = NULL;
fclose(fs);
}
int write_preset_name(FILE * fs) {
char s[256];
int len;
memset(s, 0, 256);
if (fs == NULL)
return FAILURE;
/* Format the preset name in a string */
sprintf(s, "[%s]\n", active_preset->name);
len = strlen(s);
/* Write preset name to file stream */
if (fwrite(s, 1, len, fs) != len)
return FAILURE;
return SUCCESS;
}
int write_init_conditions(FILE * fs) {
if (fs == NULL)
return FAILURE;
if (active_preset == NULL)
return FAILURE;
splay_traverse(write_init, active_preset->init_cond_tree);
return SUCCESS;
}
void write_init(init_cond_t * init_cond) {
char s[512];
int len;
if (write_stream == NULL)
return;
memset(s, 0, 512);
if (init_cond->param->type == P_TYPE_BOOL)
sprintf(s, "%s=%d\n", init_cond->param->name, init_cond->init_val.bool_val);
else if (init_cond->param->type == P_TYPE_INT)
sprintf(s, "%s=%d\n", init_cond->param->name, init_cond->init_val.int_val);
else if (init_cond->param->type == P_TYPE_DOUBLE)
{
lldiv_t div = lldiv( init_cond->init_val.double_val * 1000000,1000000 );
sprintf(s, "%s=%"PRId64".%06u\n", init_cond->param->name, div.quot,
(unsigned int) div.rem );
}
else { printf("write_init: unknown parameter type!\n"); return; }
len = strlen(s);
if ((fwrite(s, 1, len, write_stream)) != len)
printf("write_init: failed writing to file stream! Out of disk space?\n");
}
int write_per_frame_init_equations(FILE * fs) {
int len;
if (fs == NULL)
return FAILURE;
if (active_preset == NULL)
return FAILURE;
len = strlen(active_preset->per_frame_init_eqn_string_buffer);
if (fwrite(active_preset->per_frame_init_eqn_string_buffer, 1, len, fs) != len)
return FAILURE;
return SUCCESS;
}
int write_per_frame_equations(FILE * fs) {
int len;
if (fs == NULL)
return FAILURE;
if (active_preset == NULL)
return FAILURE;
len = strlen(active_preset->per_frame_eqn_string_buffer);
if (fwrite(active_preset->per_frame_eqn_string_buffer, 1, len, fs) != len)
return FAILURE;
return SUCCESS;
}
int write_per_pixel_equations(FILE * fs) {
int len;
if (fs == NULL)
return FAILURE;
if (active_preset == NULL)
return FAILURE;
len = strlen(active_preset->per_pixel_eqn_string_buffer);
if (fwrite(active_preset->per_pixel_eqn_string_buffer, 1, len, fs) != len)
return FAILURE;
return SUCCESS;
}
void load_init_conditions() {
splay_traverse(load_init_cond, builtin_param_tree);
}
void load_init_cond(param_t * param) {
init_cond_t * init_cond;
value_t init_val;
/* Don't count read only parameters as initial conditions */
if (param->flags & P_FLAG_READONLY)
return;
/* If initial condition was not defined by the preset file, force a default one
with the following code */
if ((init_cond = splay_find(param->name, active_preset->init_cond_tree)) == NULL) {
/* Make sure initial condition does not exist in the set of per frame initial equations */
if ((init_cond = splay_find(param->name, active_preset->per_frame_init_eqn_tree)) != NULL)
return;
if (param->type == P_TYPE_BOOL)
init_val.bool_val = 0;
else if (param->type == P_TYPE_INT)
init_val.int_val = *(int*)param->engine_val;
else if (param->type == P_TYPE_DOUBLE)
init_val.double_val = *(double*)param->engine_val;
//printf("%s\n", param->name);
/* Create new initial condition */
if ((init_cond = new_init_cond(param, init_val)) == NULL)
return;
/* Insert the initial condition into this presets tree */
if (splay_insert(init_cond, init_cond->param->name, active_preset->init_cond_tree) < 0) {
free_init_cond(init_cond);
return;
}
}
}
void load_custom_wave_init_conditions() {
splay_traverse(load_custom_wave_init, active_preset->custom_wave_tree);
}
void load_custom_wave_init(custom_wave_t * custom_wave) {
load_unspecified_init_conds(custom_wave);
}
void load_custom_shape_init_conditions() {
splay_traverse(load_custom_shape_init, active_preset->custom_shape_tree);
}
void load_custom_shape_init(custom_shape_t * custom_shape) {
load_unspecified_init_conds_shape(custom_shape);
}
#ifndef PRESET_H
#define PRESET_H
#define PRESET_DEBUG 0 /* 0 for no debugging, 1 for normal, 2 for insane */
#define HARD_CUT 0
#define SOFT_CUT 1
#include "preset_types.h"
void evalInitConditions();
void evalPerFrameEquations();
void evalPerFrameInitEquations();
int switchPreset(switch_mode_t switch_mode, int cut_type);
void switchToIdlePreset();
int loadPresetDir(char * dir);
int closePresetDir();
int initPresetLoader();
int destroyPresetLoader();
int loadPresetByFile(char * filename);
void reloadPerFrame(char * s, preset_t * preset);
void reloadPerFrameInit(char *s, preset_t * preset);
void reloadPerPixel(char *s, preset_t * preset);
void savePreset(char * name);
#endif
#ifndef PRESET_TYPES_H
#define PRESET_TYPES_H
#include "splaytree_types.h"
#include "expr_types.h"
#include "per_pixel_eqn_types.h"
typedef enum {
ALPHA_NEXT,
ALPHA_PREVIOUS,
RANDOM_NEXT,
RESTART_ACTIVE,
} switch_mode_t;
typedef struct PRESET_T {
char name[MAX_TOKEN_SIZE]; /* preset name as parsed in file */
char file_path[MAX_PATH_SIZE]; /* Points to the preset file name */
int per_pixel_eqn_string_index;
int per_frame_eqn_string_index;
int per_frame_init_eqn_string_index;
int per_pixel_flag[NUM_OPS];
char per_pixel_eqn_string_buffer[STRING_BUFFER_SIZE];
char per_frame_eqn_string_buffer[STRING_BUFFER_SIZE];
char per_frame_init_eqn_string_buffer[STRING_BUFFER_SIZE];
/* Data structures that contain equation and initial condition information */
splaytree_t * per_frame_eqn_tree; /* per frame equations */
splaytree_t * per_pixel_eqn_tree; /* per pixel equation tree */
gen_expr_t * per_pixel_eqn_array[NUM_OPS]; /* per pixel equation array */
splaytree_t * per_frame_init_eqn_tree; /* per frame initial equations */
splaytree_t * init_cond_tree; /* initial conditions */
splaytree_t * user_param_tree; /* user parameter splay tree */
splaytree_t * custom_wave_tree; /* custom wave forms for this preset */
splaytree_t * custom_shape_tree; /* custom shapes for this preset */
} preset_t;
#endif
/*****************************************************************************
* splaytree.c:
*****************************************************************************
* Copyright (C) 2004 the VideoLAN team
* $Id$
*
* Authors: Cyril Deguet <asmax@videolan.org>
* code from projectM http://xmms-projectm.sourceforge.net
*
* 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*
An implementation of top-down splaying
D. Sleator <sleator@cs.cmu.edu>
March 1992
"Splay trees", or "self-adjusting search trees" are a simple and
efficient data structure for storing an ordered set. The data
structure consists of a binary tree, without parent pointers, and no
additional fields. It allows searching, insertion, deletion,
deletemin, deletemax, splitting, joining, and many other operations,
all with amortized logarithmic performance. Since the trees adapt to
the sequence of requests, their performance on real access patterns is
typically even better. Splay trees are described in a number of texts
and papers [1,2,3,4,5].
The code here is adapted from simple top-down splay, at the bottom of
page 669 of [3]. It can be obtained via anonymous ftp from
spade.pc.cs.cmu.edu in directory /usr/sleator/public.
The chief modification here is that the splay operation works even if the
item being splayed is not in the tree, and even if the tree root of the
tree is NULL. So the line:
t = splay(i, t);
causes it to search for item with key i in the tree rooted at t. If it's
there, it is splayed to the root. If it isn't there, then the node put
at the root is the last one before NULL that would have been reached in a
normal binary search for i. (It's a neighbor of i in the tree.) This
allows many other operations to be easily implemented, as shown below.
[1] "Fundamentals of data structures in C", Horowitz, Sahni,
and Anderson-Freed, Computer Science Press, pp 542-547.
[2] "Data Structures and Their Algorithms", Lewis and Denenberg,
Harper Collins, 1991, pp 243-251.
[3] "Self-adjusting Binary Search Trees" Sleator and Tarjan,
JACM Volume 32, No 3, July 1985, pp 652-686.
[4] "Data Structure and Algorithm Analysis", Mark Weiss,
Benjamin Cummins, 1992, pp 119-130.
[5] "Data Structures, Algorithms, and Performance", Derick Wood,
Addison-Wesley, 1993, pp 367-375.
The following code was written by Daniel Sleator, and is released
in the public domain. It has been heavily modified by Carmelo Piccione,
(cep@andrew.cmu.edu), to suit personal needs,
*/
#include <stdlib.h>
#include <stdio.h>
#include "common.h"
#include "fatal.h"
#include "splaytree_types.h"
#include "splaytree.h"
splaynode_t * splay (void * key, splaynode_t * t, int * match_type, int (*compare)());
int free_splaynode(splaynode_t * splaynode, void (*free_key)());
void splay_traverse_helper (void (*func_ptr)(), splaynode_t * splaynode);
splaynode_t * splay_delete_helper(void * key, splaynode_t * t, int (*compare)(), void (*free_key)());
void splay_find_above_min_helper(void * max_key, void ** closest_key, splaynode_t * root, int (*compare)());
void splay_find_below_max_helper(void * max_key, void ** closest_key, splaynode_t * root, int (*compare)());
splaynode_t * new_splaynode(int type, void * key, void * data);
int splay_insert_node(splaynode_t * splaynode, splaytree_t * splaytree);
int splay_rec_size(splaynode_t * splaynode);
/* Creates a splay tree given a compare key function, copy key function, and free key function.
Ah yes, the wonders of procedural programming */
splaytree_t * create_splaytree(int (*compare)(), void * (*copy_key)(), void (*free_key)()) {
splaytree_t * splaytree;
/* Allocate memory for the splaytree struct */
if ((splaytree = (splaytree_t*)malloc(sizeof(splaytree_t))) == NULL)
return NULL;
/* Set struct entries */
splaytree->root = NULL;
splaytree->compare = compare;
splaytree->copy_key = copy_key;
splaytree->free_key = free_key;
/* Return instantiated splay tree */
return splaytree;
}
/* Destroys a splay tree */
int destroy_splaytree(splaytree_t * splaytree) {
/* Null argument check */
if (splaytree == NULL)
return FAILURE;
/* Recursively free all splaynodes in tree */
free_splaynode(splaytree->root, splaytree->free_key);
/* Free the splaytree struct itself */
free(splaytree);
/* Done, return success */
return SUCCESS;
}
/* Recursively free all the splaynodes */
int free_splaynode(splaynode_t * splaynode, void (*free_key)()) {
/* Ok if this happens, a recursive base case */
if (splaynode == NULL)
return SUCCESS;
/* Free left node */
free_splaynode(splaynode->left, free_key);
/* Free right node */
free_splaynode(splaynode->right, free_key);
/* Free this node's key */
free_key(splaynode->key);
/* Note that the data pointers are not freed here.
Should be freed with a splay traversal function */
/* Free the splaynode structure itself */
free(splaynode);
/* Finished, return success */
return SUCCESS;
}
/* Traverses the entire splay tree with the given function func_ptr */
void splay_traverse(void (*func_ptr)(), splaytree_t * splaytree) {
/* Null argument check */
if (splaytree == NULL)
return;
if (func_ptr == NULL)
return;
/* Call recursive helper function */
splay_traverse_helper(func_ptr, splaytree->root);
return;
}
/* Helper function to traverse the entire splaytree */
void splay_traverse_helper (void (*func_ptr)(), splaynode_t * splaynode) {
/* Normal if this happens, its a base case of recursion */
if (splaynode == NULL)
return;
/* Recursively traverse to the left */
splay_traverse_helper(func_ptr, splaynode->left);
/* Node is a of regular type, so its ok to perform the function on it */
if (splaynode->type == REGULAR_NODE_TYPE)
func_ptr(splaynode->data);
/* Node is of symbolic link type, do nothing */
else if (splaynode->type == SYMBOLIC_NODE_TYPE)
;
/* Unknown node type */
else
;
/* Recursively traverse to the right */
splay_traverse_helper(func_ptr, splaynode->right);
/* Done */
return;
}
/* Find the node corresponding to the given key in splaytree, return its data pointer */
void * splay_find(void * key, splaytree_t * splaytree) {
splaynode_t * splaynode;
int match_type;
if (key == NULL)
return NULL;
if (splaytree == NULL)
return NULL;
splaynode = splaytree->root;
/* Bring the targeted splay node to the top of the splaytree */
splaynode = splay(key, splaynode, &match_type, splaytree->compare);
splaytree->root = splaynode;
/* We only want perfect matches, so return null when match isn't perfect */
if (match_type == CLOSEST_MATCH)
return NULL;
/* This shouldn't happen because of the match type check, but whatever */
if (splaytree->root == NULL)
return NULL;
/* Node is a regular type, return its data pointer */
if (splaytree->root->type == REGULAR_NODE_TYPE) /* regular node */
return splaytree->root->data;
/* If the node is a symlink, pursue one link */
if (splaytree->root->type == SYMBOLIC_NODE_TYPE) /* symbolic node */
return ((splaynode_t*)splaytree->root->data)->data;
/* Unknown type */
return NULL;
}
/* Gets the splaynode that the given key points to */
splaynode_t * get_splaynode_of(void * key, splaytree_t * splaytree) {
splaynode_t * splaynode;
int match_type;
/* Null argument checks */
if (splaytree == NULL)
return NULL;
if (key == NULL)
return NULL;
splaynode = splaytree->root;
/* Find the splaynode */
splaynode = splay(key, splaynode, &match_type, splaytree->compare);
splaytree->root = splaynode;
/* Only perfect matches are valid */
if (match_type == CLOSEST_MATCH)
return NULL;
/* Return the perfect match splay node */
return splaynode;
}
/* Finds the desired node, and changes the tree such that it is the root */
splaynode_t * splay (void * key, splaynode_t * t, int * match_type, int (*compare)()) {
/* Simple top down splay, not requiring key to be in the tree t.
What it does is described above. */
splaynode_t N, *l, *r, *y;
*match_type = CLOSEST_MATCH;
if (t == NULL) return t;
N.left = N.right = NULL;
l = r = &N;
for (;;) {
if (compare(key, t->key) < 0) {
if (t->left == NULL) break;
if (compare(key, t->left->key) < 0) {
y = t->left; /* rotate right */
t->left = y->right;
y->right = t;
t = y;
if (t->left == NULL) break;
}
r->left = t; /* link right */
r = t;
t = t->left;
} else if (compare(key, t->key) > 0) {
if (t->right == NULL) break;
if (compare(key, t->right->key) > 0) {
y = t->right; /* rotate left */
t->right = y->left;
y->left = t;
t = y;
if (t->right == NULL) break;
}
l->right = t; /* link left */
l = t;
t = t->right;
} else {
*match_type = PERFECT_MATCH;
break;
}
}
l->right = t->left; /* assemble */
r->left = t->right;
t->left = N.right;
t->right = N.left;
return t;
//return NULL;
}
/* Deletes a splay node from a splay tree. If the node doesn't exist
then nothing happens */
int splay_delete(void * key, splaytree_t * splaytree) {
splaynode_t * splaynode;
/* Use helper function to delete the node and return the resulting tree */
if ((splaynode = splay_delete_helper(key, splaytree->root, splaytree->compare, splaytree->free_key)) == NULL)
return FAILURE;
/* Set new splaytree root equal to the returned splaynode after deletion */
splaytree->root = splaynode;
/* Finished, no errors */
return SUCCESS;
}
/* Deletes a splay node */
splaynode_t * splay_delete_helper(void * key, splaynode_t * splaynode, int (*compare)(), void (*free_key)()) {
splaynode_t * new_root;
int match_type;
/* Argument check */
if (splaynode == NULL)
return NULL;
splaynode = splay(key, splaynode, &match_type, compare);
/* If entry wasn't found, quit here */
if (match_type == CLOSEST_MATCH)
return NULL;
/* If the targeted node's left pointer is null, then set the new root
equal to the splaynode's right child */
if (splaynode->left == NULL) {
new_root = splaynode->right;
}
/* Otherwise, do something I don't currently understand */
else {
new_root = splay(key, splaynode->left, &match_type, compare);
new_root->right = splaynode->right;
}
/* Set splay nodes children pointers to null */
splaynode->left = splaynode->right = NULL;
/* Free the splaynode (and only this node since its children are now empty */
free_splaynode(splaynode, free_key);
/* Return the resulting tree */
return new_root;
}
/* Create a new splay node type */
splaynode_t * new_splaynode(int type, void * key, void * data) {
splaynode_t * splaynode;
/* Argument checks */
if (data == NULL)
return NULL;
if (key == NULL)
return NULL;
/* Creates the new splay node struct */
if ((splaynode = (splaynode_t*)malloc(sizeof(splaynode_t))) == NULL)
return NULL;
splaynode->data = data;
splaynode->type = type;
splaynode->key = key;
/* Return the new splay node */
return splaynode;
}
/* Inserts a link into the splay tree */
int splay_insert_link(const void * alias_key, void * orig_key, splaytree_t * splaytree) {
splaynode_t * splaynode, * data_node;
void * key_clone;
/* Null arguments */
if (splaytree == NULL)
return FAILURE;
if (alias_key == NULL)
return FAILURE;
if (orig_key == NULL)
return FAILURE;
/* Find the splaynode corresponding to the original key */
if ((data_node = get_splaynode_of(orig_key, splaytree)) == NULL)
return FAILURE;
/* Create a new splay node of symbolic link type */
if ((splaynode = new_splaynode(SYMBOLIC_NODE_TYPE, (key_clone = splaytree->copy_key(alias_key)), data_node)) == NULL) {
splaytree->free_key(key_clone);
return OUTOFMEM_ERROR;
}
/* Insert the splaynode into the given splaytree */
if ((splay_insert_node(splaynode, splaytree)) < 0) {
splaynode->left=splaynode->right = NULL;
free_splaynode(splaynode, splaytree->free_key);
return FAILURE;
}
/* Done, return success */
return SUCCESS;
}
/* Inserts 'data' into the 'splaytree' paired with the passed 'key' */
int splay_insert(void * data, void * key, splaytree_t * splaytree) {
splaynode_t * splaynode;
void * key_clone;
/* Null argument checks */
if (splaytree == NULL) {
return FAILURE;
}
if (key == NULL)
return FAILURE;
/* Clone the key argument */
key_clone = splaytree->copy_key(key);
/* Create a new splaynode (of regular type) */
if ((splaynode = new_splaynode(REGULAR_NODE_TYPE, key_clone, data)) == NULL) {
splaytree->free_key(key_clone);
return OUTOFMEM_ERROR;
}
/* Inserts the splaynode into the splaytree */
if (splay_insert_node(splaynode, splaytree) < 0) {
splaynode->left=splaynode->right=NULL;
free_splaynode(splaynode, splaytree->free_key);
return FAILURE;
}
return SUCCESS;
}
/* Helper function to insert splaynodes into the splaytree */
int splay_insert_node(splaynode_t * splaynode, splaytree_t * splaytree) {
int match_type;
int cmpval;
void * key;
splaynode_t * t;
/* Null argument checks */
if (splaytree == NULL)
return FAILURE;
if (splaynode == NULL)
return FAILURE;
key = splaynode->key;
t = splaytree->root;
/* Root is null, insert splaynode here */
if (t == NULL) {
splaynode->left = splaynode->right = NULL;
splaytree->root = splaynode;
return SUCCESS;
}
t = splay(key, t, &match_type, splaytree->compare);
if ((cmpval = splaytree->compare(key,t->key)) < 0) {
splaynode->left = t->left;
splaynode->right = t;
t->left = NULL;
splaytree->root = splaynode;
return SUCCESS;
}
else if (cmpval > 0) {
splaynode->right = t->right;
splaynode->left = t;
t->right = NULL;
splaytree->root = splaynode;
return SUCCESS;
}
/* Item already exists in tree, don't reinsert */
else {
return FAILURE;
}
}
/* Returns the 'maximum' key that is less than the given key in the splaytree */
void * splay_find_below_max(void * key, splaytree_t * splaytree) {
void * closest_key;
if (splaytree == NULL)
return NULL;
if (splaytree->root == NULL)
return NULL;
if (key == NULL)
return NULL;
closest_key = NULL;
splay_find_below_max_helper(key, &closest_key, splaytree->root, splaytree->compare);
if (closest_key == NULL) return NULL;
return splay_find(closest_key, splaytree);
}
/* Returns the 'minimum' key that is greater than the given key in the splaytree */
void * splay_find_above_min(void * key, splaytree_t * splaytree) {
void * closest_key;
if (splaytree == NULL)
return NULL;
if (splaytree->root == NULL)
return NULL;
if (key == NULL)
return NULL;
closest_key = NULL;
splay_find_above_min_helper(key, &closest_key, splaytree->root, splaytree->compare);
if (closest_key == NULL) {
return NULL;
}
return splay_find(closest_key, splaytree);
}
/* Helper function */
void splay_find_below_max_helper(void * min_key, void ** closest_key, splaynode_t * root, int (*compare)()) {
/* Empty root, return*/
if (root == NULL)
return;
/* The root key is less than the previously found closest key.
Also try to make the key non null if the value is less than the max key */
if ((*closest_key == NULL) || (compare(root->key, *closest_key) < 0)) {
/* The root key is less than the given max key, so this is the
smallest change from the given max key */
if (compare(root->key, min_key) > 0) {
*closest_key = root->key;
/* Look right again in case even a greater key exists that is
still less than the given max key */
splay_find_below_max_helper(min_key, closest_key, root->left, compare);
}
/* The root key is greater than the given max key, and greater than
the closest key, so search left */
else {
splay_find_below_max_helper(min_key, closest_key, root->right, compare);
}
}
/* The root key is less than the found closest key, search right */
else {
splay_find_below_max_helper(min_key, closest_key, root->left, compare);
}
}
/* Helper function */
void splay_find_above_min_helper(void * max_key, void ** closest_key, splaynode_t * root, int (*compare)()) {
/* Empty root, stop */
if (root == NULL)
return;
/* The root key is greater than the previously found closest key.
Also try to make the key non null if the value is less than the min key */
if ((*closest_key == NULL) || (compare(root->key, *closest_key) > 0)) {
/* The root key is greater than the given min key, so this is the
smallest change from the given min key */
if (compare(root->key, max_key) < 0) {
*closest_key = root->key;
/* Look left again in case even a smaller key exists that is
still greater than the given min key */
splay_find_above_min_helper(max_key, closest_key, root->right, compare);
}
/* The root key is less than the given min key, and less than
the closest key, so search right */
else {
splay_find_above_min_helper(max_key, closest_key, root->left, compare);
}
}
/* The root key is greater than the found closest key, search left */
else {
splay_find_above_min_helper(max_key, closest_key, root->right, compare);
}
}
/* Find the minimum entry of the splay tree */
void * splay_find_min(splaytree_t * t) {
splaynode_t * splaynode;
if (t == NULL)
return NULL;
if (t->root == NULL)
return NULL;
splaynode = t->root;
while (splaynode->left != NULL)
splaynode= splaynode->left;
return splaynode->data;
}
/* Find the maximum entry of the splay tree */
void * splay_find_max(splaytree_t * t) {
splaynode_t * splaynode;
if (t == NULL)
return NULL;
if (t->root == NULL)
return NULL;
splaynode = t->root;
while (splaynode->right != NULL) {
printf("data:%d\n", *(int*)splaynode->key);
splaynode = splaynode->right;
}
return splaynode->data;
}
int splay_size(splaytree_t * t) {
if (t == NULL)
return 0;
if (t->root == NULL)
return 0;
return splay_rec_size(t->root);
}
int splay_rec_size(splaynode_t * splaynode) {
if (!splaynode)
return 0;
return 1 + splay_rec_size(splaynode->left) + splay_rec_size(splaynode->right);
}
#ifndef SPLAYTREE_H
#define SPLAYTREE_H
#define REGULAR_NODE_TYPE 0
#define SYMBOLIC_NODE_TYPE 1
#define PERFECT_MATCH 0
#define CLOSEST_MATCH 1
void * splay_find(void * key, splaytree_t * t);
int splay_insert(void * data, void * key, splaytree_t * t);
int splay_insert_link(const void * alias_key, void * orig_key, splaytree_t * splaytree);
int splay_delete(void * key, splaytree_t * splaytree);
int splay_size(splaytree_t * t);
splaytree_t * create_splaytree(int (*compare)(), void * (*copy_key)(), void (*free_key)());
int destroy_splaytree(splaytree_t * splaytree);
void splay_traverse(void (*func_ptr)(), splaytree_t * splaytree);
splaynode_t * get_splaynode_of(void * key, splaytree_t * splaytree);
void * splay_find_above_min(void * key, splaytree_t * root);
void * splay_find_below_max(void * key, splaytree_t * root);
void * splay_find_min(splaytree_t * t);
void * splay_find_max(splaytree_t * t);
#endif
#ifndef SPLAYTREE_TYPES_H
#define SPLAYTREE_TYPES_H
typedef struct SPLAYNODE_T {
int type;
struct SPLAYNODE_T * left, * right;
void * data;
void * key;
} splaynode_t;
typedef struct SPLAYTREE_T {
splaynode_t * root;
int (*compare)();
void * (*copy_key)();
void (*free_key)();
} splaytree_t;
#endif
/*****************************************************************************
* tree_types.c:
*****************************************************************************
* Copyright (C) 2004 the VideoLAN team
* $Id$
*
* Authors: Cyril Deguet <asmax@videolan.org>
* code from projectM http://xmms-projectm.sourceforge.net
*
* 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "common.h"
/* Compares integer value numbers in 32 bit range */
int compare_int(int * num1, int * num2) {
if ((*num1) < (*num2))
return -1;
if ((*num1) > (*num2))
return 1;
return 0;
}
/* Compares strings in lexographical order */
int compare_string(char * str1, char * str2) {
// printf("comparing \"%s\" to \"%s\"\n", str1, str2);
//return strcmp(str1, str2);
return strncmp(str1, str2, MAX_TOKEN_SIZE-1);
}
/* Compares a string in version order. That is, file1 < file2 < file10 */
int compare_string_version(char * str1, char * str2) {
return strverscmp(str1, str2);
}
void free_int(void * num) {
free(num);
}
void free_string(char * string) {
free(string);
}
void * copy_int(int * num) {
int * new_num;
if ((new_num = (int*)malloc(sizeof(int))) == NULL)
return NULL;
*new_num = *num;
return (void*)new_num;
}
void * copy_string(char * string) {
char * new_string;
if ((new_string = (char*)malloc(MAX_TOKEN_SIZE)) == NULL)
return NULL;
strncpy(new_string, string, MAX_TOKEN_SIZE-1);
return (void*)new_string;
}
int compare_int(char * num1, char * num2);
int compare_string(char * str1, char * str2);
void free_int(int * num);
void free_string(char * string);
void * copy_int(int * num);
void * copy_string(char * string);
void * compare_string_version(char * str1, char * str2);
/*****************************************************************************
* video_init.c:
*****************************************************************************
* Copyright (C) 2004 the VideoLAN team
* $Id$
*
* Authors: Cyril Deguet <asmax@videolan.org>
* code from projectM http://xmms-projectm.sourceforge.net
*
* 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
//video_init.c - SDL/Opengl Windowing Creation/Resizing Functions
//
//by Peter Sperl
//
//Opens an SDL Window and creates an OpenGL session
//also able to handle resizing and fullscreening of windows
//just call init_display again with differant variables
#include <stdlib.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include "video_init.h"
extern int texsize;
extern char *buffer;
void setup_opengl( int w, int h )
{
/* Our shading model--Gouraud (smooth). */
glShadeModel( GL_SMOOTH);
/* Culling. */
// glCullFace( GL_BACK );
// glFrontFace( GL_CCW );
// glEnable( GL_CULL_FACE );
/* Set the clear color. */
glClearColor( 0, 0, 0, 0 );
/* Setup our viewport. */
glViewport( 0, 0, w, h );
/*
* Change to the projection matrix and set
* our viewing volume.
*/
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
// gluOrtho2D(0.0, (GLfloat) width, 0.0, (GLfloat) height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// glFrustum(0.0, height, 0.0,width,10,40);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glDrawBuffer(GL_BACK);
glReadBuffer(GL_BACK);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_POINT_SMOOTH);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
// glCopyTexImage2D(GL_TEXTURE_2D,0,GL_RGB,0,0,texsize,texsize,0);
//glCopyTexSubImage2D(GL_TEXTURE_2D,0,0,0,0,0,texsize,texsize);
glLineStipple(2, 0xAAAA);
}
void CreateRenderTarget(int texsize,int *RenderTargetTextureID, int *RenderTarget )
{
/* Create the texture that will be bound to the render target */
glGenTextures(1, RenderTargetTextureID);
glBindTexture(GL_TEXTURE_2D, *RenderTargetTextureID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
#if 0
/* Create the render target */
*RenderTarget = SDL_GL_CreateRenderTarget(texsize,texsize, NULL);
if ( *RenderTarget ) {
int value;
//printf("Created render target:\n");
SDL_GL_GetRenderTargetAttribute( *RenderTarget, SDL_GL_RED_SIZE, &value );
// printf( "SDL_GL_RED_SIZE: %d\n", value);
SDL_GL_GetRenderTargetAttribute( *RenderTarget, SDL_GL_GREEN_SIZE, &value );
// printf( "SDL_GL_GREEN_SIZE: %d\n", value);
SDL_GL_GetRenderTargetAttribute( *RenderTarget, SDL_GL_BLUE_SIZE, &value );
// printf( "SDL_GL_BLUE_SIZE: %d\n", value);
SDL_GL_GetRenderTargetAttribute( *RenderTarget, SDL_GL_ALPHA_SIZE, &value );
// printf( "SDL_GL_ALPHA_SIZE: %d\n", value);
SDL_GL_GetRenderTargetAttribute( *RenderTarget, SDL_GL_DEPTH_SIZE, &value );
// printf( "SDL_GL_DEPTH_SIZE: %d\n", value );
SDL_GL_BindRenderTarget(*RenderTarget, *RenderTargetTextureID);
} else {
#endif
/* We can fake a render target in this demo by rendering to the
* screen and copying to a texture before we do normal rendering.
*/
buffer = malloc(3*texsize*texsize);
glBindTexture(GL_TEXTURE_2D, *RenderTargetTextureID);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGB,
texsize, texsize,
0,
GL_RGB,
GL_UNSIGNED_BYTE,
buffer);
// }
}
void setup_opengl( int w, int h );
void CreateRenderTarget(int texsize,int *RenderTargetTextureID, int *RenderTarget);
...@@ -1278,61 +1278,6 @@ modules/video_output/xcb/window.c ...@@ -1278,61 +1278,6 @@ modules/video_output/xcb/window.c
modules/video_output/xcb/x11.c modules/video_output/xcb/x11.c
modules/video_output/xcb/xvideo.c modules/video_output/xcb/xvideo.c
modules/video_output/yuv.c modules/video_output/yuv.c
modules/visualization/galaktos/PCM.c
modules/visualization/galaktos/PCM.h
modules/visualization/galaktos/beat_detect.c
modules/visualization/galaktos/beat_detect.h
modules/visualization/galaktos/builtin_funcs.h
modules/visualization/galaktos/common.h
modules/visualization/galaktos/compare.h
modules/visualization/galaktos/custom_shape.c
modules/visualization/galaktos/custom_shape.h
modules/visualization/galaktos/custom_shape_types.h
modules/visualization/galaktos/custom_wave.c
modules/visualization/galaktos/custom_wave.h
modules/visualization/galaktos/custom_wave_types.h
modules/visualization/galaktos/engine_vars.c
modules/visualization/galaktos/engine_vars.h
modules/visualization/galaktos/eval.c
modules/visualization/galaktos/eval.h
modules/visualization/galaktos/expr_types.h
modules/visualization/galaktos/fatal.h
modules/visualization/galaktos/fftsg.c
modules/visualization/galaktos/fftsg.h
modules/visualization/galaktos/func.c
modules/visualization/galaktos/func.h
modules/visualization/galaktos/func_types.h
modules/visualization/galaktos/idle_preset.h
modules/visualization/galaktos/init_cond.c
modules/visualization/galaktos/init_cond.h
modules/visualization/galaktos/init_cond_types.h
modules/visualization/galaktos/interface_types.h
modules/visualization/galaktos/main.c
modules/visualization/galaktos/main.h
modules/visualization/galaktos/param.c
modules/visualization/galaktos/param.h
modules/visualization/galaktos/param_types.h
modules/visualization/galaktos/parser.c
modules/visualization/galaktos/parser.h
modules/visualization/galaktos/per_frame_eqn.c
modules/visualization/galaktos/per_frame_eqn.h
modules/visualization/galaktos/per_frame_eqn_types.h
modules/visualization/galaktos/per_pixel_eqn.c
modules/visualization/galaktos/per_pixel_eqn.h
modules/visualization/galaktos/per_pixel_eqn_types.h
modules/visualization/galaktos/per_point_types.h
modules/visualization/galaktos/plugin.c
modules/visualization/galaktos/plugin.h
modules/visualization/galaktos/preset.c
modules/visualization/galaktos/preset.h
modules/visualization/galaktos/preset_types.h
modules/visualization/galaktos/splaytree.c
modules/visualization/galaktos/splaytree.h
modules/visualization/galaktos/splaytree_types.h
modules/visualization/galaktos/tree_types.c
modules/visualization/galaktos/tree_types.h
modules/visualization/galaktos/video_init.c
modules/visualization/galaktos/video_init.h
modules/visualization/goom.c modules/visualization/goom.c
modules/visualization/visual/effects.c modules/visualization/visual/effects.c
modules/visualization/visual/fft.c modules/visualization/visual/fft.c
......
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