allow cascading files to be loaded, fix the filter. Improve stability of output linear. Change a bunch of IIR settings.

This commit is contained in:
cnlohr 2015-01-10 01:44:13 -05:00
parent f3d950c129
commit a377262c80
15 changed files with 227 additions and 99 deletions

View file

@ -19,6 +19,7 @@ struct DPODriver
{ {
int xn; int xn;
int yn; int yn;
int rot90;
int zigzag; int zigzag;
}; };
@ -29,8 +30,8 @@ static void DPOUpdate(void * id, struct NoteFinder*nf)
struct DPODriver * d = (struct DPODriver*)id; struct DPODriver * d = (struct DPODriver*)id;
float cw = ((float)screenx) / d->xn; float cw = ((float)(d->rot90?screeny:screenx)) / d->xn;
float ch = ((float)screeny) / d->yn; float ch = ((float)(d->rot90?screenx:screeny)) / d->yn;
for( y = 0; y < d->yn; y++ ) for( y = 0; y < d->yn; y++ )
for( x = 0; x < d->xn; x++ ) for( x = 0; x < d->xn; x++ )
@ -54,7 +55,11 @@ static void DPOUpdate(void * id, struct NoteFinder*nf)
CNFGColor( OutLEDs[index*3+0] | (OutLEDs[index*3+1] <<8)|(OutLEDs[index*3+2] <<16) ); CNFGColor( OutLEDs[index*3+0] | (OutLEDs[index*3+1] <<8)|(OutLEDs[index*3+2] <<16) );
float dx = (x) * cw; float dx = (x) * cw;
float dy = (y) * ch; float dy = (y) * ch;
CNFGTackRectangle( dx, dy, dx+cw+.5, dy+ch+.5 );
if( d->rot90 )
CNFGTackRectangle( dy, dx, dy+ch+.5, dx+cw+.5 );
else
CNFGTackRectangle( dx, dy, dx+cw+.5, dy+ch+.5 );
} }
CNFGColor( 0xffffff ); CNFGColor( 0xffffff );
} }
@ -66,6 +71,7 @@ static void DPOParams(void * id )
d->xn = 16; RegisterValue( "lightx", PINT, &d->xn, sizeof( d->xn ) ); d->xn = 16; RegisterValue( "lightx", PINT, &d->xn, sizeof( d->xn ) );
d->yn = 9; RegisterValue( "lighty", PINT, &d->yn, sizeof( d->yn ) ); d->yn = 9; RegisterValue( "lighty", PINT, &d->yn, sizeof( d->yn ) );
d->zigzag = 0; RegisterValue( "zigzag", PINT, &d->zigzag, sizeof( d->zigzag ) ); d->zigzag = 0; RegisterValue( "zigzag", PINT, &d->zigzag, sizeof( d->zigzag ) );
d->rot90 = 0; RegisterValue( "rot90", PINT, &d->rot90, sizeof( d->rot90 ) );
} }

View file

@ -1,3 +1,6 @@
//XXX This needs to be re-worked to only output LEDs so DisplayArray can take it.
//XXX CONSIDER DUMPING
#include "outdrivers.h" #include "outdrivers.h"
#include "notefinder.h" #include "notefinder.h"
#include <stdio.h> #include <stdio.h>
@ -11,7 +14,7 @@
//Uses: note_amplitudes2[note] for how many lights to use. //Uses: note_amplitudes2[note] for how many lights to use.
//Uses: note_amplitudes_out[note] for how bright it should be. //Uses: note_amplitudes_out[note] for how bright it should be.
#define MAX_LEDS_PER_NOTE 512 #define MAX_LEDS_PER_NOTE 1024
extern short screenx, screeny; extern short screenx, screeny;
@ -116,7 +119,7 @@ static void DPOUpdate(void * id, struct NoteFinder*nf)
} }
} }
float cw = ((float)screenx) / d->xn; /* float cw = ((float)screenx) / d->xn;
float ch = ((float)screeny) / d->yn; float ch = ((float)screeny) / d->yn;
for( i = 0; i < d->note_peaks; i++ ) for( i = 0; i < d->note_peaks; i++ )
@ -134,7 +137,24 @@ static void DPOUpdate(void * id, struct NoteFinder*nf)
CNFGDrawBox( x, y, x+cw, y+ch ); CNFGDrawBox( x, y, x+cw, y+ch );
} }
}*/
int led = 0;
for( i = 0; i < d->note_peaks; i++ )
{
struct LINote * l = &d->notes[i];
int j;
float sat = nf->note_amplitudes_out[i] * d->satamp;
if( sat > 1 ) sat = 1;
uint32_t color = CCtoHEX( nf->note_positions[i] / nf->freqbins, 1.0, sat );
OutLEDs[led*3+0] = color & 0xff;
OutLEDs[led*3+1] = ( color >> 8 ) & 0xff;
OutLEDs[led*3+2] = ( color >> 16 ) & 0xff;
led++;
} }
} }
static void DPOParams(void * id ) static void DPOParams(void * id )

View file

@ -2,13 +2,16 @@ all : colorchord
RAWDRAW:=DrawFunctions.o XDriver.o RAWDRAW:=DrawFunctions.o XDriver.o
SOUND:=sound.o sound_alsa.o sound_pulse.o sound_null.o SOUND:=sound.o sound_alsa.o sound_pulse.o sound_null.o
OUTS:=LEDOUTDriver.o DisplayOUTDriver.o DisplayShapeDriver.o parameters.o chash.o OUTS := OutputVoronoi.o DisplayArray.o OutputLinear.o DisplayPie.o
#LEDOUTDriver.o DisplayOUTDriver.o
RAWDRAWLIBS:=-lX11 -lm -lpthread -lXinerama -lXext RAWDRAWLIBS:=-lX11 -lm -lpthread -lXinerama -lXext
LDLIBS:=-lpthread -lasound -lm -lpulse-simple -lpulse LDLIBS:=-lpthread -lasound -lm -lpulse-simple -lpulse
CFLAGS:=-g -Os -flto -Wall -ffast-math CFLAGS:=-g -Os -flto -Wall -ffast-math
EXTRALIBS:=-lusb-1.0 EXTRALIBS:=-lusb-1.0
colorchord : os_generic.o main.o dft.o decompose.o filter.o color.o sort.o notefinder.o util.o outdrivers.o $(RAWDRAW) $(SOUND) $(OUTS) colorchord : os_generic.o main.o dft.o decompose.o filter.o color.o sort.o notefinder.o util.o outdrivers.o $(RAWDRAW) $(SOUND) $(OUTS) parameters.o chash.o
gcc -o $@ $^ $(CFLAGS) $(LDLIBS) $(EXTRALIBS) $(RAWDRAWLIBS) gcc -o $@ $^ $(CFLAGS) $(LDLIBS) $(EXTRALIBS) $(RAWDRAWLIBS)

View file

@ -13,8 +13,6 @@
#define MAX_LEDS_PER_NOTE 512 #define MAX_LEDS_PER_NOTE 512
extern short screenx, screeny;
struct LINote struct LINote
{ {
float x, y; //In screen space. float x, y; //In screen space.
@ -64,8 +62,8 @@ static void DPOUpdate(void * id, struct NoteFinder*nf)
{ {
float angle = nf->note_positions[i] / nf->freqbins * 6.28318; float angle = nf->note_positions[i] / nf->freqbins * 6.28318;
// float angle = nf->enduring_note_id[i]; // float angle = nf->enduring_note_id[i];
float cx = screenx/2; float cx = d->xn/2.0;
float cy = screeny/2; float cy = d->yn/2.0;
float tx = sin( angle ) * cx + cx; float tx = sin( angle ) * cx + cx;
float ty = cos( angle ) * cy + cy; float ty = cos( angle ) * cy + cy;
l->x = l->x * .9 + tx * .1; l->x = l->x * .9 + tx * .1;
@ -79,8 +77,8 @@ static void DPOUpdate(void * id, struct NoteFinder*nf)
else else
{ {
srand( nf->enduring_note_id[i] ); srand( nf->enduring_note_id[i] );
l->x = rand()%screenx; l->x = rand()%d->xn;
l->y = rand()%screenx; l->y = rand()%d->yn;
} }
} }
@ -92,17 +90,13 @@ static void DPOUpdate(void * id, struct NoteFinder*nf)
float cw = ((float)screenx) / d->xn;
float ch = ((float)screeny) / d->yn;
int x, y; int x, y;
int led = 0;
for( y = 0; y < d->yn; y++ ) for( y = 0; y < d->yn; y++ )
for( x = 0; x < d->xn; x++ ) for( x = 0; x < d->xn; x++ )
{ {
float lx = (x+.5) * cw; float lx = (x+.5);
float ly = (y+.5) * ch; float ly = (y+.5);
float kx = (x) * cw;
float ky = (y) * ch;
int bestmatch = -1; int bestmatch = -1;
float bestmatchval = 0; float bestmatchval = 0;
@ -126,18 +120,18 @@ static void DPOUpdate(void * id, struct NoteFinder*nf)
} }
} }
uint32_t color = 0;
if( bestmatch != -1 ) if( bestmatch != -1 )
{ {
float sat = nf->note_amplitudes_out[bestmatch] * d->satamp; float sat = nf->note_amplitudes_out[bestmatch] * d->satamp;
if( sat > 1.0 ) sat = 1.0; if( sat > 1.0 ) sat = 1.0;
CNFGColor ( CCtoHEX( nf->note_positions[bestmatch] / nf->freqbins, 1.0, sat ) ); color = CCtoHEX( nf->note_positions[bestmatch] / nf->freqbins, 1.0, sat );
} }
else
{
CNFGColor ( 0 );
}
CNFGTackRectangle( kx, ky, kx+cw, ky+ch );
OutLEDs[led*3+0] = color & 0xff;
OutLEDs[led*3+1] = ( color >> 8 ) & 0xff;
OutLEDs[led*3+2] = ( color >> 16 ) & 0xff;
led++;
} }
CNFGColor ( 0xffffff ); CNFGColor ( 0xffffff );
} }
@ -145,20 +139,22 @@ static void DPOUpdate(void * id, struct NoteFinder*nf)
static void DPOParams(void * id ) static void DPOParams(void * id )
{ {
struct DPODriver * d = (struct DPODriver*)id; struct DPODriver * d = (struct DPODriver*)id;
d->xn = 160; RegisterValue( "lightx", PINT, &d->xn, sizeof( d->xn ) ); printf( "XN: %d\n", d->xn );
//XXX WRONG
d->xn = 160; RegisterValue( "lightx", PINT, &d->xn, sizeof( d->xn ) );
d->yn = 90; RegisterValue( "lighty", PINT, &d->yn, sizeof( d->yn ) ); d->yn = 90; RegisterValue( "lighty", PINT, &d->yn, sizeof( d->yn ) );
d->cutoff = .01; RegisterValue( "shape_cutoff", PFLOAT, &d->cutoff, sizeof( d->cutoff ) ); d->cutoff = .01; RegisterValue( "Voronoi_cutoff", PFLOAT, &d->cutoff, sizeof( d->cutoff ) );
d->satamp = 5; RegisterValue( "satamp", PFLOAT, &d->satamp, sizeof( d->satamp ) ); d->satamp = 5; RegisterValue( "satamp", PFLOAT, &d->satamp, sizeof( d->satamp ) );
d->amppow = 2.51; RegisterValue( "amppow", PFLOAT, &d->amppow, sizeof( d->amppow ) ); d->amppow = 2.51; RegisterValue( "amppow", PFLOAT, &d->amppow, sizeof( d->amppow ) );
d->distpow = 1.5; RegisterValue( "distpow", PFLOAT, &d->distpow, sizeof( d->distpow ) ); d->distpow = 1.5; RegisterValue( "distpow", PFLOAT, &d->distpow, sizeof( d->distpow ) );
d->from_sides = 1.5;RegisterValue( "fromsides", PINT, &d->from_sides, sizeof( d->from_sides ) ); d->from_sides = 1; RegisterValue( "fromsides", PINT, &d->from_sides, sizeof( d->from_sides ) );
d->note_peaks = 0; d->note_peaks = 0;
} }
static struct DriverInstances * DisplayShapeDriver(const char * parameters) static struct DriverInstances * OutputVoronoi(const char * parameters)
{ {
struct DriverInstances * ret = malloc( sizeof( struct DriverInstances ) ); struct DriverInstances * ret = malloc( sizeof( struct DriverInstances ) );
struct DPODriver * d = ret->id = malloc( sizeof( struct DPODriver ) ); struct DPODriver * d = ret->id = malloc( sizeof( struct DPODriver ) );
@ -169,6 +165,6 @@ static struct DriverInstances * DisplayShapeDriver(const char * parameters)
return ret; return ret;
} }
REGISTER_OUT_DRIVER(DisplayShapeDriver); REGISTER_OUT_DRIVER(OutputVoronoi);

5
TODO
View file

@ -1,8 +1,11 @@
Still to do: Still to do:
Try this: Try this:
* Separate "LED Selection" from "output" algorithms. * Separate "LED Selection" from "output" algorithms. << Do this by allowing arbitrary Lights Drivers
* For light finding, pick lights off the peaks to get number of lights to use. * For light finding, pick lights off the peaks to get number of lights to use.
* For light shifting (for 1d-looping light systems) shift the centers of the notes, then vernoi between the notes. * For light shifting (for 1d-looping light systems) shift the centers of the notes, then vernoi between the notes.
Brenden:
* Consider running DFT on all channels and mixing results * Consider running DFT on all channels and mixing results

View file

@ -251,7 +251,7 @@ void CNFGTackRectangle( short x1, short y1, short x2, short y2 )
void CNFGTackPoly( RDPoint * points, int verts ) void CNFGTackPoly( RDPoint * points, int verts )
{ {
XFillPolygon(CNFGDisplay, CNFGPixmap, CNFGGC, (XPoint *)points, 3, Convex, CoordModeOrigin ); XFillPolygon(CNFGDisplay, CNFGPixmap, CNFGGC, (XPoint *)points, verts, Convex, CoordModeOrigin );
} }
#endif #endif

View file

@ -7,22 +7,9 @@
#Whether to limit the control loop to ~60ish FPS. #Whether to limit the control loop to ~60ish FPS.
cpu_autolimit = 1 cpu_autolimit = 1
#What display output driver should be used?
displayname = DisplayShapeDriver
#Display Shape Driver parameters
fromsides = 1
lightx = 80
lighty = 45
shape_cutoff = 0.01
satamp = 5.000
amppow = 2.510
distpow = 1.500
#General GUI properties. #General GUI properties.
title = PA Test title = PA Test
set_screenx = 640 set_screenx = 720
set_screeny = 480 set_screeny = 480
#Sound properties. #Sound properties.
@ -41,7 +28,7 @@ sourcename = alsa_output.pci-0000_00_1b.0.analog-stereo.monitor
################################## ##################################
# How much to amplify the incoming signal. # How much to amplify the incoming signal.
amplify = 2.0 amplify = 2.5
# What is the base note? I.e. the lowest note. # What is the base note? I.e. the lowest note.
# Note that it won't have very much impact until an octave up though! # Note that it won't have very much impact until an octave up though!
@ -52,29 +39,43 @@ base_hz = 55.0000
# default_sigma = 1.4000 # default_sigma = 1.4000
# DFT properties for the DFT up top. # DFT properties for the DFT up top.
dft_iir = 0.7000 dft_iir = 0.0
dft_q = 10.0000 dft_q = 20.0000
dft_speedup = 300.0000 dft_speedup = 1000.0000
octaves = 5 octaves = 5
filter_iter = 1 filter_iter = 2
filter_strength = 0.5000 filter_strength = .5
# How many bins per octave to use? # How many bins per octave to use?
freqbins = 24 freqbins = 24
# For the final note information... How much to slack everything? # For the final note information... How much to slack everything?
note_attach_amp_iir = 0.3000 note_attach_amp_iir = 0.3000
note_attach_amp_iir2 = 0.2000 note_attach_amp_iir2 = 0.200
note_attach_freq_iir = 0.4000 note_attach_freq_iir = 0.4000
#How many bins a note can jump from frame to frame to be considered a slide. #How many bins a note can jump from frame to frame to be considered a slide.
#this is used to prevent notes from popping in and out a lot. #this is used to prevent notes from popping in and out a lot.
note_combine_distance = 0.5000 note_combine_distance = 0.5000
note_jumpability = 2.5000 note_jumpability = 1.8000
note_minimum_new_distribution_value = 0.0200 note_minimum_new_distribution_value = 0.0200
note_out_chop = 0.1000 note_out_chop = 0.1000
#=======================================================================
#Outputs
This is a vornoi thing:
outdrivers = DisplayArray, OutputVoronoi
lightx = 72
lighty = 48
fromsides = 1
shape_cutoff = 0.03
satamp = 5.000
amppow = 2.510
distpow = 1.500

View file

@ -2,7 +2,7 @@
#include <math.h> #include <math.h>
#include <string.h> #include <string.h>
/*
void FilterFoldedBinsIIRTWOPASS( float * folded, int bins, float iir ) void FilterFoldedBinsIIRTWOPASS( float * folded, int bins, float iir )
{ {
int i; int i;
@ -33,8 +33,7 @@ void FilterFoldedBinsIIRTWOPASS( float * folded, int bins, float iir )
{ {
folded[i] = v * iir + folded[i] * inv; folded[i] = v * iir + folded[i] * inv;
} }
}*/
}
void FilterFoldedBinsBlob( float * folded, int bins, float strength, int iter ) void FilterFoldedBinsBlob( float * folded, int bins, float strength, int iter )
@ -47,8 +46,10 @@ void FilterFoldedBinsBlob( float * folded, int bins, float strength, int iter )
memcpy( tmp, folded, sizeof( tmp ) ); memcpy( tmp, folded, sizeof( tmp ) );
for( i = 0; i < bins; i++ ) for( i = 0; i < bins; i++ )
{ {
float left = tmp[(i-1+bins)%bins]; // float left = tmp[(i-1+bins)%bins];
float right = tmp[(i-1+bins)%bins]; // float right = tmp[(i-1+bins)%bins];
float right = tmp[(i+bins+1)%bins];
float left = tmp[(i+bins-1)%bins];
folded[i] = folded[i] * (1.-strength) + (left + right) * strength * 0.5; folded[i] = folded[i] * (1.-strength) + (left + right) * strength * 0.5;
} }
} }

View file

@ -3,7 +3,7 @@
//Perform a two-pass filter on the data, circularly. Once right, then left. //Perform a two-pass filter on the data, circularly. Once right, then left.
void FilterFoldedBinsIIRTWOPASS( float * folded, int bins, float strength ); //void FilterFoldedBinsIIRTWOPASS( float * folded, int bins, float strength );
void FilterFoldedBinsBlob( float * folded, int bins, float strength, int iter ); void FilterFoldedBinsBlob( float * folded, int bins, float strength, int iter );

72
main.c
View file

@ -17,6 +17,8 @@
short screenx, screeny; short screenx, screeny;
int gargc; int gargc;
char ** gargv; char ** gargv;
struct DriverInstances * outdriver[MAX_OUT_DRIVERS];
int set_screenx = 640; REGISTER_PARAM( set_screenx, PINT ); int set_screenx = 640; REGISTER_PARAM( set_screenx, PINT );
int set_screeny = 480; REGISTER_PARAM( set_screeny, PINT ); int set_screeny = 480; REGISTER_PARAM( set_screeny, PINT );
@ -68,7 +70,7 @@ void SoundCB( float * out, float * in, int samplesr, int * samplesp, struct Soun
//Load the samples into a ring buffer. Split the channels from interleved to one per buffer. //Load the samples into a ring buffer. Split the channels from interleved to one per buffer.
*samplesp = 0; *samplesp = 0;
int process_channels = (MAX_CHANNELS < channelin)?MAX_CHANNELS:channelin; // int process_channels = (MAX_CHANNELS < channelin)?MAX_CHANNELS:channelin;
int i; int i;
int j; int j;
@ -77,13 +79,13 @@ void SoundCB( float * out, float * in, int samplesr, int * samplesp, struct Soun
if( sample_channel < 0 ) if( sample_channel < 0 )
{ {
float fo = 0; float fo = 0;
for( j = 0; j < process_channels; j++ ) for( j = 0; j < channelin; j++ )
{ {
float f = in[i*channelin+j]; float f = in[i*channelin+j];
if( f < -1 || f > 1 ) continue; if( f < -1 || f > 1 ) continue;
fo += f; fo += f;
} }
fo /= process_channels; fo /= channelin;
sound[soundhead] = fo; sound[soundhead] = fo;
soundhead = (soundhead+1)%SOUNDCBSIZE; soundhead = (soundhead+1)%SOUNDCBSIZE;
@ -144,9 +146,11 @@ void LoadFile( const char * filename )
int main(int argc, char ** argv) int main(int argc, char ** argv)
{ {
// const char * OutDriver = "name=LEDOutDriver;leds=512;light_siding=1.9"; // const char * OutDriver = "name=LEDOutDriver;leds=512;light_siding=1.9";
const char * InitialFile = "default.conf"; const char * InitialFile = 0;
const char * InitialFileDefault = "default.conf";
int i; int i;
double LastFileTime; double LastFileTimeInit = 0;
double LastFileTimeDefault = 0;
gargc = argc; gargc = argc;
gargv = argv; gargv = argv;
@ -156,8 +160,15 @@ int main(int argc, char ** argv)
InitialFile = argv[1]; InitialFile = argv[1];
} }
{ {
LastFileTime = OGGetFileTime( InitialFile ); LastFileTimeDefault = OGGetFileTime( InitialFileDefault );
LoadFile( InitialFileDefault );
}
if( InitialFile )
{
LastFileTimeInit = OGGetFileTime( InitialFile );
LoadFile( InitialFile ); LoadFile( InitialFile );
} }
@ -171,7 +182,35 @@ int main(int argc, char ** argv)
CNFGBGColor = 0x800000; CNFGBGColor = 0x800000;
CNFGDialogColor = 0x444444; CNFGDialogColor = 0x444444;
CNFGSetup( "ColorChord Test", set_screenx, set_screeny ); CNFGSetup( "ColorChord Test", set_screenx, set_screeny );
struct DriverInstances * outdriver = SetupOutDriver( );
char * OutDriverNames = strdup( GetParameterS( "outdrivers", "null" ) );
char * ThisDriver = OutDriverNames;
char * TDStart;
for( i = 0; i < MAX_OUT_DRIVERS; i++ )
{
while( *ThisDriver == ' ' || *ThisDriver == '\t' ) ThisDriver++;
if( !*ThisDriver ) break;
TDStart = ThisDriver;
while( *ThisDriver != 0 && *ThisDriver != ',' )
{
if( *ThisDriver == '\t' || *ThisDriver == ' ' ) *ThisDriver = 0;
ThisDriver++;
}
if( *ThisDriver )
{
*ThisDriver = 0;
ThisDriver++;
}
printf( "Loading: %s\n", TDStart );
outdriver[i] = SetupOutDriver( TDStart );
}
free(OutDriverNames);
//Initialize Sound //Initialize Sound
struct SoundDriver * sd = InitSound( sound_source, &SoundCB ); struct SoundDriver * sd = InitSound( sound_source, &SoundCB );
@ -198,8 +237,10 @@ int main(int argc, char ** argv)
//Done all ColorChord work. //Done all ColorChord work.
VisTimeStart = OGGetAbsoluteTime(); VisTimeStart = OGGetAbsoluteTime();
if( outdriver ) for( i = 0; i < MAX_OUT_DRIVERS; i++ )
outdriver->Func( outdriver->id, nf ); if( outdriver[i] )
outdriver[i]->Func( outdriver[i]->id, nf );
VisTimeEnd = OGGetAbsoluteTime(); VisTimeEnd = OGGetAbsoluteTime();
//Handle outputs. //Handle outputs.
@ -331,10 +372,17 @@ int main(int argc, char ** argv)
OGUSleep( (int)( SecToWait * 1000000 ) ); OGUSleep( (int)( SecToWait * 1000000 ) );
} }
if( OGGetFileTime( InitialFile ) != LastFileTime ) if( OGGetFileTime( InitialFileDefault ) != LastFileTimeDefault ||
(InitialFile && LastFileTimeInit != OGGetFileTime( InitialFile ) ) )
{ {
LastFileTime = OGGetFileTime( InitialFile ); LastFileTimeDefault = OGGetFileTime( InitialFileDefault );
LoadFile( InitialFile ); LoadFile( InitialFileDefault );
if( InitialFile )
{
LastFileTimeInit = OGGetFileTime( InitialFile );
LoadFile( InitialFile );
}
} }
} }

View file

@ -206,6 +206,7 @@ void RunNoteFinder( struct NoteFinder * nf, const float * audio_stream, int head
nf->folded_bins[i] = amp; nf->folded_bins[i] = amp;
} }
//This is here to reduce the number of false-positive hits. It helps remove peaks that are meaningless.
FilterFoldedBinsBlob( nf->folded_bins, freqbins, nf->filter_strength, nf->filter_iter ); FilterFoldedBinsBlob( nf->folded_bins, freqbins, nf->filter_strength, nf->filter_iter );
nf->FilterTime = OGGetAbsoluteTime(); nf->FilterTime = OGGetAbsoluteTime();
@ -328,7 +329,7 @@ void RunNoteFinder( struct NoteFinder * nf, const float * audio_stream, int head
nf->note_amplitudes2[i] = nf->note_amplitudes2[i] * (1.-nf->note_attach_amp_iir2) + nf->note_amplitudes[i] * nf->note_attach_amp_iir2; nf->note_amplitudes2[i] = nf->note_amplitudes2[i] * (1.-nf->note_attach_amp_iir2) + nf->note_amplitudes[i] * nf->note_attach_amp_iir2;
if( nf->note_amplitudes[i] < nf->note_min_amplitude ) if( nf->note_amplitudes2[i] < nf->note_min_amplitude )
{ {
nf->note_amplitudes[i] = 0; nf->note_amplitudes[i] = 0;
nf->note_amplitudes2[i] = 0; nf->note_amplitudes2[i] = 0;

View file

@ -5,6 +5,10 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
unsigned char OutLEDs[MAX_LEDS*3];
int UsedLEDs;
struct OutDriverListElem ODList[MAX_OUT_DRIVERS]; struct OutDriverListElem ODList[MAX_OUT_DRIVERS];
const char OutDriverParameters[MAX_OUT_DRIVER_STRING]; const char OutDriverParameters[MAX_OUT_DRIVER_STRING];
@ -28,13 +32,12 @@ struct DriverInstances * null( )
REGISTER_OUT_DRIVER(null); REGISTER_OUT_DRIVER(null);
struct DriverInstances * SetupOutDriver( ) struct DriverInstances * SetupOutDriver( const char * drivername )
{ {
int i; int i;
const char * p = GetParameterS( "displayname", "null" );
for( i = 0; i < MAX_OUT_DRIVERS; i++ ) for( i = 0; i < MAX_OUT_DRIVERS; i++ )
{ {
if( ODList[i].Name && strcmp( p, ODList[i].Name ) == 0 ) if( ODList[i].Name && strcmp( drivername, ODList[i].Name ) == 0 )
{ {
printf( "Found: %s %p\n", ODList[i].Name, ODList[i].Init ); printf( "Found: %s %p\n", ODList[i].Name, ODList[i].Init );
return ODList[i].Init( ); return ODList[i].Init( );

View file

@ -5,6 +5,12 @@
struct NoteFinder; struct NoteFinder;
#define MAX_LEDS 32678
extern unsigned char OutLEDs[MAX_LEDS*3];
extern int UsedLEDs;
#define MAX_OUT_DRIVERS 64 #define MAX_OUT_DRIVERS 64
#define MAX_OUT_DRIVER_STRING 1024 #define MAX_OUT_DRIVER_STRING 1024

View file

@ -26,10 +26,10 @@ float GetParameterF( const char * name, float defa )
{ {
switch( p->t ) switch( p->t )
{ {
case PFLOAT: return *((float*)p->ptr); case PFLOAT: return *((float*)p->lp->ptr);
case PINT: return *((int*)p->ptr); case PINT: return *((int*)p->lp->ptr);
case PSTRING: case PSTRING:
case PBUFFER: if( p->ptr ) return atof( p->ptr ); case PBUFFER: if( p->lp->ptr ) return atof( p->lp->ptr );
default: break; default: break;
} }
} }
@ -46,10 +46,10 @@ int GetParameterI( const char * name, int defa )
{ {
switch( p->t ) switch( p->t )
{ {
case PFLOAT: return *((float*)p->ptr); case PFLOAT: return *((float*)p->lp->ptr);
case PINT: return *((int*)p->ptr); case PINT: return *((int*)p->lp->ptr);
case PSTRING: case PSTRING:
case PBUFFER: if( p->ptr ) return atoi( p->ptr ); case PBUFFER: if( p->lp->ptr ) return atoi( p->lp->ptr );
default: break; default: break;
} }
} }
@ -67,10 +67,10 @@ const char * GetParameterS( const char * name, const char * defa )
{ {
switch( p->t ) switch( p->t )
{ {
case PFLOAT: snprintf( returnbuffer, sizeof( returnbuffer ), "%0.4f", *((float*)p->ptr) ); return returnbuffer; case PFLOAT: snprintf( returnbuffer, sizeof( returnbuffer ), "%0.4f", *((float*)p->lp->ptr) ); return returnbuffer;
case PINT: snprintf( returnbuffer, sizeof( returnbuffer ), "%d", *((int*)p->ptr) ); return returnbuffer; case PINT: snprintf( returnbuffer, sizeof( returnbuffer ), "%d", *((int*)p->lp->ptr) ); return returnbuffer;
case PSTRING: case PSTRING:
case PBUFFER: return p->ptr; case PBUFFER: return p->lp->ptr;
default: break; default: break;
} }
} }
@ -83,22 +83,41 @@ const char * GetParameterS( const char * name, const char * defa )
static int SetParameter( struct Param * p, const char * str ) static int SetParameter( struct Param * p, const char * str )
{ {
struct LinkedParameter * lp;
lp = p->lp;
switch( p->t ) switch( p->t )
{ {
case PFLOAT: case PFLOAT:
*((float*)p->ptr) = atof( str ); while( lp )
{
*((float*)lp->ptr) = atof( str );
lp = lp->lp;
}
break; break;
case PINT: case PINT:
*((int*)p->ptr) = atoi( str ); while( lp )
{
*((int*)lp->ptr) = atoi( str );
lp = lp->lp;
}
break; break;
case PBUFFER: case PBUFFER:
strncpy( (char*)p->ptr, str, p->size ); while( lp )
if( p->size > 0 ) {
((char*)p->ptr)[p->size-1]= '\0'; strncpy( (char*)lp->ptr, str, p->size );
if( p->size > 0 )
((char*)lp->ptr)[p->size-1]= '\0';
lp = lp->lp;
}
break; break;
case PSTRING: case PSTRING:
free( p->ptr ); while( lp )
p->ptr = strdup( str ); {
free( lp->ptr );
lp->ptr = strdup( str );
lp = lp->lp;
}
break; break;
default: default:
return -1; return -1;
@ -129,8 +148,8 @@ void RegisterValue( const char * name, enum ParamType t, void * ptr, int size )
{ {
fprintf( stderr, "Warning: Orphan parameter %s was not a PSTRING.\n", name ); fprintf( stderr, "Warning: Orphan parameter %s was not a PSTRING.\n", name );
} }
char * orig = p->ptr; char * orig = p->lp->ptr;
p->ptr = ptr; p->lp->ptr = ptr;
p->t = t; p->t = t;
p->size = size; p->size = size;
p->orphan = 0; p->orphan = 0;
@ -143,7 +162,18 @@ void RegisterValue( const char * name, enum ParamType t, void * ptr, int size )
} }
else else
{ {
fprintf( stderr, "Warning: Parameter %s re-registered. Cannot re-register.\n", name ); struct LinkedParameter * lp = p->lp;
if( size != p->size )
{
fprintf( stderr, "Size mismatch: Parameter %s.\n", name );
}
else
{
p->lp = malloc( sizeof( struct LinkedParameter ) );
p->lp->lp = lp;
p->lp->ptr = ptr;
memcpy( p->lp->ptr, p->lp->lp->ptr, size );
}
} }
} }
else else
@ -151,7 +181,9 @@ void RegisterValue( const char * name, enum ParamType t, void * ptr, int size )
struct Param ** n = (struct Param**)HashTableInsert( parameters, name, 1 ); struct Param ** n = (struct Param**)HashTableInsert( parameters, name, 1 );
*n = malloc( sizeof( struct Param ) ); *n = malloc( sizeof( struct Param ) );
(*n)->t = t; (*n)->t = t;
(*n)->ptr = ptr; (*n)->lp = malloc( sizeof( struct LinkedParameter ) );
(*n)->lp->lp = 0;
(*n)->lp->ptr = ptr;
(*n)->orphan = 0; (*n)->orphan = 0;
(*n)->size = size; (*n)->size = size;
(*n)->callback = 0; (*n)->callback = 0;
@ -215,7 +247,9 @@ void SetParametersFromString( const char * string )
*n = malloc( sizeof ( struct Param ) ); *n = malloc( sizeof ( struct Param ) );
(*n)->orphan = 1; (*n)->orphan = 1;
(*n)->t = PSTRING; (*n)->t = PSTRING;
(*n)->ptr = strdup( value ); (*n)->lp = malloc( sizeof( struct LinkedParameter ) );
(*n)->lp->lp = 0;
(*n)->lp->ptr = strdup( value );
(*n)->size = strlen( value ) + 1; (*n)->size = strlen( value ) + 1;
(*n)->callback = 0; (*n)->callback = 0;
} }

View file

@ -22,13 +22,19 @@ struct ParamCallback
struct ParamCallback * next; struct ParamCallback * next;
}; };
struct LinkedParameter
{
void * ptr;
struct LinkedParameter * lp;
};
struct Param struct Param
{ {
char orphan; //If this is set, then this is something that was received from a string, but has no claimed interface. char orphan; //If this is set, then this is something that was received from a string, but has no claimed interface.
//It will be claimed when RegisterValue is called. NOTE: When orphan is set, it must be a malloc'd string. //It will be claimed when RegisterValue is called. NOTE: When orphan is set, it must be a malloc'd string.
enum ParamType t; enum ParamType t;
void * ptr;
int size; int size;
struct LinkedParameter * lp;
struct ParamCallback * callback; struct ParamCallback * callback;
}; };