colorchord/DisplayOUTDriver.c
2015-01-06 22:51:39 -05:00

170 lines
3.6 KiB
C

#include "outdrivers.h"
#include "notefinder.h"
#include <stdio.h>
#include "parameters.h"
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "color.h"
#include "DrawFunctions.h"
//Uses: note_amplitudes2[note] for how many lights to use.
//Uses: note_amplitudes_out[note] for how bright it should be.
#define MAX_LEDS_PER_NOTE 512
extern short screenx, screeny;
struct LINote
{
float ledexp;
float lednrm; //How many LEDs should we have?
int nrleds; //How many LEDs do we have?
int ledids[MAX_LEDS_PER_NOTE];
};
struct DPODriver
{
int xn;
int yn;
float cutoff;
float satamp;
float pow;
int note_peaks;
struct LINote * notes;
int numallocleds;
int unallocleds[MAX_LEDS_PER_NOTE];
};
int GetAnLED( struct DPODriver * d )
{
if( d->numallocleds )
{
return d->unallocleds[--d->numallocleds];
}
int i;
//Okay, now we have to go search for one.
for( i = 0; i < d->note_peaks; i++ )
{
struct LINote * n = &d->notes[i];
if( n->lednrm < n->nrleds && n->nrleds > 0 )
{
return n->ledids[--n->nrleds];
}
}
return -1;
}
static void DPOUpdate(void * id, struct NoteFinder*nf)
{
int i;
struct DPODriver * d = (struct DPODriver*)id;
int tleds = d->xn * d->yn;
if( d->note_peaks != nf->note_peaks )
{
d->note_peaks = nf->note_peaks;
if( d->notes ) free( d->notes );
d->notes = malloc( sizeof( struct LINote ) * nf->note_peaks );
memset( d->notes, 0, sizeof( struct LINote ) * nf->note_peaks );
d->numallocleds = tleds;
for( i = 0; i < d->numallocleds; i++ )
d->unallocleds[i] = i;
}
float totalexp = 0;
for( i = 0; i < d->note_peaks; i++ )
{
struct LINote * l = &d->notes[i];
l->ledexp = pow( nf->note_amplitudes2[i], d->pow ) - d->cutoff;
if( l->ledexp < 0 ) l->ledexp = 0;
totalexp += l->ledexp;
}
for( i = 0; i < d->note_peaks; i++ )
{
struct LINote * l = &d->notes[i];
l->lednrm = l->ledexp * tleds / totalexp;
}
//Relinquish LEDs
for( i = 0; i < d->note_peaks; i++ )
{
struct LINote * l = &d->notes[i];
while( l->lednrm < l->nrleds && l->nrleds > 0 )
{
d->unallocleds[d->numallocleds++] = l->ledids[--l->nrleds];
}
}
//Add LEDs
for( i = 0; i < d->note_peaks; i++ )
{
struct LINote * l = &d->notes[i];
while( l->lednrm > l->nrleds )
{
int led = GetAnLED( d );
if( led < 0 ) break;
l->ledids[l->nrleds++] = led;
}
}
float cw = ((float)screenx) / d->xn;
float ch = ((float)screeny) / d->yn;
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;
CNFGDialogColor = CCtoHEX( nf->note_positions[i] / nf->freqbins, 1.0, sat );
for( j = 0; j < l->nrleds; j++ )
{
int id = l->ledids[j];
float x = (id % d->xn) * cw;
float y = (id / d->xn) * ch;
CNFGDrawBox( x, y, x+cw, y+ch );
}
}
}
static void DPOParams(void * id )
{
struct DPODriver * d = (struct DPODriver*)id;
d->xn = GetParameterI( "lightx", 16 );
d->yn = GetParameterI( "lighty", 9 );
d->cutoff = GetParameterF( "cutoff", .05 );
d->satamp = GetParameterF( "satamp", 3 );
d->pow = GetParameterF( "pow", 2.1 );
d->note_peaks = 0;
if( d->xn * d->yn >= MAX_LEDS_PER_NOTE )
{
fprintf( stderr, "ERROR: Cannot have more lights than %d\n", MAX_LEDS_PER_NOTE );
exit (-1);
}
}
static struct DriverInstances * DisplayOutDriver(const char * parameters)
{
struct DriverInstances * ret = malloc( sizeof( struct DriverInstances ) );
struct DPODriver * d = ret->id = malloc( sizeof( struct DPODriver ) );
memset( d, 0, sizeof( struct DPODriver ) );
ret->Func = DPOUpdate;
ret->Params = DPOParams;
DPOParams( d );
return ret;
}
REGISTER_OUT_DRIVER(DisplayOutDriver);