made progress... getting very close to an embedded colorchord

This commit is contained in:
cnlohr 2015-04-04 02:23:53 -04:00
parent 5e9023c6a0
commit 36a3777522
7 changed files with 152 additions and 50 deletions

View file

@ -32,7 +32,7 @@
//must decrease. Increasing this value makes responses slower. Lower values are
//more responsive.
#ifndef DFTIIR
#define DFTIIR 4
#define DFTIIR 6
#endif
//Everything the integer one buys, except it only calculates 2 octaves worth of notes per audio frame.

View file

@ -101,6 +101,11 @@ void Init()
void HandleFrameInfo()
{
int i, j, k;
uint8_t hitnotes[MAXNOTES];
for( i = 0; i < MAXNOTES; i++ )
{
hitnotes[i] = 0;
}
#ifdef USE_32DFT
uint16_t * strens;
@ -275,10 +280,11 @@ void HandleFrameInfo()
if( marked_note != -1 )
{
if( note_peak_amps[marked_note] <= this )
note_peak_amps[marked_note] = this;
if( note_peak_amps2[marked_note] <= this )
note_peak_amps2[marked_note] = this;
hitnotes[marked_note] = 1;
// if( note_peak_amps[marked_note] <= this )
note_peak_amps[marked_note] = note_peak_amps[marked_note] - (note_peak_amps[marked_note]>>AMP_1_NERFING_BITS) + (this>>AMP_1_NERFING_BITS);
// if( note_peak_amps2[marked_note] <= this )
note_peak_amps2[marked_note] = note_peak_amps2[marked_note] - (note_peak_amps2[marked_note]>>AMP_2_NERFING_BITS) + (this>>AMP_2_NERFING_BITS);
}
}
}
@ -327,7 +333,7 @@ void HandleFrameInfo()
for( i = 0; i < MAXNOTES; i++ )
{
if( note_peak_freqs[i] == 255 ) continue;
if( note_peak_freqs[i] == 255 || hitnotes[i] ) continue;
note_peak_amps[i] -= note_peak_amps[i]>>AMP_1_NERFING_BITS;
note_peak_amps2[i] -= note_peak_amps2[i]>>AMP_2_NERFING_BITS;

View file

@ -17,7 +17,7 @@
//Notes are the individually identifiable notes we receive from the sound.
//We track up to this many at one time. Just because a note may appear to
//vaporize in one frame doesn't mean it is annihilated immediately.
#define MAXNOTES 10
#define MAXNOTES 12
//Determines bit shifts for where notes lie. We represent notes with an uint8_t
//We have to define all of the possible locations on the note line in this.
@ -25,19 +25,22 @@
#define SEMIBITSPERBIN 3
#define NOTERANGE ((1<<SEMIBITSPERBIN)*FIXBPERO)
//This is the amplitude, coming from folded_bins. If the value is below this
//it is considered a non-note.
#define MIN_AMP_FOR_NOTE 64
//If there is detected note this far away from an established note, we will
//then consider this new note the same one as last time, and move the established
//note. This is also used when combining notes. It is this distance times two.
#define MAX_JUMP_DISTANCE 7
#define MAX_JUMP_DISTANCE 5
#define MINIMUM_AMP_FOR_NOTE_TO_DISAPPEAR 32
#define AMP_1_NERFING_BITS 5
#define AMP_2_NERFING_BITS 3
//This is the amplitude, coming from folded_bins. If the value is below this
//it is considered a non-note.
#define MIN_AMP_FOR_NOTE 64
#define MINIMUM_AMP_FOR_NOTE_TO_DISAPPEAR (1<<(AMP_1_NERFING_BITS))
#ifdef USE_32DFT
#include "DFT32.h"

View file

@ -3,7 +3,7 @@
//uint8_t ledArray[NUM_LIN_LEDS]; //Points to which notes correspond to these LEDs
uint8_t ledOut[NUM_LIN_LEDS*3];
void UpdateLinear()
void UpdateLinearLEDs()
{
//Source material:
/*
@ -19,46 +19,85 @@ void UpdateLinear()
uint8_t i;
uint16_t j;
uint32_t total_size_all_notes = 0;
uint16_t porpamps[MAXNOTES]; //LEDs for each corresponding note.
int32_t porpamps[MAXNOTES]; //LEDs for each corresponding note.
uint8_t sorted_note_map[MAXNOTES]; //mapping from which note into the array of notes from the rest of the system.
uint16_t local_peak_amps[MAXNOTES];
uint16_t local_peak_amps2[MAXNOTES];
uint8_t local_note_freq[MAXNOTES];
uint8_t sorted_map_count = 0;
for( i = 0; i < MAXNOTES; i++ )
{
porpamps[i] = 0;
if( note_peak_freqs[i] == 255 ) continue;
total_size_all_notes += note_peak_amps[i];
uint16_t ist = note_peak_amps[i];
if( note_peak_freqs[i] == 255 || ist <= NERF_NOTE_SIZE_VALUE )
{
local_peak_amps[i] = 0;
continue;
}
for( j = 0; j < sorted_map_count; j++ )
{
//TODO SORT ME
}
sorted_map_count++;
}
uint32_t porportional = (total_size_for_all_notes << 8) / NUM_LIN_LEDS;
for( i = 0; i < MAXNOTES; i++ )
{
uint16_t ist = note_peak_amps[i];
porpamps[i] = 0;
if( note_peak_freqs[i] == 255 || ist <= NERF_NOTE_SIZE_VALUE )
{
local_peak_amps[i] = 0;
continue;
}
local_peak_amps[i] = ist - NERF_NOTE_SIZE_VALUE;
total_size_all_notes += local_peak_amps[i];
}
if( total_size_all_notes == 0 )
{
for( j = 0; j < NUM_LIN_LEDS * 3; j++ )
{
ledOut[j] = 0;
}
return;
}
uint32_t porportional = (uint32_t)(NUM_LIN_LEDS<<8)/((uint32_t)total_size_all_notes);
uint16_t total_accounted_leds = 0;
for( i = 0; i < MAXNOTES; i++ )
{
if( note_peak_freqs[i] == 255 ) continue;
porpamps[i] = (note_peak_amps[i] * porportional) >> 8;
porpamps[i] = (local_peak_amps[i] * porportional) >> 8;
total_accounted_leds += porpamps[i];
}
uint16_t total_unaccounted_leds = NUM_LIN_LEDS - total_accounted_leds;
int16_t total_unaccounted_leds = NUM_LIN_LEDS - total_accounted_leds;
for( i = 0; i < MAXNOTES, total_unaccounted_leds; i++ )
for( i = 0; i < MAXNOTES && total_unaccounted_leds; i++ )
{
if( note_peak_freqs[i] == 255 ) continue;
porpamps[i]++;
porpamps[i]++; total_unaccounted_leds--;
}
//Now, we use porpamps to march through the LEDs, coloring them.
j = 0;
for( i = 0; i < MAXNOTES; i++ )
{
while( porpamps[i] )
while( porpamps[i] > 0 )
{
uint16_t amp = note_peak_amps2[i];
uint16_t amp = ((uint32_t)note_peak_amps2[i] * NOTE_FINAL_AMP) >> 8;
if( amp > 255 ) amp = 255;
uint32_t color = ECCtoHEX( note_peak_freqs[i], 255, amp );
ledOut[i*3+0] = ( color >> 0 ) & 0xff;
ledOut[i*3+1] = ( color >> 8 ) & 0xff;
ledOut[i*3+2] = ( color >>16 ) & 0xff;
ledOut[j*3+0] = ( color >> 0 ) & 0xff;
ledOut[j*3+1] = ( color >> 8 ) & 0xff;
ledOut[j*3+2] = ( color >>16 ) & 0xff;
j++;
porpamps[i]--;
}
@ -69,43 +108,46 @@ void UpdateLinear()
uint32_t ECCtoHEX( uint8_t note, uint8_t sat, uint8_t val )
{
uint16_t hue = 0;
uint8_t third = 65535/3;
uint16_t scalednote = note
uint16_t renote = ((uint32_t)note * 65535) / NOTERANGE;
uint16_t third = 65535/3;
uint16_t scalednote = note;
uint32_t renote = ((uint32_t)note * 65536) / NOTERANGE;
//Note is expected to be a vale from 0..(NOTERANGE-1)
//renote goes from 0 to the next one under 65536.
if( renote < third )
{
//Yellow to Red.
hue = (third - renote) >> 1;
}
else if( note < (third>>1) )
else if( renote < (third<<1) )
{
//Red to Blue
hue = (third-renote);
}
else
{
hue = (((65535-renote) * third) >> 1) + (third>>1);
//hue = ((((65535-renote)>>8) * (uint32_t)(third>>8)) >> 1) + (third<<1);
hue = (uint16_t)(((uint32_t)(65536-renote)<<16) / (third<<1)) + (third>>1); // ((((65535-renote)>>8) * (uint32_t)(third>>8)) >> 1) + (third<<1);
}
hue >>= 8;
// printf( "%d;", hue );
return EHSVtoHEX( hue, sat, val );
}
uint32_t EHSVtoHEX( uint8_t hue, uint8_t sat, uint8_t val )
{
#define SIXTH1 43
#define SIXTH2 85
#define SIXTH3 128
#define SIXTH4 171
#define SIXTH5 213
#define SIXTH1 43
#define SIXTH2 85
#define SIXTH3 128
#define SIXTH4 171
#define SIXTH5 213
uint16_t or = 0, og = 0, ob = 0;
hue += SIXTH2; //Off by 60 degrees.
hue -= SIXTH1; //Off by 60 degrees.
//TODO: There are colors that overlap here, consider
//tweaking this to make the best use of the colorspace.
@ -155,15 +197,17 @@ uint32_t EHSVtoHEX( uint8_t hue, uint8_t sat, uint8_t val )
//OR..OB == 0..65025
or = or * rs + 255 * (256-rs);
or = or * rs + 255 * (256-rs);
or = or * rs + 255 * (256-rs);
og = og * rs + 255 * (256-rs);
ob = ob * rs + 255 * (256-rs);
//printf( "__%d %d %d =-> %d\n", or, og, ob, rs );
or >>= 8;
og >>= 8;
ob >>= 8;
return or | (og<<8) | (ob<<16);
}
return or | (og<<8) | ((uint32_t)ob<<16);
}
/*
uint32_t HSVtoHEX( float hue, float sat, float value )
{
@ -233,4 +277,4 @@ uint32_t HSVtoHEX( float hue, float sat, float value )
return (ob<<16) | (og<<8) | ora;
}
*/

View file

@ -3,13 +3,20 @@
#include "embeddednf.h"
//Controls brightness
#define NOTE_FINAL_AMP 255 //Number from 0...255
//Controls, basically, the minimum size of the splotches.
#define NERF_NOTE_SIZE_VALUE 10
#define NUM_LIN_LEDS 296
#define LIN_WRAPAROUND 0 //Whether the output lights wrap around. (TODO)
extern uint8_t ledArray[];
extern uint8_t ledOut[]; //[NUM_LIN_LEDS*3]
void UpdateLinear();
void UpdateLinearLEDs();
uint32_t ECCtoHEX( uint8_t note, uint8_t sat, uint8_t val );
uint32_t EHSVtoHEX( uint8_t hue, uint8_t sat, uint8_t val ); //hue = 0..255 // TODO: TEST ME!!!

View file

@ -3,11 +3,11 @@ all : embeddedcc
CFLAGS:=-Ofast -DCCEMBEDDED -I.. -flto -m32 -DDFREQ=11025
LDFLAGS:=-ffunction-sections -Wl,--gc-sections -fno-asynchronous-unwind-tables -Wl,--strip-all
embeddedcc : ../embeddednf.c ../DFT32.c embeddedcc.c
embeddedcc : ../embeddednf.c ../DFT32.c embeddedcc.c ../embeddedout.c
gcc -o $@ $^ $(CFLAGS) $(LDFLAGS)
runembedded : embeddedcc
parec --format=u8 --rate=11025 --channels=1 --device=alsa_output.pci-0000_00_1b.0.analog-stereo.monitor | ./embeddedcc
parec --format=u8 --rate=11025 --channels=1 --device=alsa_output.pci-0000_00_1b.0.analog-stereo.monitor --latency=128 | ./embeddedcc
clean :
rm -rf embeddedcc *~

View file

@ -3,14 +3,57 @@
// It is intended as a minimal scaffolding for testing Embedded ColorChord.
//
#include <stdio.h>
#include "embeddednf.h"
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <stdio.h>
#include "embeddedout.h"
struct sockaddr_in servaddr;
int sock;
#define expected_lights 296
void NewFrame()
{
int i;
char buffer[3000];
HandleFrameInfo();
UpdateLinearLEDs();
buffer[0] = 0;
buffer[1] = 0;
buffer[2] = 0;
for( i = 0; i < expected_lights * 3; i++ )
{
buffer[i+3] = ledOut[i];
}
int r = send(sock,buffer,expected_lights*3+3,0);
}
int main()
{
int wf = 0;
int ci;
sock = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
printf( "%d\n", sock );
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr("192.168.0.245");
servaddr.sin_port=htons(7777);
connect( sock, (struct sockaddr *)&servaddr, sizeof(servaddr) );
Init();
while( ( ci = getchar() ) != EOF )
{
int cs = ci - 0x80;
@ -19,11 +62,10 @@ int main()
#else
Push8BitIntegerSkippy( (int8_t)cs );
#endif
//printf( "%d ", cs ); fflush( stdout );
wf++;
if( wf == 64 )
{
HandleFrameInfo();
NewFrame();
wf = 0;
}
}