made progress... getting very close to an embedded colorchord
This commit is contained in:
parent
5e9023c6a0
commit
36a3777522
2
DFT32.h
2
DFT32.h
|
@ -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.
|
||||
|
|
16
embeddednf.c
16
embeddednf.c
|
@ -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;
|
||||
|
|
15
embeddednf.h
15
embeddednf.h
|
@ -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"
|
||||
|
|
108
embeddedout.c
108
embeddedout.c
|
@ -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;
|
||||
}
|
||||
|
||||
*/
|
||||
|
|
|
@ -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!!!
|
||||
|
|
|
@ -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 *~
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue