From 74fd2e2b40a45847f729328693057f1379732482 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Wed, 28 Jan 2015 19:32:40 -0500 Subject: [PATCH 01/22] Update with libraries closes #2 --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index b905700..78e6f86 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,14 @@ Currently, ColorChord 2 is designed to run on Linux. It's not particularly tied Building and Using ------------------ +On Linux you'll need the following packages, for Debian/Ubuntu/Mint you'll need the following: +* libpulse-dev +* libasound2-dev +* libx11-dev +* libxext-dev +* libxinerama-dev +* libusb-1.0-0-dev + To make colorchord, type: ``` From fe04a3424d562d0faca231032372f9586a7d6153 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Wed, 28 Jan 2015 19:33:58 -0500 Subject: [PATCH 02/22] cleanup: Give command --- README.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 78e6f86..b2ac7bd 100644 --- a/README.md +++ b/README.md @@ -27,12 +27,9 @@ Building and Using ------------------ On Linux you'll need the following packages, for Debian/Ubuntu/Mint you'll need the following: -* libpulse-dev -* libasound2-dev -* libx11-dev -* libxext-dev -* libxinerama-dev -* libusb-1.0-0-dev +``` +apt-get install libpulse-dev libasound2-dev libx11-dev libxext-dev libxinerama-dev libusb-1.0-0-dev +``` To make colorchord, type: From 7148254c4176d692b7cd2841e62b0b66108fef68 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Wed, 4 Feb 2015 21:31:37 -0500 Subject: [PATCH 03/22] Works in Linux and Windows --- colorchord.exe | Bin 0 -> 58368 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100755 colorchord.exe diff --git a/colorchord.exe b/colorchord.exe new file mode 100755 index 0000000000000000000000000000000000000000..867fcfcb6630384b350accff5e213e0d75784e9f GIT binary patch literal 58368 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 Date: Tue, 10 Feb 2015 00:57:10 -0500 Subject: [PATCH 04/22] Add embedded-oriented integer version of DFT. --- Makefile | 7 +- WinDriver.c | 10 ++ colorchord.exe | Bin 58368 -> 60928 bytes dft.c | 255 ++++++++++++++++++++++++++++++++++++++++++++++- dft.h | 7 ++ integerprog.conf | 5 + main.c | 9 +- notefinder.c | 17 +++- notefinder.h | 1 + sound_win.c | 47 +++++---- 10 files changed, 333 insertions(+), 25 deletions(-) create mode 100644 integerprog.conf diff --git a/Makefile b/Makefile index c6dfdc7..a1dce0a 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,8 @@ SOUND:=sound.o sound_alsa.o sound_pulse.o sound_null.o OUTS := OutputVoronoi.o DisplayArray.o OutputLinear.o DisplayPie.o DisplayNetwork.o DisplayUSB2812.o DisplayDMX.o WINGCC:=i586-mingw32msvc-gcc -WINGCCFLAGS:= -lwinmm -lgdi32 -lws2_32 -O2 -ffast-math -g +WINGCCFLAGS:= -O2 -ffast-math -Wl,--relax -Wl,--gc-sections -ffunction-sections -fdata-sections -s +WINLDFLAGS:=-lwinmm -lgdi32 -lws2_32 RAWDRAWLIBS:=-lX11 -lm -lpthread -lXinerama -lXext LDLIBS:=-lpthread -lasound -lm -lpulse-simple -lpulse @@ -16,8 +17,8 @@ colorchord : os_generic.o main.o dft.o decompose.o filter.o color.o sort.o note gcc -o $@ $^ $(CFLAGS) $(LDLIBS) $(EXTRALIBS) $(RAWDRAWLIBS) colorchord.exe : os_generic.c main.c dft.c decompose.c filter.c color.c sort.c notefinder.c util.c outdrivers.c DrawFunctions.c parameters.c chash.c WinDriver.c sound.c sound_null.c sound_win.c OutputVoronoi.c DisplayArray.c OutputLinear.c DisplayPie.c DisplayNetwork.c - $(WINGCC) -o $@ $^ $(WINGCCFLAGS) + $(WINGCC) $(WINGCCFLAGS) -o $@ $^ $(WINLDFLAGS) clean : - rm -rf *.o *~ colorchord + rm -rf *.o *~ colorchord colorchord.exe diff --git a/WinDriver.c b/WinDriver.c index 4b054ed..b0f41d7 100644 --- a/WinDriver.c +++ b/WinDriver.c @@ -5,6 +5,7 @@ #include "DrawFunctions.h" #include #include +#include #include //for alloca static HINSTANCE lhInstance; @@ -193,6 +194,8 @@ void CNFGSetup( const char * name_of_window, int width, int height ) InternalHandleResize(); } +void WindowsTerm(); + void CNFGHandleInput() { int ldown = 0; @@ -204,6 +207,13 @@ void CNFGHandleInput() switch( msg.message ) { + case WM_QUIT: + case WM_DESTROY: + case WM_CLOSE: + printf( "Close\n" ); + WindowsTerm(); + TerminateProcess( 0, 0 ); + break; case WM_MOUSEMOVE: HandleMotion( (msg.lParam & 0xFFFF), (msg.lParam>>16) & 0xFFFF, ( (msg.wParam & 0x01)?1:0) | ((msg.wParam & 0x02)?2:0) | ((msg.wParam & 0x10)?4:0) ); break; diff --git a/colorchord.exe b/colorchord.exe index 867fcfcb6630384b350accff5e213e0d75784e9f..7e2638dd6968a22a228d97c31d4ffe04eecab512 100755 GIT binary patch delta 12043 zcmZ{K3tUvy_WwD@K_>)fGEh`hRD2~GlzJs02XP!L(cz5-ilsCXDj8E+;$Xw1r!Bs= zb@i4HqKBmw3O*{WL5PQ0q27C)xjaIxJOml3*G#SXeb*T<>wo|7Ip^%X*4k^Ywf5R; z@4faE)OIUq?6zrL|ARZ+NkZpei=gY)QZSW!UcH?fa(K83!Wf6wY*uJEw+@6ldO`o^8K>6G?zuG z_6**Ok8tZ5DbF7 zLMuvumzCXR50GZImQ5NIE{cU^iwDo^F0SOY!~ZQUY~{O0WQ)sr&yhJ|K3_319Pf8W zS|p*3-!m$0Vpy9&h?nalY8(B-Q5;=Ab^>&2^qGW8gC?}m-++R>D!}1vu2`)ztDqTe zym-_CNoePq(N@Xa#$OnHE=XuM2y9yDsEX^FJ$hZ?5I;e1*ELSq&GYUZD;DrK?wuf| zwQ={oqhr&-k>!Psnq^{1p`lGlp(~1JhUTV%wX4ovrE&RWf}klqG?&fMtZ9Ru-5jUo zIU1egDPKWoa=V5vY%4R4$<>Iz@k96hP5hN#!n=cy2>+Z!`Z0XEl-^c0AtF_j0@}(p z+<$+!VHPmVf^b>oek?sSt)?)v5aU6AS@N{dg^lC?b)8?BFqztgOk5;N3)}eGzvYP6 z`PIJ>GafZ5T(Y$BrIVh34rOO1-6!=Wb>(^}OY-XqBSeVi`nZ7in>>lDv!$r-cy!7TTgQ0=%;diQP0O_^jrA93=dZnB5L|(` zfFPhx-e9*6RhrMq$$B}?ugOObg62ARhBl*h;}`+7K>&DZhyIl|KwI>z;2KLE zczL;c`;S7U(I*^lmEn{z{HK&4-9m`U0%zha8?P5<@;<4f2U5*koTMu8ZmGwUR;)sb zj2(dT^whzknXgLiH^F=dT_Wi0Rer^3YO4vTnazpWLbjm9crhg^rZ}nWMCur^Pv%vO zll{6!S6GR$8Se2w;%zNuJ?E?tdy`1=cg(2GlJ(5!#{x6?D|0uB>3sNO?@CKY@%qP> zNcWB6Q_=(d!oD{M$~{*-9%Vx!&rDC09v;mPrqAu8YGu@01e+j~WP)FfvAp9=K0ITL z=;ZMk;|AZ4hL%ZqLBRYg9#1h5Wecjr=Hi8XXT~sFx~fV%uq76?_~3gU5A&xon?Uqz zAoWwC8p@oK7_Zz70vLe>5~ySbUgiX){ax6ixOUTYxP%Mk5;CU61C^CJs;X8rs{qwr zRRDrXNi-R(n1sj{&B~d}9#4@`F{=Qxa#F3jx~iX}%90zI@mprSI=Y?>%;fp=`UaDD zqdP>GIU%0;6Q_7(Gbq#MDi1xtOXr2$r;5(}Ntt*SNaP75L$O!iiIAkTzf?3UPUoI^ zeK8Jw=MNf0w0VIg^pOLpz4F%mf>2ipznhE!OPoJmOycY2&%yir{FEM~BpaB-r(~uB z@_Oc&-d^`Iy#u~`$TsjScjk%-M=$|gCz!FrAR9ZHZ$@TxxN6;Xu3DGBlcvV64P)!+ zTjzGVZ#A}JLUp)&8u?2L<_Cr$kZ9c|eN%8KGil81IcB;Sp0UfXdn*RL_Eq0ET;;uMkx(A>cWshL(Imv4NMpDx@e@o2?;9)T{uXK@3^8&{bus|i7;f2Hy zWGRu^$R=hlG>xEhRJtTDWEDY7UF^cWz?TVlze*NL5XrKIAR#JQaH6Gt2_m9u-+`A@ z7wH7i;48j=0&Ti55U^i-uZv~es;k`O{o`Lh+1IxEB53wcB%_fp&Bbtf zyLAv^8xSxZyvq0NFu0pKzM^G4;Z~`Q{AyycsoC9Wq1OoUL{}sI*^&^$Z4Y>Za3-}; zKuv4_c8zf5p5z@U zuiV`f;PwFrp$TEHgwTnwqc0)&1m1J;n5ex}UT~Xpd;Fw_yyh<@#EdS^+J9`{{!k|a z(Q<@vVH5cB#gVp)RBj*NC7Otiyxq4G;tUX8(H0E4L$qszJFGU+c1q`MbdwM}y^Smd z;FXfCv1nQWlmV=w;cW78f&eSSO}9@iksf!SaGh-OsaKmd`M9|5 zsr0)Rx;5blQp&?T@2Q7$)Y4v!9xA@Y9-@j@Jk?j+$K6lGh_!q`PJ(!pFU<+Yo8?UH zMLcQmWw74u3T)vGIgg5&eB_dFzx0L}$RWAG^#p%nNxE3XolD-9^a{5uT_NW1b4y24 z#c$bY@f|*K*<`9bvuwCHjc><$1OIHF#H$p!$+`&%DasgrwIJ9QE#+i?X)3v+#*VX|6H{5Dh z#1~z)qo#Hh(5thPRca>&9`fvXaT8B|mfQT8Q6K3OjBSUm@b6gvi-S z;7;JLE-x_mPT;qlz)5!kzwQJIcLG250?BPN^tOr%QpB}H=oH|D;aE{YDhv`o=)FaWTB>g){eE&p3a@-~v(@8P_Ul`)_+jJiLxbbV;!7myn8}-&U5V2&x5*iR@3@r&$zab@~)NhbM z4h%s_KF;E_6*mU63E`;yk{>MlhZ6W~UjA*0>BdISfFI4vsS}$RuW!3b6)-@8$SlCPx?|Z`R{|l!0Hm1poiMrkB%iE~AD9Qin zVn~BmXd>hVxf0&e`VOH3Nfv(JOa0)$8GZ%Pey9r8CvU4+?L!bT;xy^2S|b5^Hu`5m zPn@VJ_K{^8PqRam6C!WsEw(Xh03tJucTvC&0e@c2+?xB*gNs!9W7NHR zl192uon~eXaQR7pQk1|-RZn<8qIBB>&ZI@&oNFy+#vqojAO5=sbHyX0Vhk!7e`=0F zSe?u!s46rdqtL9$Vl$h&%g3`SZs@Wqe$a}?<=U)@>nJN)z_cROw7L(Sx(`o_^$sG9GUt;;eEIG*S9Q}>#c2~6BRa8C#E%?UgLi<)W*ELt-XjGMd8f!rVjzTBg70oC3 z$>#>!BCxL7tAZYzH$S7Y$?d+>c1GPDCClHXrXmRa3{mqX2}-}7 z{PUGVdMx-3JuEoIe_T02dioR(eE!kVB&=C^)>jo4?�V8v6|?@4@GSAIUSuC#G1I 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 #include - +#include +#include +#include void DoDFT( float * outbins, float * frequencies, int bins, float * databuffer, int place_in_data_buffer, int size_of_data_buffer, float q ) { @@ -41,6 +44,8 @@ void DoDFTQuick( float * outbins, float * frequencies, int bins, const float * d for( i = 0; i < bins; i++ ) { + int flirts = 0; + float freq = frequencies[i]; float phi = 0; int ftq = freq * q; @@ -66,6 +71,7 @@ void DoDFTQuick( float * outbins, float * frequencies, int bins, const float * d binqtyc += cv; phi += advance; + flirts++; } float amp = sqrtf( binqtys * binqtys + binqtyc * binqtyc ); @@ -73,3 +79,250 @@ void DoDFTQuick( float * outbins, float * frequencies, int bins, const float * d } } + + +////////////////////////////DFT Progressive is for embedded systems, primarily. + + +static float * gbinqtys; +static float * gbinqtyc; +static float * phis; +static float * gfrequencies; +static float * goutbins; +static float * lastbins; +static float * advances; + +static int gbins; +static float gq; +static float gspeedup; + +#define PROGIIR .005 + +void HandleProgressive( float sample ) +{ + int i; + + for( i = 0; i < gbins; i++ ) + { + float thiss = sinf( phis[i] ) * sample; + float thisc = cosf( phis[i] ) * sample; + + float s = gbinqtys[i] = gbinqtys[i] * (1.-PROGIIR) + thiss * PROGIIR; + float c = gbinqtyc[i] = gbinqtyc[i] * (1.-PROGIIR) + thisc * PROGIIR; + + phis[i] += advances[i]; + if( phis[i] > 6.283 ) phis[i]-=6.283; + + goutbins[i] = sqrtf( s * s + c * c ); + } +} + + +void DoDFTProgressive( float * outbins, float * frequencies, int bins, const float * databuffer, int place_in_data_buffer, int size_of_data_buffer, float q, float speedup ) +{ + int i; + static int last_place; + + if( gbins != bins ) + { + if( gbinqtys ) free( gbinqtys ); + if( gbinqtyc ) free( gbinqtyc ); + if( phis ) free( phis ); + if( lastbins ) free( lastbins ); + if( advances ) free( advances ); + + gbinqtys = malloc( sizeof(float)*bins ); + gbinqtyc = malloc( sizeof(float)*bins ); + phis = malloc( sizeof(float)*bins ); + lastbins = malloc( sizeof(float)*bins ); + advances = malloc( sizeof(float)*bins ); + + memset( gbinqtys, 0, sizeof(float)*bins ); + memset( gbinqtyc, 0, sizeof(float)*bins ); + memset( phis, 0, sizeof(float)*bins ); + memset( lastbins, 0, sizeof(float)*bins ); + + } + memcpy( outbins, lastbins, sizeof(float)*bins ); + + for( i = 0; i < bins; i++ ) + { + float freq = frequencies[i]; + advances[i] = 3.14159*2.0/freq; + } + + gbins = bins; + gfrequencies = frequencies; + goutbins = outbins; + gspeedup = speedup; + gq = q; + + place_in_data_buffer = (place_in_data_buffer+1)%size_of_data_buffer; + + int didrun = 0; + for( i = last_place; i != place_in_data_buffer; i = (i+1)%size_of_data_buffer ) + { + float fin = ((float)((int)(databuffer[i] * 127))) / 127.0; //simulate 8-bit input (it looks FINE!) + HandleProgressive( fin ); + didrun = 1; + } + last_place = place_in_data_buffer; + + if( didrun ) + { + memcpy( lastbins, outbins, sizeof(float)*bins ); + } + +/* for( i = 0; i < bins; i++ ) + { + printf( "%0.2f ", outbins[i]*100 ); + } + printf( "\n" );*/ + +} + + + + + + + +/////////////////////////////INTEGER DFT + + + + +#define PROGIIR .005 + +//NOTES to self: +// +// Let's say we want to try this on an AVR. +// 24 bins, 5 octaves = 120 bins. +// 20 MHz clock / 4.8k sps = 4096 IPS = 34 clocks per bin = :( +// We can do two at the same time, this frees us up some + +static uint8_t donefirstrun; +static int8_t sintable[512]; //Actually [sin][cos] pairs. + + +//LDD instruction on AVR can read with constant offset. We can set Y to be the place in the buffer, and read with offset. +static uint16_t * datspace; //(advances,places,isses,icses) + +// +void HandleProgressiveInt( int8_t sample1, int8_t sample2 ) +{ + int i; + uint16_t startpl = 0; + int16_t ts, tc; + int16_t tmp1; + int8_t s1, c1; + uint16_t ipl, localipl, adv; + + + //startpl maps to 'Y' + // + + + //Estimated 68 minimum instructions... So for two pairs each... just under 5ksps, theoretical. + //Running overall at ~2kHz. + for( i = 0; i < gbins; i++ ) //Loop, fixed size = 3 + 2 cycles 5 + { + //12 cycles MIN + adv = datspace[startpl++]; //Read, indirect from RAM (and increment) 2+2 cycles 4 + ipl = datspace[startpl++]; //Read, indirect from RAM (and increment) 2+2 cycles 4 + + //13 cycles MIN + ipl += adv; //Advance, 16bit += 16bit, 1 + 1 cycles 2 + localipl = (ipl>>8)<<1; //Select upper 8 bits 1 cycles 1 + + // need to load Z with 'sintable' and add localipl 2 + s1 = sintable[localipl++]; //Read s1 component out of table. 2+2 cycles 2 + c1 = sintable[localipl++]; //Read c1 component out of table. 2 cycles 2 + + ts = (s1 * sample1); // 8 x 8 multiply signed + copy R1 out. zero MSB ts 2 + tc = (c1 * sample1); // 8 x 8 multiply signed + copy R1 out. zero MSB tc 2 + + + //15 cycles MIN + ipl += adv; //Advance, 16bit += 16bit, 1 + 1 cycles 2 + localipl = (ipl>>8)<<1; //Select upper 8 bits 1 cycles 1 + + // need to load Z with 'sintable' and add localipl 2 + s1 = sintable[localipl++]; //Read s1 component out of table. 2 cycles 2 + c1 = sintable[localipl++]; //Read c1 component out of table. 2 cycles 2 + + ts += (s1 * sample2); // 8 x 8 multiply signed + add R1 out. 3 + tc += (c1 * sample2); // 8 x 8 multiply signed + add R1 out. 3 + + + //Add TS and TC to the datspace stuff. (24 instructions) + tmp1 = datspace[startpl]; //Read out, sin component. 4 + tmp1 -= tmp1>>6; //Subtract from the MSB (with carry) 2 + tmp1 += ts>>6; //Add MSBs with carry 2 + + datspace[startpl++] = tmp1; //Store values back 4 + + tmp1 = datspace[startpl]; //Read out, sin component. 4 + tmp1 -= tmp1>>6; //Subtract from the MSB (with carry) 2 + tmp1 += tc>>6; //Add MSBs with carry 2 + + datspace[startpl++] = tmp1; //Store values back 4 + + datspace[startpl-3] = ipl; //Store values back 4 + } +} + + +void DoDFTProgressiveInteger( float * outbins, float * frequencies, int bins, const float * databuffer, int place_in_data_buffer, int size_of_data_buffer, float q, float speedup ) +{ + int i; + static int last_place; + + if( !donefirstrun ) + { + donefirstrun = 1; + for( i = 0; i < 256; i++ ) + { + sintable[i*2+0] = (int8_t)((sinf( i / 256.0 * 6.283 ) * 127.0)); + sintable[i*2+1] = (int8_t)((cosf( i / 256.0 * 6.283 ) * 127.0)); + } + } + + if( gbins != bins ) + { + gbins = bins; + if( datspace ) free( datspace ); + datspace = malloc( bins * 2 * 4 ); + } + + + for( i = 0; i < bins; i++ ) + { + float freq = frequencies[i]; + datspace[i*4] = 65536.0/freq; + } + + + for( i = last_place; i != ( place_in_data_buffer&0xffffe ); i = (i+2)%size_of_data_buffer ) + { + int8_t ifr1 = (int8_t)( ((databuffer[i+0]) ) * 127 ); + int8_t ifr2 = (int8_t)( ((databuffer[i+1]) ) * 127 ); +// printf( "%d %d\n", i, place_in_data_buffer&0xffffe ); + HandleProgressiveInt( ifr1, ifr2 ); + } + + last_place = place_in_data_buffer&0xfffe; + + //Extract bins. + for( i = 0; i < bins; i++ ) + { + int16_t isps = datspace[i*4+2]; + int16_t ispc = datspace[i*4+3]; + int16_t mux = ( (isps/256) * (isps/256)) + ((ispc/256) * (ispc/256)); +// printf( "%d (%d %d)\n", mux, isps, ispc ); + outbins[i] = sqrt( mux )/100.0; + } +// printf( "\n"); +} + + diff --git a/dft.h b/dft.h index 7fedc79..bae53b5 100644 --- a/dft.h +++ b/dft.h @@ -12,5 +12,12 @@ void DoDFT( float * outbins, float * frequencies, int bins, float * databuffer, //Speedup = target number of data points void DoDFTQuick( float * outbins, float * frequencies, int bins, const float * databuffer, int place_in_data_buffer, int size_of_data_buffer, float q, float speedup ); +//An unusual tool to do a "progressive" DFT, using data from previous rounds. +void DoDFTProgressive( float * outbins, float * frequencies, int bins, const float * databuffer, int place_in_data_buffer, int size_of_data_buffer, float q, float speedup ); + +//A progressive DFT that's done using only low-bit integer math. +void DoDFTProgressiveInteger( float * outbins, float * frequencies, int bins, const float * databuffer, int place_in_data_buffer, int size_of_data_buffer, float q, float speedup ); + + #endif diff --git a/integerprog.conf b/integerprog.conf new file mode 100644 index 0000000..d321461 --- /dev/null +++ b/integerprog.conf @@ -0,0 +1,5 @@ +do_progressive_dft = 1 +samplerate = 8000 +buffer = 128 + + diff --git a/main.c b/main.c index d268ede..be4cd84 100644 --- a/main.c +++ b/main.c @@ -14,8 +14,15 @@ #include "outdrivers.h" #include "parameters.h" +struct SoundDriver * sd; + #ifdef WIN32 #include +void WindowsTerm() +{ + CloseSound( sd ); +} + #endif int lastfps; @@ -244,7 +251,7 @@ int main(int argc, char ** argv) //Initialize Sound - struct SoundDriver * sd = InitSound( sound_source, &SoundCB ); + sd = InitSound( sound_source, &SoundCB ); if( !sd ) { diff --git a/notefinder.c b/notefinder.c index 96d042c..11078c8 100644 --- a/notefinder.c +++ b/notefinder.c @@ -25,6 +25,7 @@ struct NoteFinder * CreateNoteFinder( int spsRec ) ret->decompose_iterations = 1000; ret->dft_speedup = 300; ret->dft_q = 16; + ret->do_progressive_dft = 0; ret->default_sigma = 1.4; ret->note_jumpability = 2.5; ret->note_combine_distance = 0.5; @@ -58,6 +59,7 @@ struct NoteFinder * CreateNoteFinder( int spsRec ) RegisterValue( "note_minimum_new_distribution_value", PAFLOAT, &ret->note_minimum_new_distribution_value, sizeof( ret->note_minimum_new_distribution_value ) ); RegisterValue( "note_out_chop", PAFLOAT, &ret->note_out_chop, sizeof( ret->note_out_chop ) ); RegisterValue( "dft_iir", PAFLOAT, &ret->dft_iir, sizeof( ret->dft_iir ) ); + RegisterValue( "do_progressive_dft", PAINT, &ret->do_progressive_dft, sizeof( ret->do_progressive_dft ) ); AddCallback( "freqbins", ChangeNFParameters, ret ); AddCallback( "octaves", ChangeNFParameters, ret ); @@ -175,7 +177,20 @@ void RunNoteFinder( struct NoteFinder * nf, const float * audio_stream, int head //This DFT function does not wavelet or anything. nf->StartTime = OGGetAbsoluteTime(); - DoDFTQuick( dftbins, nf->frequencies, freqs, audio_stream, head, buffersize, nf->dft_q, nf->dft_speedup ); + switch( nf->do_progressive_dft ) + { + case 0: + DoDFTQuick( dftbins, nf->frequencies, freqs, audio_stream, head, buffersize, nf->dft_q, nf->dft_speedup ); + break; + case 1: + DoDFTProgressive( dftbins, nf->frequencies, freqs, audio_stream, head, buffersize, nf->dft_q, nf->dft_speedup ); + break; + case 2: + DoDFTProgressiveInteger( dftbins, nf->frequencies, freqs, audio_stream, head, buffersize, nf->dft_q, nf->dft_speedup ); + break; + default: + fprintf( stderr, "Error: No DFT Seleced\n" ); + } nf->DFTTime = OGGetAbsoluteTime(); for( i = 0; i < freqs; i++ ) diff --git a/notefinder.h b/notefinder.h index f42d4b4..937ebc7 100644 --- a/notefinder.h +++ b/notefinder.h @@ -16,6 +16,7 @@ struct NoteFinder int filter_iter;// = 1; int decompose_iterations;// = 1000; float amplify; // =1 (amplify input across the board) + int do_progressive_dft; //= 1 //at 300, there is still some minimal aliasing at higher frequencies. Increase this for less low-end distortion //NOTE: This /should/ get fixed, as we /should/ be decimating the input data intelligently with lower octaves. diff --git a/sound_win.c b/sound_win.c index e0c5afb..ee731ea 100644 --- a/sound_win.c +++ b/sound_win.c @@ -1,5 +1,3 @@ -//XXX THIS DRIVER IS INCOMPLETE XXX - #include #include "parameters.h" #include "sound.h" @@ -12,7 +10,7 @@ #pragma comment(lib,"winmm.lib") #endif -#define BUFFS 3 +#define BUFFS 2 struct SoundDriverWin { @@ -27,9 +25,7 @@ struct SoundDriverWin int buffer; int isEnding; - int Cbuff; int GOBUFF; - int OLDBUFF; int recording; @@ -42,6 +38,7 @@ static struct SoundDriverWin * w; void CloseSoundWin( struct SoundDriverWin * r ) { int i; + if( r ) { waveInStop(r->hMyWave); @@ -65,6 +62,7 @@ int SoundStateWin( struct SoundDriverWin * soundobject ) void CALLBACK HANDLEMIC(HWAVEIN hwi,UINT umsg, DWORD dwi, DWORD hdr, DWORD dwparm) { int ctr; + int ob; long cValue; unsigned int maxWave=0; @@ -80,18 +78,20 @@ void CALLBACK HANDLEMIC(HWAVEIN hwi,UINT umsg, DWORD dwi, DWORD hdr, DWORD dwpar break; case MM_WIM_DATA: - w->OLDBUFF=w->GOBUFF; - w->GOBUFF=w->Cbuff; - w->Cbuff = (w->Cbuff+1)%3; - waveInPrepareHeader(w->hMyWave,&(w->WavBuff[w->Cbuff]),sizeof(WAVEHDR)); - waveInAddBuffer(w->hMyWave,&(w->WavBuff[w->Cbuff]),sizeof(WAVEHDR)); +// printf( "Mic Data.\n"); + ob = (w->GOBUFF+(BUFFS))%BUFFS; +// waveInPrepareHeader(w->hMyWave,&(w->WavBuff[w->Cbuff]),sizeof(WAVEHDR)); for (ctr=0;ctrbuffer * w->channelsRec;ctr++) { - float cv = (uint16_t)(((uint8_t)w->WavBuff[w->GOBUFF].lpData[ctr*2+1])*256+((uint8_t)w->WavBuff[w->GOBUFF].lpData[ctr*2])+32768)-32768; + float cv = (uint16_t)(((uint8_t)w->WavBuff[ob].lpData[ctr*2+1])*256+((uint8_t)w->WavBuff[ob].lpData[ctr*2])+32768)-32768; cv /= 32768; +// if( ctr < 3 ) cv = -1; +// buffer[(w->buffer * w->channelsRec)-ctr-1] = cv; buffer[ctr] = cv; } + waveInAddBuffer(w->hMyWave,&(w->WavBuff[w->GOBUFF]),sizeof(WAVEHDR)); + w->GOBUFF = ( w->GOBUFF + 1 ) % BUFFS; int playbacksamples; //Unused w->callback( 0, buffer, w->buffer, &playbacksamples, (struct SoundDriver*)w ); @@ -113,23 +113,34 @@ static struct SoundDriverWin * InitWinSound( struct SoundDriverWin * r ) w = r; + + printf( "WFMT: %d %d %d\n", r->channelsRec, r->spsRec, + r->spsRec * r->channelsRec ); + wfmt.wFormatTag = WAVE_FORMAT_PCM; wfmt.nChannels = r->channelsRec; wfmt.nSamplesPerSec = r->spsRec; - wfmt.nBlockAlign = 1; + wfmt.nAvgBytesPerSec = r->spsRec * r->channelsRec; + wfmt.nBlockAlign = r->channelsRec * 2; wfmt.wBitsPerSample = 16; - wfmt.nAvgBytesPerSec = 0; + wfmt.cbSize = 0; long dwdevice; dwdevice = GetParameterI( "wininput", WAVE_MAPPER ); - int p = waveInOpen(&r->hMyWave, dwdevice, &wfmt,(DWORD)(void*)(HANDLEMIC) , 0, CALLBACK_FUNCTION); + printf( "Wave Devs: %d; WAVE_MAPPER: %d; Selected Input: %d\n", waveInGetNumDevs(), WAVE_MAPPER, dwdevice ); - printf( "WIO: %d\n", p ); + printf( "waveInOpen: %p, %p\n", &r->hMyWave, &wfmt ); + + int p = waveInOpen(&r->hMyWave, dwdevice, &wfmt,(DWORD)(void*)(&HANDLEMIC) , 0, CALLBACK_FUNCTION); + + printf( "WIO: %d\n", p ); //On real windows, returns 11 for ( i=0;iWavBuff[i]), 0, sizeof(r->WavBuff[i]) ); (r->WavBuff[i]).dwBufferLength = r->buffer*2*r->channelsRec; + (r->WavBuff[i]).dwLoops = 1; (r->WavBuff[i]).lpData=(char*) malloc(r->buffer*r->channelsRec*2); waveInPrepareHeader(r->hMyWave,&(r->WavBuff[i]),sizeof(WAVEHDR)); waveInAddBuffer(r->hMyWave,&(r->WavBuff[i]),sizeof(WAVEHDR)); @@ -137,7 +148,7 @@ static struct SoundDriverWin * InitWinSound( struct SoundDriverWin * r ) p = waveInStart(r->hMyWave); - printf( "WIS: %d\n", p ); + printf( "WIS: %d\n", p ); //On real windows returns 5. return r; } @@ -154,14 +165,12 @@ void * InitSoundWin( SoundCBType cb ) r->spsRec = GetParameterI( "samplerate", 44100 ); r->channelsRec = GetParameterI( "channels", 2 ); - r->buffer = GetParameterI( "buffer", 1024 ); + r->buffer = GetParameterI( "buffer", 384 ); r->recording = 0; r->isEnding = 0; printf( "Buffer: %d\n", r->buffer ); - r->Cbuff=0; r->GOBUFF=0; - r->OLDBUFF=0; return InitWinSound(r); } From 3914898fbbb9a050f34688772dda32a1639f8002 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Wed, 11 Feb 2015 01:10:16 -0500 Subject: [PATCH 05/22] integer-based DFTs are working. --- colorchord.exe | Bin 60928 -> 63488 bytes default.conf | 9 +- dft.c | 282 +++++++++++++++++++++++++++++++++----- dft.h | 12 +- integerprog.conf | 6 +- main.c | 344 ++++++++++++++++++++++++++--------------------- netlight.conf | 15 ++- notefinder.c | 7 +- notefinder.h | 1 + 9 files changed, 472 insertions(+), 204 deletions(-) diff --git a/colorchord.exe b/colorchord.exe index 7e2638dd6968a22a228d97c31d4ffe04eecab512..5c013e79e2e94f76ad2252db0ea75045728f4dab 100755 GIT binary patch delta 20191 zcmc(H4_H*y*7upifTIr0WMHT$W1*svL8*yij^c==ATlAg?u`V0}vOpT3^KX@5>$S-Az?;VTv`%vs2BkvD_U3J3!nV<&WdyX8I;2t~SQ28Q;{V7jCq2asnH!j~v=$<*Tk&dZsxtm*sN}MI*H~! z=4fsCu;AKX$Dk$qCUXS^9fOu@I7h>aG`vc~c^b~uaK47^8b0ujs;6ATH5%Th;gmhv zN2!L7YS^pc5)D^rxIk09TftAyvB!gp=*v~Z7Zd*N z5Xa?lIh{m(7m?F-5e?Ufd>7HI5Z9i>$mqL>7KM1R;#ywo%?c^+drOWs9KRZ7?xnFQQl`dQTb^3>e?`*iQm_Mms#0GNP9oB+XNW-+Dn92hDphK zNw*el!Khalbi6`m`@4_pF$LyG!#Am{>`M12ovw)u>bXVNot5`Iq)RV*(zx1u(}=qi z8#n=i52LI2{9Ut+rlXY(g7G2@Vj_@6GZ$A{cO==C8F@XOoTO;H)6cC=f$WU(%` zrXhGYK8M!bJ`#SUA+Q9AdVOR=a49}qRUvNgiHbEQK_Qj5v!bYl{DLb?Kh(i{+u4&t zzwNW&3QT=cWK>0)zQkOWnYfIgAb!ti*;x-HNuo13qRcG`v9%&J9aP$O&kj^j#f{P-*sb;P&f#; zch(0y%5-d#zh)irV=!Q2#zpF0V)Mt{+YhD&U!g~J^hFsk5_gBhAz>(*TgEEK{j=v> zq8*bAV6q+ejIuz!&8gwEX)qcgKx$4~F|Y%jPgZ;k=H z5V);R;lbI8HQYI z+t-8WXa?ENCBwd_9qj0+4y2saRdCWC{i9%dZqPNs|jXN;|ckwAL?K6W5De-W_H8m-nyo; zL6gS@>iV#SQ?vPy-`QtVZ$;vlsS|X4%I=!BEWkMfJx{J-m4+8-_>_hhXn2W+_i0$K zIoP9Gx0*`M@f*B(a4tx`&?WdKVqi{$Kadh9z7^BVVv?~jFppBT{!Bw= z^TFFW$gb~_op{Tig$u3;GYESg<$SkO392$*@OFGR1n$PKqHx*m?C10_=MuC@3Y~#p z(biUE2TrNBQMk)h+bI49`HEa#+R;%orD!r*zaO7)4aJm0D4I*Z@@t@F6e$#st+kWd z?J^{*LTa^00lfi7ZI&|O#i_LZQKZi%XCiZ|JYQ2wtWE`~M5{6uEl>&>iIgCuW^>t` zJVE6YD;!jUeL6F$2k8@Stwp1Y*zYs9b_+wY$WX+#XJp>&)g#_=wRM>CX$vrjyt`++ z^>=2R^)nv^@mZPiBrc9LP@Ux7SE*pLHk#KW9So@yN*yMCFWC%PqFJ&TrBM56_U!CU zgBF1fw@@QW|MNb2K4pTb zP|pbREToE;E1zRtN14I&EsdnwO8uz;#fmWr>8Z)`jSxU_QYev%1^fsp@|o9Q0Gbv0 z@U562`n!XZYbmLij-U{fUYlG6Dzqq8Qlt)#AlIMk=NOn!!>l-3~G zPDzdnL+hme7~D1UdWTc}hPLW_LQ1j}OsbOQ=OLOgTi!H^mCmyyDRq~EsWr)}jigW| ziqr;=LQS*+=Odf;ITxR(AEJ|~f}l(swWmT@|M_7NRAf%5GPELW3}*4`NRF$m#JnC$ zHaBDbt-X{fWIAXw3ivV5ykX+}3?Asa`Dr&%he-XEnxVz%LaID~OnRTK)F0<8F|N<|Z& zBHEe+1Y>4U#l!_t;u7#k)~N`8{gW!3*_57+piKS|X)$q$l(6B3QfW=e$tjSk zQlu71iT3NIHmOnqbr}`8Q%#GBb}2EZt9o`#$_cRs63gur%aIauyTm5`Nm)v#RIZeW zC{t@|xJs2W8`SDYBP}K_m)7NBW?o;n^Jlbno=UFxj!#BY17z+ew)XFRomDC;C577m zm6{OO(H1~jw;sP;g}tcq(7r??dY0;5(kV`Y(z=4{#g}x6tKG4xQ@h)C;pK=Ar@%PnfVlNwS}lOfxNw5Uj73X9z! zI!j7A<*r>br9ROZTQ9wr2L=92pAr=N6X*IK3rVfV?#tnGozeT7V5D{kShKmt%o;gb zRo-Z;fq{qbOc>V$B`^(R*X3#oiL-vSH45B9?geW>YcL9{II>o|NqJfBq6tVDZy^|UjMx@eCIg6?; zl87%Va*=AzIHHK1V$mvb0ugf*u^5$-M3ldEij7u@sYFat#Nt)TLZXaycFI{*>I$L` zR^;?5Wj#?sI>jcb#7#u(7(;EHqEd>9@)IaZmrPTM?-9|bh|N$bM~QN{Q!FFfsdQ8; zQQubNMyPUEiL$FxE{ce}JqV$yyg?xvQ|)z2v5+gB{+r@!I!RjS-=XMaPEflBfE>ID64jILVXuf#B@wSdv}`0Cbp%_4R7E5th!M_piq zC34(utqXg$f$=36=!xnC^H;?dt0%#%Hmeu$-cvG#R42f0z2md>J;_%35NBr`E3k)l z8%W^9boMCX?HJ9rJQ(MkN#Aq3 z6wnM&i=Ru3giZy9f;yr>(yFMA|TO7gP%4teT(&6n0;QIsZ_E1L9zJQ74Htxl|#Y{%hErTfgRB769R zXmmkCEg1Dy{fSy>;)42#Mqhl4G%;7w$GE+XfiVz(*KGF(jwaDV{v*Dlje%ArTVvpq zHWu^HobGnNJ_asV9?G^pbdQO$x(=hv*G?h)-NU|p=w{tkcIlxB{OC3oza%+=3YC)1 zRNGEb-97v6ZHutMnYY&4PWb|(+t{8Z6HHVZZKkY_8-1Zd8@saPKHVagxHQJNpnd|X z$oo;=>&&%uu5Kx7T6$lfJ`*^pw?DHXg_eQU4LF5E;+sIZA4_;RfzNAW>mQySaR~)& zSbG`26;0-flZNhxV!a#IQt{mnrO4BmZrM;0jb1iXw~nPR8%qhcY>+OJy}xXb<>AvE z9i-9r*Cq8~SC&72|XZ*efeCL#VL{>v^>o)=$)J zSbHgg^FP`$h-|axNsK=cpd2ck_8v`kI;>pk@`Rsb|MlKFeFqv+SG!eB^nyA*Yy9 zcQ|ef+3+=v(DadJSO~5|Rv{$@uz@>5L#)c|##Rf{H0B8_&FUuhoFj6?P&G#siWCpa z{g9$HwbD)mEU99UJd?D9M^;bPH?2m-$p$a`+0ifLYrj$y=|xdTky45Zxj`#rl~Tw8 zW_@%7Z#d5$eRR9if{@&l{~RLRqHuh6#aGHi=f=ZR+wFH$W-=QU_6!{h;u84l|>tfO`jSD}` zjz2bx4?DdjcOaj8n%xRC=`@?18<9=&70tY~+Hn3A$%a6DO@Aqra>aUa4$>HCz_Q{S zvDP2{ly$7l>}Y|Elx8fZZjo$}#W4!D6h|vK%qoUP;!8XvB^fF%M@S<_BlX+ra4|UQ zH2XZaH{W!Qoz9JnF+(ebXpwR^6C6Xj4%>&z5hVEUjJU5H`>FEdD6ix&NaIk|v5)8R zqffJs9v|p5gUmS|@UK3XCE3pHGae2kiZ1q87Ir*Jm`I+XA=r1$3X9Z}M{B}o!x8@x z|I*fPGSB*#o;y*Cyl2_dCw0;#n*u}Y(hrW%pxGJ|*i zrI-N?nGOCoK#=V!rI^H|Br_t}5nWZq9Sx{zP5ptV&asjwEPVWFcI1f&>Y0`&#*I3T zvtUmu-_;*qX2iA6b`(jOVNkaAyQ?^?aMy}R*}{tBp=?c>G}3sQWj;A6SVk-T;oA}Q znjK|qx~HELhaG7KY|E$Ehtj-l&&`QeCT+FNjJrW{ z0XQN92gfrZ)i%RMXzn~I+w>)-J5*+#q87k7O7kG7HF0evCH5KLr@UEC3bbwitZ*7R|Gsyq<=n=1FCUY^-$ zbq(TI8F5!2bf9$^UF@;gTCwiSwh~>=P&7HnaqgN+4TDQvj((R7#}sEq!GRot?^1nK&HAS} z)NP{cvc>UHb5s<3v3BW)v%Hz{L?e9T!p^f3PcDt5nSSD&`(i__ zY5gi#$Lzb)UslI~zY)_@WnD@bwpm$y7bH+RteqW9)IW^thNSO-%$sTkL z=3n_Id&YUcmgzU#0iu!DWg1PHG6iIMnwoR?$0x{cS&jUezY8_hU zL-x*VcPma)LOvv(#Q8be_^!TAJarv=GH;=-nKkBx^XzHXo_Ck=7{%&0euf3Ps+o;h z>*5=JV+Yp`Htcd?3I~Js)7t3+GBE5o^!EMXpgV9bQ3Es1v)NBY@{7*1yr&ZQob&9H zr``;=gQc8)JMO#wD13oG(0-n6a*gGIK6MQ=E$@`exz!)I{5)%S4dj6aW=vp(2_aNE)5Aev)aR^+^F1c?RZUGge<-TazREm}s(Mmm83Z)Q0>Q5np z6dZFEmeegvn#t=9NtvzUzjcSQD$e3uJ?&gp#g7Kv zMcuKrKhSx)dLIiNPkW&lc!P@f+RmExeu}j71zKfw6;fI&Nm0VI_vd|VW0}FpryQ3go7~BYD>5st z=-T6l*kka8PI87uw0^y0?_dj{EYmXV(;P)>a$7 zRl4JxGfSF!IV)gln^==oAsckCZFC#TDWHV_IFA+y)82oZ_8vwD1Z0U2uV@R%(j{EU z(xqO-&NQyw@d5mq(mF|5nPNM{v@=-+SyK4#lTccgG~)Nkz~a|pD|DFNr$rY^Oc*Pt zK`HiY&<#3p+i;?L%(U05s}sbwZ}gG=%fB^?ZQ>VLoGUKzLo3P`p&PzzLYyr6ARUNZ zUDnV_(%Tl8C2HjjJ)9+~MPg!|xJ1EM`1^^jj$D)bK@3Ind)j)0)qth04+-!FO<>vU z2PQA9Qf31d^dE6>jd78zI5wUND$IjciL|bJx=|piL)p2cP>3T;X>XM z??$g-wd+~I-jL#X_j%SV%?#P&r3lI(UKuA9AP; z3ORuyQst`$S?k6$T{WBRiSCj;_X}I)xsT5}$Z9;}_|qS=ZkxvHjPEgPO-qvcZ9*n(N-)>O*mzi^!u$K2=d8~*tE^Vqv?-R@!vvIz1iU@Pgva-!XoxTI0+p46rs%nmV zMA6WyY7i$HGG?n9E>H%#7m$*w#0g>ZGoYk{Xy<4Hyt+zE44E^}PO+rjK#N#C$kmC; zX{MMMUY%&6ew{r_u$zdx4MkQb;*gT#=8c+<%dUPzEkPco`%Lcpp-8e-6<6VroHQjw z62in9)80e48?tATXxahxOo7F@6yI6Zwv#$^&X4$LHB<5&hwDq|@?@SAZFTaaE6G&q zQnEV)doE@E{X;4zTyj*Ux(-KU4I`oq;`|Id#|2ASGozgME7}mH#Gq>=+tF-`;HtDp6L9!kzk>P(l$q!uX*$lTzW~K` zm7nd{Og5MZnQEfo(#2j&`eUIC%czKVdx*xa#gOrcAuS|O^1-zjav#16rgZs9C1^v$ zQ6#`S3i5MMjJJn$twq;`^gCB!?4%NL^c_q|_2w^GetZSHeal@D+iC*kG98$zmFzV<*IjL|Q-VpXA+ z*ajtQn3SLw>~%!==6%+U4Re}lI)=M(9>=-9YZZO+Fbsm|!%Hrc>)Tc_sYdPt0wob} z5ur*pXarmdf#UXxNnX>YpP>Lz@x%qvYOg=D2`6ZxZI3k3?$0chQkKMC6m2D9+RH6` zqfbiP;|bpnaV*xQtdvFYACIp_3FB+cR>Cc1f_a)O7+U++DFP>*?PZ@Z);<}ZaZt~g9)(yX*%$seRmtK zBFyWbrXw(XuYdY-1Pgd>vysC&jBnagX6)%Nv7OJwJ8|1!J7fPFf-ymUcOQ)+;&HnD zehu|b&*mveehYLuJ>IGCjpAXtBTbc`L((%@N7vw6@tG=CXY0}hxj>P^Ub8h--iYtR z`nxFrcCBvJ<=jmsnsi1n!sK)~b|-e3DfT?2c*-cQM!hYa+ssEn@w`hth9>-dWp4dHyT6sEAs^bRd{wq(BV!&11{hkQWE@x8nTZ#Q}Uk z8C&*Z6hE+xJ^$jZ{FQgu$1nEhUwMZ$zIY4&;5$sWqc8t{DeJ$(a@%w2`wsE2UBOVGp-bb7b^C9DGphJqs0?pJ2taqFmi!NZ{+`D~oTjYaBxI^!1)i2+yeU=5pX zWXpS0$!5;MY84VG_pf0UJHpb7wj+RtiA`BEUK&@^Z-N?;wFKeZqcta58nH_dvd5*% zXZE7q%If(;Q55G`Kkz{oT)3S7`3!Rw zj+tuMMQ<4$KT~Jn&R%9Xixu^aM8@KcFC%@?jo&p7I|Lp!n)Zd0-%=WiElr1<@)pzY zj2elxmbQdrM{LW(=bC$ID^7ka@=mOpub`n*uhR%kuN{;~6p>9mE#0Uv@xF-fKg{u8=7J$)vgn}d@oKdszK zYLlNr{k+j!&TLn%J|HJdov+H&YD0Sj`I$G_pk22HpQ61jJ!(mpXT8bNcHI&?AM1B# z2VD2EYVez=(P}f!lcFKe(wJ3%Y}p3+pLePG%p&~B! zXBJUPkXN9FFqaTAk;C#5ogz(qKPB4lT4)TQ7@L%?h=hsmNI zKH~p_UEDo{|9KIMC|c~qYH~nIJ0Lj@bUmfmhZh*8y{+0>;z=0bYHF1iEP`vCfwk*o ztC&_QS6~+`B}O&w+KpbovsP37CqX#b+jIuMcvNc2w<#Y1ru;m7bdHda-5VxagFU)z zd0lCRQ_h7Z_r=CtB~Y|xl9W~&TkFw#kl+H8=Li185q=H_1-x&1Wby>pA-z8^95&JL zoxk?Pr}emvnU1HZ`nX?CRGc`16QVFj1=`ZNRmJsoqEXtM4{gfLjgr-)-$v?nH4|~M z^}tK!VSi-1WWCM@mfqE(_x&<9?SRh!t$wVpo7c0VmqIKCoRZU?_31zkj}j=ecut3_ z9{*W&?O=5;S)7$pVmO{iguz!H5Ty6kLn>YV2ad?)l#A4IxWIjlyJ$O&*HF@Cda;l! z&wq`2)iPUfoxx+6(KsBCZ2JWD;R8?sgn+gx=sLAcM@eIhSm6m#;tg@#Mki!wsD2RZ zUVIqm zI4wLD@hlz(od-X9VvB^_0}+b=hK>#vpc28;~$myr@L_%qkbFT#h@v2+@a36A>1lxIa2 zl%$N5KXHoR>oXeSc5P&FuiWQcAUeFs$tZ&Ihs2~Ho|p7yL0$_bO3SQD%S`#NQU}aj zA|=)N^*#KjlxCUS5A%rY^mlfp=Tf@X_r*6&V$yLm+?1aRij?LR|0$*&N9ag?I%zi= zmaNp7@vrvowiP1|)hy!Gu&@RGaJ)M8R_ozZIj&j{e^zq{oyDfVI>NaGI~Tv6_stiy zO1(~%LQf`DDUwJi7T~ToZQ2Z0Y_0Sj*>GO`4V>cSKSqz@DIcdBC`&0L@*@w6$e>9F3c>l|c* zZbIB<#i}+xin5f>YeESV@b8Jlq$b)KCN;$+?K5p2OzcE^>_xotnZ6vcb6$Kb=eR-i z`DNb&Qvwo~&}8=~TBiB+eSNi}FCfwGmrtBTM;pkwNVXECAp$GM{%|YmMEf~gvsN4t`mFNh%H+_RD#@5GP>QAe~)EKU$Cbx7e@Hi2|H2M`~*Hfe+#sc-S;OIsq$HMH|`oo(VK3~ zV+U#P))Ix|2m3w>T7SSJs*EBE=MwR%K#=Ewk0Rp~`887%j%UP2$izwEG0Dl<<5J}p zkOwmGC9&mrXly?~igx}<(W7d?sv>9CShF`v#_&sDV$CJ@^MhVuajy;N@vkCyO&s>F zp2HTt)}OyxRF?NzzV1efK#~vVhh9JjA{1$EV4-hBbZe&Iu4NY+`$lDNMM9Plzg&w^ zPVQtOdm{M*JK2~$!}#0`mbK@*8A>EspYt;+J5%nxv$OW!%#@73QV^M(YM(`V%L-u{ zDhch=%(LU$YisvFtlf5!99YN--;9p_E*-ez|At!R_+oa)nc zj$mJ?;T+TLjmA~O@V#NYuOFMT_df+(dsp5ih5GPBB1QgKjl?@2#C2^wEZBOa%GMXr z>*0}&nXPi*i)?6Vq_LYyL7?}q7uc-QyZESI*``tlp}@Cqae8;+0o3t}i1KvuEcL;k zs#*#0jCRW|@LP%BLyr3ozS+KfE%+I9Jn)7Z_jXoH$#1sT5q}CjT9E#V@3dQ z9{MW*yY&t5*HZyg|B_!y{3benx$Q6cdB?z?L8IIAk9-^f=v~fJtsReCQD<-R+B2hZ zktXS+d-bA6hEEgSXYeamPFG$vx-($2f}O`|B-aSADTP~1Q&4h~cri`5>OcxfXWn~1 zzG$*mVH(YwFVB}@Qy={uE=|tI8NNrXFxPz z*^*_Ah1@wdtSsE=`iLr{TQlurn(V4BwOn!x;iai^=yozwBTWY$pDJ^XWGtPWEMIyK zdD~#bhdGNUS2uP)DRUe=+ztQwfr5B!$-;#qinfI!3d#kKQUgKGds(r4!713kKvV4h zCbzH(J20G&4sQsGx0v#0W95(UZpu#q&iCd_6VJy-=UC&r=iD7{ z$+;_GLqNXQ@e^LR+P@`b51?w;*~$;VzoLSo{-bjA8&0~%J9~*ITK3?@_u&A}*;0ew zgqB)rtx}pGk3!CQ^Xutth0p1VvQ4 zFQ609nRo($l42Dk)hqr*z<^v&xJ+4y&V4wj*DW((m5J{yyY2 zxf%8os=HBkp-8HN~{~ZmgvkDI5mi-!nY610sdga)?kQ))OXweKTV(`U~U1ZsElfYEyk4 zN-I~Fo_RVckMkEw3+7eLjp2S+qBb*Ffp!TWSbX7r?~P0mWn=be#L2rWF_iSrks&KzcD5M$QICV~>Kx+%CvZZ6VFqnM@I?1WRyL>J!KA zr`|Jdbify5nz9ey?{^!`%0JCk(|a{TzsPcpqi2QKU3f^uw8<63bRP`vGXljoeCq$S zb8>4{EHpFg2l4&PXb%28Nwpv!KnUZPwO-H{VsU=%gZ^g94X1$mz%PjV&1_eBs8d&G zde2AAM|nfPlsp2I#I>0=KTg&#j&7gb9VYiwEFH04n7JTF!9i=?<&t|;2hz-=Kc(B0 zYalxvY21i$bSdsY*T?H>?HEM!gZ!=x*Qe&nMK0$xRf+=T3MiKpd_il%UnwZ*QqT$o zf6AY(OeDWGq-!=y{X@`*RQq~mQco@T;|MwBY?Om|O_{#;Lp3bpnocQrH0(~PnW|8& zc{%Jq+5WPk@$zPRxT%-{?!W}OFZ9W2YEUOBe%dN3NG?TW*yyI^(-%lCkM@dAbywoP zS&z}KRpqaFcXhEXraBbSfflU{KLlX^;^q|7wL(kdHv0B`+YmYhDN+|`%Kscf_{Z#n z1QNhH40Gt*wZ2L$#WnbXGtRMp9k|1}sgas(mLJ8!pe{66R@@!Gp&?}$MtLWB!cG^b zdlv1TZKvsCC!>)$8fiTF{2cOKQuWA^C54gzcoz@nncRGr({OzXuVq1{l)*}Orc3L| zmnKW){Ev|Ox3}iKolN zQ{A7}=OJpB7trRvUs(|v@P5hvCVSxHTXZ38!^eZHZEC!%)jYxPro5(uhx~;h_=xkF zHV4zZ*pDSm^OZQ3>uU7tTiMSa4{(lvsOs~{364g}f7V~vge-nH{VJ_a@E1-2r*jRU zJW?K=T>Z)S`wPRtnkfi=H_7`vq)$EaQ2oE$z6FYv#wz|lt5>JP>ujn!95cONsM3r6 zZE8JeIcT7_T15xL449VLoX<0b#B73mh0%ao;?A4g)LNywt}{{UVqh|vxW+szOZY8S zeoN>#kV1imK@?2*;U(Gq-g}%Ql=<LG^Mcf?($Ii50UKKAb0JK24%-!Q`1U;+Q|)w zVHdZ~a@BOu6{u(7l}fC&&8N=e$&I681n-)}-l&+)pWDE$RJ0G-NHMo8DsBOBAnv&7 z8y~2(RllIb3SmAOOq+l?Z7LAq{8+ECiWSRNjIk_S^1!kc59ZjHTCx^8mgEdqj*c|m#0MW6y zHt$GMS=o`rI{nHe%a*g=N3AU5=!~+`qZL7AYrh=dGobdO75`UHqx0obM1k7h=nsRq zl6Qi*?WIO+SpoQ!U;uc&-Gkg@pEdp($ zN~3Y&xF`?{_60pNu#d9@ymtUc0Ve@x0sQ_Tt`{I25Cs?w==__6?-alSz;Zx7U@Kq` zpbBsd&;+;u2zob&y9F>BFb%K>@C0BhpcLSJH^|8y$HzIqWxx&Z1#yvp&c8AEo^)OM zetgdZJPcR^*aX-CcneStI0QHXI1Xq6{0KM)xD3#j2XRI~Z@>UR6dA z0J8y$04o5i08ax70M7z;16~Kb1NZa3NXBnUIc^#I{yaado<6F*M?o&szE>;&uqlmiX}jss2sE&>c6p!R@afX=@$_?`xs4R{!^3a|yR8}Jt3 z0HE{lIKEE;&H*k1^e`(rZCC#Om+ZjVX$b#Ic7X9$4dH*u4ru%pLjeBYu!A7g5XxRS zb&tOL5q@RPioe@eaAjY~gL#++`KA8{NSt)S4Kg+d9Iu6*?GD{|DD#3TLR0_T5M!T)Fe&PF(?KLsfHpMbPfTS{ktErQPf8{l}W XUsBTWNzFfUkgH;JX delta 19102 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 //Select upper 8 bits 1 cycles 1 + localipl = (ipl>>8)<<1; //Select upper 8 bits 1 cycles 1 *** AS/IS: 4 - // need to load Z with 'sintable' and add localipl 2 - s1 = sintable[localipl++]; //Read s1 component out of table. 2+2 cycles 2 - c1 = sintable[localipl++]; //Read c1 component out of table. 2 cycles 2 + st = &sintable[localipl]; + s1 = *(st++); //Read s1 component out of table. 2+2 cycles 2 + c1 = *st; //Read c1 component out of table. 2 cycles 2 *** AS/IS: 4 - ts = (s1 * sample1); // 8 x 8 multiply signed + copy R1 out. zero MSB ts 2 - tc = (c1 * sample1); // 8 x 8 multiply signed + copy R1 out. zero MSB tc 2 + ts = (s1 * sample1); // 8 x 8 multiply signed + copy R1 out. zero MSB ts 2 ->Deferred + tc = (c1 * sample1); // 8 x 8 multiply signed + copy R1 out. zero MSB tc 2 ->Deferred //15 cycles MIN ipl += adv; //Advance, 16bit += 16bit, 1 + 1 cycles 2 - localipl = (ipl>>8)<<1; //Select upper 8 bits 1 cycles 1 + localipl = (ipl>>8)<<1; //Select upper 8 bits 1 cycles 1 *** AS/IS: 4 // need to load Z with 'sintable' and add localipl 2 - s1 = sintable[localipl++]; //Read s1 component out of table. 2 cycles 2 - c1 = sintable[localipl++]; //Read c1 component out of table. 2 cycles 2 + st = &sintable[localipl]; + s1 = *(st++); //Read s1 component out of table. 2 cycles 2 + c1 = *st; //Read c1 component out of table. 2 cycles 2 *** AS/IS: 4 - ts += (s1 * sample2); // 8 x 8 multiply signed + add R1 out. 3 - tc += (c1 * sample2); // 8 x 8 multiply signed + add R1 out. 3 + ts += (s1 * sample2); // 8 x 8 multiply signed + add R1 out. 3 ->Deferred + tc += (c1 * sample2); // 8 x 8 multiply signed + add R1 out. 3 ->Deferred //Add TS and TC to the datspace stuff. (24 instructions) - tmp1 = datspace[startpl]; //Read out, sin component. 4 - tmp1 -= tmp1>>6; //Subtract from the MSB (with carry) 2 - tmp1 += ts>>6; //Add MSBs with carry 2 + tmp1 = (*ds); //Read out, sin component. 4 Accurate. + tmp1 -= tmp1>>7; //Subtract from the MSB (with carry) 2 -> 6 AS/IS: 7+7 = 14 + tmp1 += ts>>7; //Add MSBs with carry 2 -> 6 AS/IS: 6 - datspace[startpl++] = tmp1; //Store values back 4 + *(ds++) = tmp1; //Store values back 4 - tmp1 = datspace[startpl]; //Read out, sin component. 4 - tmp1 -= tmp1>>6; //Subtract from the MSB (with carry) 2 - tmp1 += tc>>6; //Add MSBs with carry 2 + tmp1 = *ds; //Read out, sin component. 4 + tmp1 -= tmp1>>7; //Subtract from the MSB (with carry) 2 -> 6 AS/IS: 7+7 = 14 + tmp1 += tc>>7; //Add MSBs with carry 2 -> 6 AS/IS: 6 - datspace[startpl++] = tmp1; //Store values back 4 + *ds++ = tmp1; //Store values back 4 - datspace[startpl-3] = ipl; //Store values back 4 + *(ds-3) = ipl; //Store values back 4 AS/IS: 6 + + //AS-IS: 8 loop overhead. } } - void DoDFTProgressiveInteger( float * outbins, float * frequencies, int bins, const float * databuffer, int place_in_data_buffer, int size_of_data_buffer, float q, float speedup ) { int i; @@ -326,3 +323,220 @@ void DoDFTProgressiveInteger( float * outbins, float * frequencies, int bins, co } + + + + + + + + + + + + +////////////////////////SKIPPY DFT + +//Skippy DFT is a very ood one. + + + +#define OCTAVES 5 +#define FIXBPERO 24 +#define FIXBINS (FIXBPERO*OCTAVES) +#define BINCYCLE (1< 128 ) + { + //Special: This is when we can update everything. + +/* if( (rand()%100) == 0 ) + { + for( i = 0; i < FIXBINS; i++ ) +// printf( "%0.2f ",goutbins[i]*100 ); + printf( "(%d %d)",Sdatspace[i*4+2], Sdatspace[i*4+3] ); + printf( "\n" ); + } */ + + for( i = 0; i < FIXBINS; i++ ) + { + int16_t isps = Sdatspace[i*4+2]; + int16_t ispc = Sdatspace[i*4+3]; + int16_t mux = ( (isps/256) * (isps/256)) + ((ispc/256) * (ispc/256)); + // printf( "%d (%d %d)\n", mux, isps, ispc ); + + int octave = i / FIXBPERO; +// mux >>= octave; + goutbins[i] = sqrt( mux ); +// goutbins[i]/=100.0; + goutbins[i]/=100*(1<>5; + Sdatspace[i*4+3] -= ispc>>5; + } + + } + + for( i = 0; i < OCTAVES;i++ ) + { + Saccum_octavebins[i] += sample1; + } + + uint16_t * ds = &Sdatspace[oct*FIXBPERO*4]; + int8_t * st; + + sample1 = Saccum_octavebins[oct]>>(OCTAVES-oct); + Saccum_octavebins[oct] = 0; + + for( i = 0; i < FIXBPERO; i++ ) //Loop, fixed size = 3 + 2 cycles N/A + { + //12 cycles MIN + adv = *(ds++); //Read, indirect from RAM (and increment) 2+2 cycles 4 + ipl = *(ds++); //Read, indirect from RAM (and increment) 2+2 cycles 4 + + //13 cycles MIN + ipl += adv; //Advance, 16bit += 16bit, 1 + 1 cycles 2 + localipl = (ipl>>8)<<1; //Select upper 8 bits 1 cycles 1 *** AS/IS: 4 + + st = &Ssintable[localipl]; + s1 = *(st++); //Read s1 component out of table. 2+2 cycles 2 + c1 = *st; //Read c1 component out of table. 2 cycles 2 *** AS/IS: 4 + + ts = (s1 * sample1); // 8 x 8 multiply signed + copy R1 out. zero MSB ts 2 ->Deferred + tc = (c1 * sample1); // 8 x 8 multiply signed + copy R1 out. zero MSB tc 2 ->Deferred + + + //Add TS and TC to the datspace stuff. (24 instructions) + tmp1 = (*ds); //Read out, sin component. 4 Accurate. +// tmp1 -= tmp1>>4; //Subtract from the MSB (with carry) 2 -> 6 AS/IS: 7+7 = 14 + tmp1 += ts>>3; //Add MSBs with carry 2 -> 6 AS/IS: 6 + + *(ds++) = tmp1; //Store values back 4 + + tmp1 = *ds; //Read out, sin component. 4 +// tmp1 -= tmp1>>4; //Subtract from the MSB (with carry) 2 -> 6 AS/IS: 7+7 = 14 + tmp1 += tc>>3; //Add MSBs with carry 2 -> 6 AS/IS: 6 + + *ds++ = tmp1; //Store values back 4 + + *(ds-3) = ipl; //Store values back 4 AS/IS: 6 + + //AS-IS: 8 loop overhead. + } +} + +void DoDFTProgressiveIntegerSkippy( float * outbins, float * frequencies, int bins, const float * databuffer, int place_in_data_buffer, int size_of_data_buffer, float q, float speedup ) +{ + static float backupbins[FIXBINS]; + int i, j; + static int last_place; + +//printf( "SKIPPY\n" ); + + if( !Sdonefirstrun ) + { + memset( outbins, 0, bins * sizeof( float ) ); + goutbins = outbins; + //Sdatspace = malloc(FIXBPERO*OCTAVES*8); + //memset(Sdatspace,0,FIXBPERO*OCTAVES*8); + //printf( "MS: %d\n", FIXBPERO*OCTAVES*8); + Sdonefirstrun = 1; + for( i = 0; i < 256; i++ ) + { + Ssintable[i*2+0] = (int8_t)((sinf( i / 256.0 * 6.283 ) * 127.0)); + Ssintable[i*2+1] = (int8_t)((cosf( i / 256.0 * 6.283 ) * 127.0)); + } + + for( i = 0; i < BINCYCLE; i++ ) + { + // Sdo_this_octave = + // 4 3 4 2 4 3 4 ... + //search for "first" zero + + for( j = 0; j <= OCTAVES; j++ ) + { + if( ((1< OCTAVES ) + { + fprintf( stderr, "Error: algorithm fault.\n" ); + exit( -1 ); + } + Sdo_this_octave[i] = OCTAVES-j-1; + } + } + + memcpy( outbins, backupbins, FIXBINS*4 ); + + if( FIXBINS != bins ) + { + fprintf( stderr, "Error: Bins was reconfigured. skippy requires a constant number of bins.\n" ); + return; + } + + + for( i = 0; i < bins; i++ ) + { + float freq = frequencies[(i%FIXBPERO) + (FIXBPERO*(OCTAVES-1))]; + Sdatspace[i*4] = (65536.0/freq);// / oneoveroctave; + } + + + for( i = last_place; i != place_in_data_buffer; i = (i+1)%size_of_data_buffer ) + { + int8_t ifr1 = (int8_t)( ((databuffer[i]) ) * 127 ); + HandleProgressiveIntSkippy( ifr1 ); + HandleProgressiveIntSkippy( ifr1 ); + } + + last_place = place_in_data_buffer; + + memcpy( backupbins, outbins, FIXBINS*4 ); + + //Extract bins. +/* + for( i = 0; i < bins; i++ ) + { + int16_t isps = Sdatspace[i*4+2]; + int16_t ispc = Sdatspace[i*4+3]; + int16_t mux = ( (isps/256) * (isps/256)) + ((ispc/256) * (ispc/256)); +// printf( "%d (%d %d)\n", mux, isps, ispc ); + outbins[i] = sqrt( mux )/100.0; + } +*/ + +// printf( "\n"); +} + + + + + + diff --git a/dft.h b/dft.h index bae53b5..944b949 100644 --- a/dft.h +++ b/dft.h @@ -1,14 +1,16 @@ #ifndef _DFT_H #define _DFT_H -//XXX WARNING: TODO: the last two parameters are a double due to a compiler bug. + +//There are several options here, the last few are selectable by modifying the do_progressive_dft flag. + //Do a DFT on a live audio ring buffer. It assumes new samples are added on in the + direction, older samples go negative. //Frequencies are as a function of the samplerate, for example, a frequency of 22050 is actually 2 Hz @ 44100 SPS //bins = number of frequencies to check against. void DoDFT( float * outbins, float * frequencies, int bins, float * databuffer, int place_in_data_buffer, int size_of_data_buffer, float q ); -//Skip many of the samples on lower frequencies; TODO: Need to fix the nyquist problem where high frequencies show low-frequency components. +//Skip many of the samples on lower frequencies. //Speedup = target number of data points void DoDFTQuick( float * outbins, float * frequencies, int bins, const float * databuffer, int place_in_data_buffer, int size_of_data_buffer, float q, float speedup ); @@ -16,8 +18,14 @@ void DoDFTQuick( float * outbins, float * frequencies, int bins, const float * d void DoDFTProgressive( float * outbins, float * frequencies, int bins, const float * databuffer, int place_in_data_buffer, int size_of_data_buffer, float q, float speedup ); //A progressive DFT that's done using only low-bit integer math. +//This is almost fast enough to work on an AVR, with two AVRs, it's likely that it could be powerful enough. +//This is fast enough to run on an ESP8266 void DoDFTProgressiveInteger( float * outbins, float * frequencies, int bins, const float * databuffer, int place_in_data_buffer, int size_of_data_buffer, float q, float speedup ); +//Everything the integer one buys, except it only calculates 2 octaves worth of notes per audio frame. +//This is sort of working, but still have some quality issues. +//It would theoretically be fast enough to work on an AVR. +void DoDFTProgressiveIntegerSkippy( float * outbins, float * frequencies, int bins, const float * databuffer, int place_in_data_buffer, int size_of_data_buffer, float q, float speedup ); #endif diff --git a/integerprog.conf b/integerprog.conf index d321461..62f5ad6 100644 --- a/integerprog.conf +++ b/integerprog.conf @@ -1,5 +1,5 @@ -do_progressive_dft = 1 +do_progressive_dft = 3 samplerate = 8000 -buffer = 128 - +buffer = 64 +sourcename = alsa_output.pci-0000_00_1b.0.analog-stereo.monitor diff --git a/main.c b/main.c index be4cd84..3664a82 100644 --- a/main.c +++ b/main.c @@ -14,6 +14,8 @@ #include "outdrivers.h" #include "parameters.h" +#define NRDEFFILES 10 + struct SoundDriver * sd; #ifdef WIN32 @@ -32,6 +34,7 @@ char ** gargv; struct DriverInstances * outdriver[MAX_OUT_DRIVERS]; +int headless = 0; REGISTER_PARAM( headless, PAINT ); int set_screenx = 640; REGISTER_PARAM( set_screenx, PAINT ); int set_screeny = 480; REGISTER_PARAM( set_screeny, PAINT ); char sound_source[16]; REGISTER_PARAM( sound_source, PABUFFER ); @@ -95,9 +98,12 @@ void SoundCB( float * out, float * in, int samplesr, int * samplesp, struct Soun for( j = 0; j < channelin; j++ ) { float f = in[i*channelin+j]; - if( f < -1 || f > 1 ) continue; - fo += f; + if( f > -1 && f < 1 ) + { + fo += f; + } } + fo /= channelin; sound[soundhead] = fo; soundhead = (soundhead+1)%SOUNDCBSIZE; @@ -106,9 +112,11 @@ void SoundCB( float * out, float * in, int samplesr, int * samplesp, struct Soun else { float f = in[i*channelin+sample_channel]; - if( f < -1 || f > 1 ) continue; - sound[soundhead] = f; - soundhead = (soundhead+1)%SOUNDCBSIZE; + if( f > -1 && f < 1 ) + { + sound[soundhead] = f; + soundhead = (soundhead+1)%SOUNDCBSIZE; + } } } } @@ -118,7 +126,6 @@ void LoadFile( const char * filename ) { char * buffer; int r; - int i; FILE * f = fopen( filename, "rb" ); if( !f ) @@ -144,26 +151,69 @@ void LoadFile( const char * filename ) } free( buffer ); } +} - if( gargc > 2 ) +const char * InitialFile[NRDEFFILES]; +double FileTimes[NRDEFFILES]; +int InitialFileCount = 1; + +void SetEnvValues() +{ + int i; + int hits = 0; + for( i = 0; i < InitialFileCount; i++ ) { - for( i = 2; i < gargc; i++ ) + double ft = OGGetFileTime( InitialFile[i] ); + if( FileTimes[i] != ft ) + { + FileTimes[i] = ft; + hits++; + } + } + + if( !hits ) return; + + //Otherwise, something changed. + + LoadFile( InitialFile[0] ); + + for( i = 1; i < gargc; i++ ) + { + if( strchr( gargv[i], '=' ) != 0 ) { printf( "AP: %s\n", gargv[i] ); SetParametersFromString( gargv[i] ); } + else + { + printf( "LF: %s\n", gargv[i] ); + LoadFile( gargv[i] ); + } } } +void ProcessArgs() +{ + int i; + for( i = 1; i < gargc; i++ ) + { + if( strchr( gargv[i], '=' ) != 0 ) + { + //A value setting operation + } + else + { + InitialFile[InitialFileCount++] = gargv[i]; + } + } + + SetEnvValues(); +} + int main(int argc, char ** argv) { -// const char * OutDriver = "name=LEDOutDriver;leds=512;light_siding=1.9"; - const char * InitialFile = 0; - const char * InitialFileDefault = "default.conf"; int i; - double LastFileTimeInit = 0; - double LastFileTimeDefault = 0; #ifdef WIN32 WSADATA wsaData; @@ -178,23 +228,9 @@ int main(int argc, char ** argv) gargc = argc; gargv = argv; - if( argc > 1 ) - { - InitialFile = argv[1]; - } - - - { - LastFileTimeDefault = OGGetFileTime( InitialFileDefault ); - LoadFile( InitialFileDefault ); - } - - if( InitialFile ) - { - LastFileTimeInit = OGGetFileTime( InitialFile ); - LoadFile( InitialFile ); - } + InitialFile[0] = "default.conf"; + ProcessArgs(); //Initialize Rawdraw int frames = 0; @@ -219,7 +255,8 @@ int main(int argc, char ** argv) tp++; } *tp = 0; - CNFGSetup( title, set_screenx, set_screeny ); + if( !headless ) + CNFGSetup( title, set_screenx, set_screeny ); char * OutDriverNames = strdup( GetParameterS( "outdrivers", "null" ) ); @@ -266,10 +303,14 @@ int main(int argc, char ** argv) { char stt[1024]; //Handle Rawdraw frame swappign - CNFGHandleInput(); - CNFGClearFrame(); - CNFGColor( 0xFFFFFF ); - CNFGGetDimensions( &screenx, &screeny ); + + if( !headless ) + { + CNFGHandleInput(); + CNFGClearFrame(); + CNFGColor( 0xFFFFFF ); + CNFGGetDimensions( &screenx, &screeny ); + } RunNoteFinder( nf, sound, (soundhead-1+SOUNDCBSIZE)%SOUNDCBSIZE, SOUNDCBSIZE ); //Done all ColorChord work. @@ -281,123 +322,127 @@ int main(int argc, char ** argv) VisTimeEnd = OGGetAbsoluteTime(); - //Handle outputs. - int freqbins = nf->freqbins; - int note_peaks = freqbins/2; - int freqs = freqbins * nf->octaves; - //int maxdists = freqbins/2; - - //Do a bunch of debugging. - if( show_debug_basic ) + if( !headless ) { - for( i = 0; i < nf->dists; i++ ) + //Handle outputs. + int freqbins = nf->freqbins; + int note_peaks = freqbins/2; + int freqs = freqbins * nf->octaves; + //int maxdists = freqbins/2; + + //Do a bunch of debugging. + if( show_debug_basic ) { - CNFGPenX = (nf->dist_means[i] + 0.5) / freqbins * screenx; //Move over 0.5 for visual purposes. The means is correct. - CNFGPenY = 400-nf->dist_amps[i] * 150.0 / nf->dist_sigmas[i]; - //printf( "%f %f\n", dist_means[i], dist_amps[i] ); - sprintf( stt, "%f\n%f\n", nf->dist_means[i], nf->dist_amps[i] ); - CNFGDrawText( stt, 2 ); + for( i = 0; i < nf->dists; i++ ) + { + CNFGPenX = (nf->dist_means[i] + 0.5) / freqbins * screenx; //Move over 0.5 for visual purposes. The means is correct. + CNFGPenY = 400-nf->dist_amps[i] * 150.0 / nf->dist_sigmas[i]; + //printf( "%f %f\n", dist_means[i], dist_amps[i] ); + sprintf( stt, "%f\n%f\n", nf->dist_means[i], nf->dist_amps[i] ); + CNFGDrawText( stt, 2 ); + } + CNFGColor( 0xffffff ); + + //Draw the folded bins + for( i = 0; i < freqbins; i++ ) + { + float x0 = i / (float)freqbins * (float)screenx; + float x1 = (i+1) / (float)freqbins * (float)screenx; + float amp = nf->folded_bins[i] * 250.0; + CNFGDialogColor = CCtoHEX( ((float)(i+0.5) / freqbins), 1.0, 1.0 ); + CNFGDrawBox( x0, 400-amp, x1, 400 ); + } + CNFGDialogColor = 0xf0f000; + + for( i = 0; i < note_peaks; i++ ) + { + //printf( "%f %f /", note_positions[i], note_amplitudes[i] ); + if( nf->note_amplitudes_out[i] < 0 ) continue; + CNFGDialogColor = CCtoHEX( (nf->note_positions[i] / freqbins), 1.0, 1.0 ); + CNFGDrawBox( ((float)i / note_peaks) * screenx, 480 - nf->note_amplitudes_out[i] * 100, ((float)(i+1) / note_peaks) * screenx, 480 ); + CNFGPenX = ((float)(i+.4) / note_peaks) * screenx; + CNFGPenY = screeny - 30; + sprintf( stt, "%d\n%0.0f", nf->enduring_note_id[i], nf->note_amplitudes2[i]*1000.0 ); + CNFGDrawText( stt, 2 ); + + } + + //Let's draw the o-scope. + int thissoundhead = soundhead; + thissoundhead = (thissoundhead-1+SOUNDCBSIZE)%SOUNDCBSIZE; + int lasty = sound[thissoundhead] * 128 + 128; thissoundhead = (thissoundhead-1+SOUNDCBSIZE)%SOUNDCBSIZE; + int thisy = sound[thissoundhead] * 128 + 128; thissoundhead = (thissoundhead-1+SOUNDCBSIZE)%SOUNDCBSIZE; + for( i = 0; i < screenx; i++ ) + { + CNFGTackSegment( i, lasty, i+1, thisy ); + lasty = thisy; + thisy = sound[thissoundhead] * 128 + 128; thissoundhead = (thissoundhead-1+SOUNDCBSIZE)%SOUNDCBSIZE; + } } + + //Extra debugging? + if( show_debug ) + { + //Draw the histogram + float lasthistval; + CNFGColor( 0xffffff ); + + for( i = -1; i < screenx; i++ ) + { + float thishistval = CalcHistAt( (float)i/(float)screenx*freqbins-0.5, nf->freqbins, nf->dist_means, nf->dist_amps, nf->dist_sigmas, nf->dists ); + if( i >= 0 ) + CNFGTackSegment( i, 400-lasthistval * 250.0, i+1, 400-thishistval * 250.0 ); + lasthistval = thishistval; + } + + CNFGColor( 0xffffff ); + + //Draw the bins + for( i = 0; i < freqs; i++ ) + { + float x0 = i / (float)freqs * (float)screenx; + float x1 = (i+1) / (float)freqs * (float)screenx; + float amp = nf->outbins[i] * 250.0; + CNFGDialogColor = CCtoHEX( ((float)i / freqbins), 1.0, 1.0 ); + CNFGDrawBox( x0, 0, x1, amp ); + } + CNFGDialogColor = 0x0f0f0f; + + char stdebug[1024]; + sprintf( stdebug, "DFT:%8.2fms\nFLT:%8.2f\nDEC:%8.2f\nFNL:%8.2f\nDPY:%8.2f", + (nf->DFTTime - nf->StartTime)*1000, + (nf->FilterTime - nf->DFTTime)*1000, + (nf->DecomposeTime - nf->FilterTime)*1000, + (nf->FinalizeTime - nf->DecomposeTime)*1000, + (VisTimeEnd - VisTimeStart)*1000 ); + CNFGPenX = 50; + CNFGPenY = 50; + CNFGDrawText( stdebug, 2 ); + } + + CNFGColor( show_debug?0xffffff:0x000000 ); + CNFGPenX = 0; CNFGPenY = screeny-10; + CNFGDrawText( "Extra Debug (D)", 2 ); + + CNFGColor( show_debug_basic?0xffffff:0x000000 ); + CNFGPenX = 120; CNFGPenY = screeny-10; + CNFGDrawText( "Basic Debug (E)", 2 ); + + CNFGColor( show_debug_basic?0xffffff:0x000000 ); + CNFGPenX = 240; CNFGPenY = screeny-10; + sprintf( stt, "[9] Key: %d [0] (%3.1f) [-]", gKey, nf->base_hz ); + CNFGDrawText( stt, 2 ); + CNFGColor( 0xffffff ); - - //Draw the folded bins - for( i = 0; i < freqbins; i++ ) - { - float x0 = i / (float)freqbins * (float)screenx; - float x1 = (i+1) / (float)freqbins * (float)screenx; - float amp = nf->folded_bins[i] * 250.0; - CNFGDialogColor = CCtoHEX( ((float)(i+0.5) / freqbins), 1.0, 1.0 ); - CNFGDrawBox( x0, 400-amp, x1, 400 ); - } - CNFGDialogColor = 0xf0f000; - - for( i = 0; i < note_peaks; i++ ) - { - //printf( "%f %f /", note_positions[i], note_amplitudes[i] ); - if( nf->note_amplitudes_out[i] < 0 ) continue; - CNFGDialogColor = CCtoHEX( (nf->note_positions[i] / freqbins), 1.0, 1.0 ); - CNFGDrawBox( ((float)i / note_peaks) * screenx, 480 - nf->note_amplitudes_out[i] * 100, ((float)(i+1) / note_peaks) * screenx, 480 ); - CNFGPenX = ((float)(i+.4) / note_peaks) * screenx; - CNFGPenY = screeny - 30; - sprintf( stt, "%d\n%0.0f", nf->enduring_note_id[i], nf->note_amplitudes2[i]*1000.0 ); - CNFGDrawText( stt, 2 ); - - } - - //Let's draw the o-scope. - int thissoundhead = soundhead; - thissoundhead = (thissoundhead-1+SOUNDCBSIZE)%SOUNDCBSIZE; - int lasty = sound[thissoundhead] * 128 + 128; thissoundhead = (thissoundhead-1+SOUNDCBSIZE)%SOUNDCBSIZE; - int thisy = sound[thissoundhead] * 128 + 128; thissoundhead = (thissoundhead-1+SOUNDCBSIZE)%SOUNDCBSIZE; - for( i = 0; i < screenx; i++ ) - { - CNFGTackSegment( i, lasty, i+1, thisy ); - lasty = thisy; - thisy = sound[thissoundhead] * 128 + 128; thissoundhead = (thissoundhead-1+SOUNDCBSIZE)%SOUNDCBSIZE; - } + CNFGPenX = 440; CNFGPenY = screeny-10; + sprintf( stt, "FPS: %d", lastfps ); + CNFGDrawText( stt, 2 ); + CNFGSwapBuffers(); } - //Extra debugging? - if( show_debug ) - { - //Draw the histogram - float lasthistval; - CNFGColor( 0xffffff ); - - for( i = -1; i < screenx; i++ ) - { - float thishistval = CalcHistAt( (float)i/(float)screenx*freqbins-0.5, nf->freqbins, nf->dist_means, nf->dist_amps, nf->dist_sigmas, nf->dists ); - if( i >= 0 ) - CNFGTackSegment( i, 400-lasthistval * 250.0, i+1, 400-thishistval * 250.0 ); - lasthistval = thishistval; - } - - CNFGColor( 0xffffff ); - - //Draw the bins - for( i = 0; i < freqs; i++ ) - { - float x0 = i / (float)freqs * (float)screenx; - float x1 = (i+1) / (float)freqs * (float)screenx; - float amp = nf->outbins[i] * 250.0; - CNFGDialogColor = CCtoHEX( ((float)i / freqbins), 1.0, 1.0 ); - CNFGDrawBox( x0, 0, x1, amp ); - } - CNFGDialogColor = 0x0f0f0f; - - char stdebug[1024]; - sprintf( stdebug, "DFT:%8.2fms\nFLT:%8.2f\nDEC:%8.2f\nFNL:%8.2f\nDPY:%8.2f", - (nf->DFTTime - nf->StartTime)*1000, - (nf->FilterTime - nf->DFTTime)*1000, - (nf->DecomposeTime - nf->FilterTime)*1000, - (nf->FinalizeTime - nf->DecomposeTime)*1000, - (VisTimeEnd - VisTimeStart)*1000 ); - CNFGPenX = 50; - CNFGPenY = 50; - CNFGDrawText( stdebug, 2 ); - } - - CNFGColor( show_debug?0xffffff:0x000000 ); - CNFGPenX = 0; CNFGPenY = screeny-10; - CNFGDrawText( "Extra Debug (D)", 2 ); - - CNFGColor( show_debug_basic?0xffffff:0x000000 ); - CNFGPenX = 120; CNFGPenY = screeny-10; - CNFGDrawText( "Basic Debug (E)", 2 ); - - CNFGColor( show_debug_basic?0xffffff:0x000000 ); - CNFGPenX = 240; CNFGPenY = screeny-10; - sprintf( stt, "[9] Key: %d [0] (%3.1f) [-]", gKey, nf->base_hz ); - CNFGDrawText( stt, 2 ); - - CNFGColor( 0xffffff ); - CNFGPenX = 440; CNFGPenY = screeny-10; - sprintf( stt, "FPS: %d", lastfps ); - CNFGDrawText( stt, 2 ); - //Finish Rawdraw with FPS counter, and a nice delay loop. frames++; - CNFGSwapBuffers(); + ThisTime = OGGetAbsoluteTime(); if( ThisTime > LastFPSTime + 1 ) { @@ -416,18 +461,7 @@ int main(int argc, char ** argv) OGUSleep( (int)( SecToWait * 1000000 ) ); } - if( OGGetFileTime( InitialFileDefault ) != LastFileTimeDefault || - (InitialFile && LastFileTimeInit != OGGetFileTime( InitialFile ) ) ) - { - LastFileTimeDefault = OGGetFileTime( InitialFileDefault ); - LoadFile( InitialFileDefault ); - - if( InitialFile ) - { - LastFileTimeInit = OGGetFileTime( InitialFile ); - LoadFile( InitialFile ); - } - } + SetEnvValues(); } diff --git a/netlight.conf b/netlight.conf index dd2a2e2..13ee3b5 100644 --- a/netlight.conf +++ b/netlight.conf @@ -1,12 +1,12 @@ -outdrivers = DisplayNetwork, OutputLinear +outdrivers = DisplayPie,DisplayNetwork, OutputLinear leds = 296 light_siding = 1.0 #Turn this to ~1.9 for more uniformity, ~1.0 for less. satamp = 1.600 is_loop=0 led_floor = .1 #Turn to .25 for more uniformity, .1 for less. -note_attach_amp_iir = .3000 -note_attach_amp_iir2 = .1500 -note_attach_freq_iir = 0.3000 +#note_attach_amp_iir = .3 #.3000 +#note_attach_amp_iir2 = .15 #.1500 +#note_attach_freq_iir = .3 #0.3000 steady_bright = 0 #dft_iir = 0.0 #dft_q = 20.0000 @@ -17,3 +17,10 @@ firstval = 0 port = 7777 address = 192.168.0.245 +slope=.10 +amplify=.3 + + +lightx = 20 +lighty = 20 + diff --git a/notefinder.c b/notefinder.c index 11078c8..3322929 100644 --- a/notefinder.c +++ b/notefinder.c @@ -25,6 +25,7 @@ struct NoteFinder * CreateNoteFinder( int spsRec ) ret->decompose_iterations = 1000; ret->dft_speedup = 300; ret->dft_q = 16; + ret->slope = 0.0; ret->do_progressive_dft = 0; ret->default_sigma = 1.4; ret->note_jumpability = 2.5; @@ -53,6 +54,7 @@ struct NoteFinder * CreateNoteFinder( int spsRec ) RegisterValue( "default_sigma", PAFLOAT, &ret->default_sigma, sizeof( ret->default_sigma ) ); RegisterValue( "note_jumpability", PAFLOAT, &ret->note_jumpability, sizeof( ret->note_jumpability ) ); RegisterValue( "note_combine_distance", PAFLOAT, &ret->note_combine_distance, sizeof( ret->note_combine_distance ) ); + RegisterValue( "slope", PAFLOAT, &ret->slope, sizeof( ret->slope ) ); RegisterValue( "note_attach_freq_iir", PAFLOAT, &ret->note_attach_freq_iir, sizeof( ret->note_attach_freq_iir ) ); RegisterValue( "note_attach_amp_iir", PAFLOAT, &ret->note_attach_amp_iir, sizeof( ret->note_attach_amp_iir ) ); RegisterValue( "note_attach_amp_iir2", PAFLOAT, &ret->note_attach_amp_iir2, sizeof( ret->note_attach_amp_iir2 ) ); @@ -188,6 +190,9 @@ void RunNoteFinder( struct NoteFinder * nf, const float * audio_stream, int head case 2: DoDFTProgressiveInteger( dftbins, nf->frequencies, freqs, audio_stream, head, buffersize, nf->dft_q, nf->dft_speedup ); break; + case 3: + DoDFTProgressiveIntegerSkippy( dftbins, nf->frequencies, freqs, audio_stream, head, buffersize, nf->dft_q, nf->dft_speedup ); + break; default: fprintf( stderr, "Error: No DFT Seleced\n" ); } @@ -195,7 +200,7 @@ void RunNoteFinder( struct NoteFinder * nf, const float * audio_stream, int head for( i = 0; i < freqs; i++ ) { - nf->outbins[i] = nf->outbins[i] * (nf->dft_iir) + (dftbins[i] * (1.-nf->dft_iir) * nf->amplify); + nf->outbins[i] = (nf->outbins[i] * (nf->dft_iir) + (dftbins[i] * (1.-nf->dft_iir) * nf->amplify * ( 1. + nf->slope * i ))); } diff --git a/notefinder.h b/notefinder.h index 937ebc7..5d56462 100644 --- a/notefinder.h +++ b/notefinder.h @@ -8,6 +8,7 @@ struct NoteFinder { //Setup DFT Bins int ofreqs; + float slope;// = 0 int octaves;// = 5; int freqbins;// = 24; int note_peaks; //Calculated from freqbins (not configurable) From 1d0245670514021263ef258a1b3cab695a73ccd2 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Wed, 11 Feb 2015 01:10:59 -0500 Subject: [PATCH 06/22] update windows exe --- colorchord.exe | Bin 63488 -> 64000 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/colorchord.exe b/colorchord.exe index 5c013e79e2e94f76ad2252db0ea75045728f4dab..f0899d3e9460e3719bfe4c618694a29f68d38927 100755 GIT binary patch delta 5062 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 WfIa^rZN#{LH!$qn@Y delta 5008 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 From 60de5e7e23678f14cfbbcc7628d9735dde803936 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Tue, 17 Feb 2015 09:21:22 -0500 Subject: [PATCH 07/22] Add my last name --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 5e07f48..962cbda 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2015, Charles +Copyright (c) 2015, Charles Lohr All rights reserved. Redistribution and use in source and binary forms, with or without From 24bb3ec84caa7374c93743354f841cb451709cb1 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Tue, 17 Feb 2015 09:21:32 -0500 Subject: [PATCH 08/22] Add my last name --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 962cbda..91c45c2 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2015, Charles Lohr +Copyright (c) 2015, Charles Lohr (CNLohr) All rights reserved. Redistribution and use in source and binary forms, with or without From 9035f16add83c33eb318398687447194ac6e1669 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Tue, 17 Feb 2015 09:24:11 -0500 Subject: [PATCH 09/22] remove third clause --- LICENSE | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/LICENSE b/LICENSE index 91c45c2..23b7afa 100644 --- a/LICENSE +++ b/LICENSE @@ -11,9 +11,7 @@ modification, are permitted provided that the following conditions are met: this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. -* Neither the name of colorchord nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. +* The third clause of this license has been voluentarily lifted by its author. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE From 6d75249cb8d98e9f99a216318a07b08866783c04 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Wed, 1 Apr 2015 00:21:01 -0400 Subject: [PATCH 10/22] The starts of Embedded ColorChord --- Makefile | 15 ++- OutputLinear.c | 4 +- OutputProminent.c | 90 ++++++++++++++ colorchord.exe | Bin 64000 -> 0 bytes default.conf | 13 +- dft.c | 310 ++++++++++++++++++++++++++++++++++------------ dft.h | 35 +++++- embeddedcc.c | 123 ++++++++++++++++++ main.c | 18 ++- quickwash.conf | 26 ++++ sound_pulse.c | 5 + 11 files changed, 545 insertions(+), 94 deletions(-) create mode 100644 OutputProminent.c delete mode 100755 colorchord.exe create mode 100644 embeddedcc.c create mode 100644 quickwash.conf diff --git a/Makefile b/Makefile index a1dce0a..c42a863 100644 --- a/Makefile +++ b/Makefile @@ -2,23 +2,30 @@ all : colorchord RAWDRAW:=DrawFunctions.o XDriver.o SOUND:=sound.o sound_alsa.o sound_pulse.o sound_null.o -OUTS := OutputVoronoi.o DisplayArray.o OutputLinear.o DisplayPie.o DisplayNetwork.o DisplayUSB2812.o DisplayDMX.o +OUTS := OutputVoronoi.o DisplayArray.o OutputLinear.o DisplayPie.o DisplayNetwork.o DisplayUSB2812.o DisplayDMX.o OutputProminent.o WINGCC:=i586-mingw32msvc-gcc -WINGCCFLAGS:= -O2 -ffast-math -Wl,--relax -Wl,--gc-sections -ffunction-sections -fdata-sections -s +WINGCCFLAGS:= -O2 -Wl,--relax -Wl,--gc-sections -ffunction-sections -fdata-sections -s WINLDFLAGS:=-lwinmm -lgdi32 -lws2_32 RAWDRAWLIBS:=-lX11 -lm -lpthread -lXinerama -lXext LDLIBS:=-lpthread -lasound -lm -lpulse-simple -lpulse -CFLAGS:=-g -Os -flto -Wall -ffast-math +CFLAGS:=-g -Os -flto -Wall 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) parameters.o chash.o gcc -o $@ $^ $(CFLAGS) $(LDLIBS) $(EXTRALIBS) $(RAWDRAWLIBS) +embeddedcc : os_generic.c embeddedcc.c dft.c + gcc -o $@ $^ $(CFLAGS) -DCCEMBEDDED $(LDFLAGS) $(EXTRALIBS) $(RAWDRAWLIBS) + +runembedded : embeddedcc + parec --format=u8 --rate=8000 --channels=1 --device=alsa_output.pci-0000_00_1b.0.analog-stereo.monitor | ./embeddedcc + + colorchord.exe : os_generic.c main.c dft.c decompose.c filter.c color.c sort.c notefinder.c util.c outdrivers.c DrawFunctions.c parameters.c chash.c WinDriver.c sound.c sound_null.c sound_win.c OutputVoronoi.c DisplayArray.c OutputLinear.c DisplayPie.c DisplayNetwork.c $(WINGCC) $(WINGCCFLAGS) -o $@ $^ $(WINLDFLAGS) clean : - rm -rf *.o *~ colorchord colorchord.exe + rm -rf *.o *~ colorchord colorchord.exe embeddedcc diff --git a/OutputLinear.c b/OutputLinear.c index 631db2c..6e3fbda 100644 --- a/OutputLinear.c +++ b/OutputLinear.c @@ -157,7 +157,9 @@ static void LEDUpdate(void * id, struct NoteFinder*nf) if( satQ > 1 ) satQ = 1; led->last_led_pos[i] = rledpos[ia]; led->last_led_amp[i] = sat; - int r = CCtoHEX( led->last_led_pos[i], 1.0, (led->steady_bright?sat:satQ) ); + float sendsat = (led->steady_bright?sat:satQ); + if( sendsat > 1 ) sendsat = 1; + int r = CCtoHEX( led->last_led_pos[i], 1.0, sendsat ); OutLEDs[i*3+0] = r & 0xff; OutLEDs[i*3+1] = (r>>8) & 0xff; diff --git a/OutputProminent.c b/OutputProminent.c new file mode 100644 index 0000000..aa5adcb --- /dev/null +++ b/OutputProminent.c @@ -0,0 +1,90 @@ +//Really basic driver, that just selects the most prominent color and washes all the LEDs with that. + +#include "outdrivers.h" +#include "notefinder.h" +#include +#include +#include "parameters.h" +#include +#include "color.h" +#include +#include +#include + +struct ProminentDriver +{ + int did_init; + int total_leds; + float satamp; +}; + +static void LEDUpdate(void * id, struct NoteFinder*nf) +{ + struct ProminentDriver * led = (struct ProminentDriver*)id; + + + //Step 1: Calculate the quantity of all the LEDs we'll want. + int totbins = nf->note_peaks;//nf->dists; + int i; + float selected_amp = 0; + float selected_note = 0; + +// if( totbins > led_bins ) totbins = led_bins; + + for( i = 0; i < totbins; i++ ) + { + float freq = nf->note_positions[i] / nf->freqbins; + float amp = nf->note_amplitudes2[i] * led->satamp; + if( amp > selected_amp ) + { + selected_amp = amp; + selected_note = freq; + } + } + + + + //Advance the LEDs to this position when outputting the values. + for( i = 0; i < led->total_leds; i++ ) + { + float sendsat = selected_amp; + if( sendsat > 1 ) sendsat = 1; + int r = CCtoHEX( selected_note, 1.0, sendsat ); + + OutLEDs[i*3+0] = r & 0xff; + OutLEDs[i*3+1] = (r>>8) & 0xff; + OutLEDs[i*3+2] = (r>>16) & 0xff; + } + +} + +static void LEDParams(void * id ) +{ + struct ProminentDriver * led = (struct ProminentDriver*)id; + + led->satamp = 2; RegisterValue( "satamp", PAFLOAT, &led->satamp, sizeof( led->satamp ) ); + led->total_leds = 4; RegisterValue( "leds", PAINT, &led->total_leds, sizeof( led->total_leds ) ); + + + printf( "Found Prominent for output. leds=%d\n", led->total_leds ); + +} + + +static struct DriverInstances * OutputProminent() +{ + struct DriverInstances * ret = malloc( sizeof( struct DriverInstances ) ); + memset( ret, 0, sizeof( struct DriverInstances ) ); + struct ProminentDriver * led = ret->id = malloc( sizeof( struct ProminentDriver ) ); + memset( led, 0, sizeof( struct ProminentDriver ) ); + + ret->Func = LEDUpdate; + ret->Params = LEDParams; + LEDParams( led ); + return ret; + +} + +REGISTER_OUT_DRIVER(OutputProminent); + + diff --git a/colorchord.exe b/colorchord.exe deleted file mode 100755 index f0899d3e9460e3719bfe4c618694a29f68d38927..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 64000 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 diff --git a/default.conf b/default.conf index f96c54e..502124b 100644 --- a/default.conf +++ b/default.conf @@ -17,7 +17,7 @@ buffer = 128 play = 0 rec = 1 channels = 2 -samplerate = 44100 +samplerate = 8000 wininput = 0 #Compiled version will default this. @@ -31,7 +31,7 @@ sourcename = alsa_output.pci-0000_00_1b.0.analog-stereo.monitor ################################## # How much to amplify the incoming signal. -amplify = 2.5 +amplify = 2.0 # What is the base note? I.e. the lowest note. # Note that it won't have very much impact until an octave up though! @@ -47,6 +47,13 @@ dft_q = 20.0000 dft_speedup = 1000.0000 octaves = 5 +# Should we use a progressive DFT? +# 0 = DFT Quick +# 1 = DFT Progressive +# 2 = DFT Progressive Integer +# 3 = DFT Progressive Integer Skippy +do_progressive_dft = 3 + filter_iter = 2 filter_strength = .5 @@ -63,7 +70,7 @@ note_attach_freq_iir = 0.3000 note_combine_distance = 0.5000 note_jumpability = 1.8000 note_minimum_new_distribution_value = 0.0200 -note_out_chop = 0.1000 +note_out_chop = 0.05000 #======================================================================= diff --git a/dft.c b/dft.c index c40ae19..bfa3d02 100644 --- a/dft.c +++ b/dft.c @@ -1,4 +1,3 @@ - #include "dft.h" #include #include @@ -6,6 +5,9 @@ #include #include + +#ifndef CCEMBEDDED + void DoDFT( float * outbins, float * frequencies, int bins, float * databuffer, int place_in_data_buffer, int size_of_data_buffer, float q ) { int i, j; @@ -88,10 +90,9 @@ static float * gbinqtys; static float * gbinqtyc; static float * phis; static float * gfrequencies; -static float * goutbins; static float * lastbins; static float * advances; - +static float * goutbins; static int gbins; static float gq; static float gspeedup; @@ -325,7 +326,7 @@ void DoDFTProgressiveInteger( float * outbins, float * frequencies, int bins, co - +#endif @@ -337,14 +338,6 @@ void DoDFTProgressiveInteger( float * outbins, float * frequencies, int bins, co ////////////////////////SKIPPY DFT -//Skippy DFT is a very ood one. - - - -#define OCTAVES 5 -#define FIXBPERO 24 -#define FIXBINS (FIXBPERO*OCTAVES) -#define BINCYCLE (1< +#include +#include + +int8_t Ssintable[512]; //Actually [sin][cos] pairs. + +int main() +{ + int i; + for( i = 0; i < 256; i++ ) + { + Ssintable[i*2+0] = (int8_t)((sinf( i / 256.0 * 6.283 ) * 127.0)); + Ssintable[i*2+1] = (int8_t)((cosf( i / 256.0 * 6.283 ) * 127.0)); + } + + printf( "const int8_t Ssintable[512] = {" ); + for( i = 0; i < 512; i++ ) + { + if( !(i & 0xf ) ) + { + printf( "\n\t" ); + } + printf( "%4d," ,Ssintable[i] ); + } + printf( "};\n" ); +} + */ + + + +uint16_t Sdatspace[FIXBINS*4]; //(advances,places,isses,icses) //For -static uint8_t Sdo_this_octave[BINCYCLE]; -static int16_t Saccum_octavebins[OCTAVES]; -static uint8_t Swhichoctaveplace; +uint8_t Sdo_this_octave[BINCYCLE]; +int16_t Saccum_octavebins[OCTAVES]; +uint8_t Swhichoctaveplace; +uint16_t embeddedbins[FIXBINS]; //This is updated every time the DFT hits the octavecount, or 1/32 updates. + +//From: http://stackoverflow.com/questions/1100090/looking-for-an-efficient-integer-square-root-algorithm-for-arm-thumb2 +/** + * \brief Fast Square root algorithm, with rounding + * + * This does arithmetic rounding of the result. That is, if the real answer + * would have a fractional part of 0.5 or greater, the result is rounded up to + * the next integer. + * - SquareRootRounded(2) --> 1 + * - SquareRootRounded(3) --> 2 + * - SquareRootRounded(4) --> 2 + * - SquareRootRounded(6) --> 2 + * - SquareRootRounded(7) --> 3 + * - SquareRootRounded(8) --> 3 + * - SquareRootRounded(9) --> 3 + * + * \param[in] a_nInput - unsigned integer for which to find the square root + * + * \return Integer square root of the input value. + */ +static uint16_t SquareRootRounded(uint32_t a_nInput) +{ + uint32_t op = a_nInput; + uint32_t res = 0; + uint32_t one = 1uL << 30; // The second-to-top bit is set: use 1u << 14 for uint16_t type; use 1uL<<30 for uint32_t type + + + // "one" starts at the highest power of four <= than the argument. + while (one > op) + { + one >>= 2; + } + + while (one != 0) + { + if (op >= res + one) + { + op = op - (res + one); + res = res + 2 * one; + } + res >>= 1; + one >>= 2; + } + + /* Do arithmetic rounding to nearest integer */ + if (op > res) + { + res++; + } + + return res; +} void HandleProgressiveIntSkippy( int8_t sample1 ) { @@ -390,27 +500,40 @@ void HandleProgressiveIntSkippy( int8_t sample1 ) { int16_t isps = Sdatspace[i*4+2]; int16_t ispc = Sdatspace[i*4+3]; - int16_t mux = ( (isps/256) * (isps/256)) + ((ispc/256) * (ispc/256)); // printf( "%d (%d %d)\n", mux, isps, ispc ); int octave = i / FIXBPERO; // mux >>= octave; - goutbins[i] = sqrt( mux ); -// goutbins[i]/=100.0; - goutbins[i]/=100*(1<>5; - Sdatspace[i*4+3] -= ispc>>5; - } +#ifndef CCEMBEDDED + uint32_t mux = ( (isps/256) * (isps/256)) + ((ispc/256) * (ispc/256)); + goutbins[i] = sqrt( mux ); + goutbins[i]/=25*(1<>= octave; + + Sdatspace[i*4+2] -= isps>>4; //XXX 4 is more responsive AND doesn't overflow as easily. + Sdatspace[i*4+3] -= ispc>>4; //XXX 4 is more responsive AND doesn't overflow as easily. + + //TRICKY: It is possible for the sin and cos accumulators to overflow, + //I DO NOT INTEND TO FIX THIS NOW! It could be easily fixed by using 32-bit integers, or + //by decreasing the quality a little bit, but it is an extreme case with a pure, full-volume sinewave. + } + return; } + for( i = 0; i < OCTAVES;i++ ) { Saccum_octavebins[i] += sample1; } uint16_t * ds = &Sdatspace[oct*FIXBPERO*4]; - int8_t * st; + const int8_t * st; sample1 = Saccum_octavebins[oct]>>(OCTAVES-oct); Saccum_octavebins[oct] = 0; @@ -436,13 +559,13 @@ void HandleProgressiveIntSkippy( int8_t sample1 ) //Add TS and TC to the datspace stuff. (24 instructions) tmp1 = (*ds); //Read out, sin component. 4 Accurate. // tmp1 -= tmp1>>4; //Subtract from the MSB (with carry) 2 -> 6 AS/IS: 7+7 = 14 - tmp1 += ts>>3; //Add MSBs with carry 2 -> 6 AS/IS: 6 + tmp1 += ts>>4; //Add MSBs with carry 2 -> 6 AS/IS: 6 *(ds++) = tmp1; //Store values back 4 tmp1 = *ds; //Read out, sin component. 4 // tmp1 -= tmp1>>4; //Subtract from the MSB (with carry) 2 -> 6 AS/IS: 7+7 = 14 - tmp1 += tc>>3; //Add MSBs with carry 2 -> 6 AS/IS: 6 + tmp1 += tc>>4; //Add MSBs with carry 2 -> 6 AS/IS: 6 *ds++ = tmp1; //Store values back 4 @@ -452,46 +575,82 @@ void HandleProgressiveIntSkippy( int8_t sample1 ) } } +void SetupDFTProgressiveIntegerSkippy() +{ + int i; + int j; + //Sdatspace = malloc(FIXBPERO*OCTAVES*8); + //memset(Sdatspace,0,FIXBPERO*OCTAVES*8); + //printf( "MS: %d\n", FIXBPERO*OCTAVES*8); + Sdonefirstrun = 1; +/* + for( i = 0; i < 256; i++ ) + { + Ssintable[i*2+0] = (int8_t)((sinf( i / 256.0 * 6.283 ) * 127.0)); + Ssintable[i*2+1] = (int8_t)((cosf( i / 256.0 * 6.283 ) * 127.0)); + } +*/ + for( i = 0; i < BINCYCLE; i++ ) + { + // Sdo_this_octave = + // 4 3 4 2 4 3 4 ... + //search for "first" zero + + for( j = 0; j <= OCTAVES; j++ ) + { + if( ((1< OCTAVES ) + { + fprintf( stderr, "Error: algorithm fault.\n" ); + exit( -1 ); + } + Sdo_this_octave[i] = OCTAVES-j-1; + } +} + +#ifndef CCEMBEDDED + +void UpdateBinsForProgressiveIntegerSkippy( const float * frequencies ) +{ + int i; + for( i = 0; i < FIXBINS; i++ ) + { + float freq = frequencies[(i%FIXBPERO) + (FIXBPERO*(OCTAVES-1))]; + Sdatspace[i*4] = (65536.0/freq);// / oneoveroctave; + } +} + +#endif + + +void UpdateBinsForProgressiveIntegerSkippyInt( const uint16_t * frequencies ) +{ + int i; + for( i = 0; i < FIXBINS; i++ ) + { + uint16_t freq = frequencies[i%FIXBPERO]; + Sdatspace[i*4] = freq;// / oneoveroctave; + } +} + +void Push8BitIntegerSkippy( int8_t dat ) +{ + HandleProgressiveIntSkippy( dat ); + HandleProgressiveIntSkippy( dat ); +} + + +#ifndef CCEMBEDDED + void DoDFTProgressiveIntegerSkippy( float * outbins, float * frequencies, int bins, const float * databuffer, int place_in_data_buffer, int size_of_data_buffer, float q, float speedup ) { static float backupbins[FIXBINS]; - int i, j; + int i; static int last_place; -//printf( "SKIPPY\n" ); - - if( !Sdonefirstrun ) - { - memset( outbins, 0, bins * sizeof( float ) ); - goutbins = outbins; - //Sdatspace = malloc(FIXBPERO*OCTAVES*8); - //memset(Sdatspace,0,FIXBPERO*OCTAVES*8); - //printf( "MS: %d\n", FIXBPERO*OCTAVES*8); - Sdonefirstrun = 1; - for( i = 0; i < 256; i++ ) - { - Ssintable[i*2+0] = (int8_t)((sinf( i / 256.0 * 6.283 ) * 127.0)); - Ssintable[i*2+1] = (int8_t)((cosf( i / 256.0 * 6.283 ) * 127.0)); - } - - for( i = 0; i < BINCYCLE; i++ ) - { - // Sdo_this_octave = - // 4 3 4 2 4 3 4 ... - //search for "first" zero - - for( j = 0; j <= OCTAVES; j++ ) - { - if( ((1< OCTAVES ) - { - fprintf( stderr, "Error: algorithm fault.\n" ); - exit( -1 ); - } - Sdo_this_octave[i] = OCTAVES-j-1; - } - } + memset( outbins, 0, bins * sizeof( float ) ); + goutbins = outbins; memcpy( outbins, backupbins, FIXBINS*4 ); @@ -501,13 +660,16 @@ void DoDFTProgressiveIntegerSkippy( float * outbins, float * frequencies, int bi return; } - - for( i = 0; i < bins; i++ ) + +//printf( "SKIPPY\n" ); + + if( !Sdonefirstrun ) { - float freq = frequencies[(i%FIXBPERO) + (FIXBPERO*(OCTAVES-1))]; - Sdatspace[i*4] = (65536.0/freq);// / oneoveroctave; + SetupDFTProgressiveIntegerSkippy(); + Sdonefirstrun = 1; } + UpdateBinsForProgressiveIntegerSkippy( frequencies ); for( i = last_place; i != place_in_data_buffer; i = (i+1)%size_of_data_buffer ) { @@ -519,23 +681,9 @@ void DoDFTProgressiveIntegerSkippy( float * outbins, float * frequencies, int bi last_place = place_in_data_buffer; memcpy( backupbins, outbins, FIXBINS*4 ); - - //Extract bins. -/* - for( i = 0; i < bins; i++ ) - { - int16_t isps = Sdatspace[i*4+2]; - int16_t ispc = Sdatspace[i*4+3]; - int16_t mux = ( (isps/256) * (isps/256)) + ((ispc/256) * (ispc/256)); -// printf( "%d (%d %d)\n", mux, isps, ispc ); - outbins[i] = sqrt( mux )/100.0; - } -*/ - -// printf( "\n"); } - +#endif diff --git a/dft.h b/dft.h index 944b949..1589c22 100644 --- a/dft.h +++ b/dft.h @@ -1,10 +1,13 @@ #ifndef _DFT_H #define _DFT_H +#include + +//Warning: Most ColorChords are not available for ColorChord Embedded. +#ifndef CCEMBEDDED //There are several options here, the last few are selectable by modifying the do_progressive_dft flag. - //Do a DFT on a live audio ring buffer. It assumes new samples are added on in the + direction, older samples go negative. //Frequencies are as a function of the samplerate, for example, a frequency of 22050 is actually 2 Hz @ 44100 SPS //bins = number of frequencies to check against. @@ -22,10 +25,40 @@ void DoDFTProgressive( float * outbins, float * frequencies, int bins, const flo //This is fast enough to run on an ESP8266 void DoDFTProgressiveInteger( float * outbins, float * frequencies, int bins, const float * databuffer, int place_in_data_buffer, int size_of_data_buffer, float q, float speedup ); +#endif + //Everything the integer one buys, except it only calculates 2 octaves worth of notes per audio frame. //This is sort of working, but still have some quality issues. //It would theoretically be fast enough to work on an AVR. +//NOTE: This is the only DFT available to the embedded port of ColorChord void DoDFTProgressiveIntegerSkippy( float * outbins, float * frequencies, int bins, const float * databuffer, int place_in_data_buffer, int size_of_data_buffer, float q, float speedup ); +//It's actually split into a few functions, which you can call on your own: +void SetupDFTProgressiveIntegerSkippy(); //Call at start. + +#ifndef CCEMBEDDED +void UpdateBinsForProgressiveIntegerSkippy( const float * frequencies ); //Update the frequencies +#endif + +void UpdateBinsForProgressiveIntegerSkippyInt( const uint16_t * frequencies ); +void Push8BitIntegerSkippy( int8_t dat ); //Call this to push on new frames of sound. + + +//You can # define these to be other things. +#ifndef OCTAVES +#define OCTAVES 5 +#endif + +#ifndef FIXBPERO +#define FIXBPERO 24 +#endif + +#define FIXBINS (FIXBPERO*OCTAVES) +#define BINCYCLE (1< + +#include "dft.h" +#define DFREQ 8000 +#define BASE_FREQ 55.0 + +const float bf_table[24] = { + 1.000000, 1.029302, 1.059463, 1.090508, 1.122462, 1.155353, + 1.189207, 1.224054, 1.259921, 1.296840, 1.334840, 1.373954, + 1.414214, 1.455653, 1.498307, 1.542211, 1.587401, 1.633915, + 1.681793, 1.731073, 1.781797, 1.834008, 1.887749, 1.943064 }; + +#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) + +/* The above table was generated using the following code: + +#include +#include + +int main() +{ + int i; + #define FIXBPERO 24 + printf( "const float bf_table[%d] = {", FIXBPERO ); + for( i = 0; i < FIXBPERO; i++ ) + { + if( ( i % 6 ) == 0 ) + printf( "\n\t" ); + printf( "%f, ", pow( 2, (float)i / (float)FIXBPERO ) ); + } + printf( "};\n" ); + return 0; +} +*/ + +void UpdateFreqs() +{ + uint16_t fbins[FIXBPERO]; + int i; + + BUILD_BUG_ON( sizeof(bf_table) != FIXBPERO*4 ); + + for( i = 0; i < FIXBPERO; i++ ) + { + float frq = ( bf_table[i] * BASE_FREQ ); + fbins[i] = ( 65536.0 ) / ( DFREQ ) * frq * 16; + } + + UpdateBinsForProgressiveIntegerSkippyInt( fbins ); +} + +void Init() +{ + //Step 1: Initialize the Integer DFT. + SetupDFTProgressiveIntegerSkippy(); + + //Step 2: Set up the frequency list. + UpdateFreqs(); +} + +void HandleFrameInfo() +{ + uint16_t folded_bins[FIXBPERO]; + + int i, j, k = 0; + + for( i = 0; i < FIXBPERO; i++ ) + folded_bins[i] = 0; + + for( j = 0; j < OCTAVES; j++ ) + { + for( i = 0; i < FIXBPERO; i++ ) + { + folded_bins[i] += embeddedbins[k++]; + } + } + + + + //XXX TODO Taper the first and last octaves. +// for( i = 0; i < freqbins; i++ ) +// { +// nf->outbins[i] *= (i+1.0)/nf->freqbins; +// } +// for( i = 0; i < freqbins; i++ ) +// { +// nf->outbins[freqs-i-1] *= (i+1.0)/nf->freqbins; +// } + + //We now have the system folded into one + + for( i = 0; i < FIXBPERO; i++ ) + { + printf( "%5d ", folded_bins[i] ); + } + printf( "\n" ); +} + +int main() +{ + int wf = 0; + int ci; + Init(); + while( ( ci = getchar() ) != EOF ) + { + int cs = ci - 0x80; + Push8BitIntegerSkippy( (int8_t)cs ); + //printf( "%d ", cs ); fflush( stdout ); + wf++; + if( wf == 64 ) + { + HandleFrameInfo(); + wf = 0; + } + } + return 0; +} + diff --git a/main.c b/main.c index 3664a82..57aae5d 100644 --- a/main.c +++ b/main.c @@ -44,7 +44,7 @@ int sample_channel = -1;REGISTER_PARAM( sample_channel, PAINT ); struct NoteFinder * nf; //Sound circular buffer -#define SOUNDCBSIZE 65536 +#define SOUNDCBSIZE 8096 #define MAX_CHANNELS 2 double VisTimeEnd, VisTimeStart; @@ -98,10 +98,15 @@ void SoundCB( float * out, float * in, int samplesr, int * samplesp, struct Soun for( j = 0; j < channelin; j++ ) { float f = in[i*channelin+j]; - if( f > -1 && f < 1 ) + if( f >= -1 && f <= 1 ) { fo += f; } + else + { + fo += (f>0)?1:-1; +// printf( "Sound fault A %d/%d %d/%d %f\n", j, channelin, i, samplesr, f ); + } } fo /= channelin; @@ -114,9 +119,13 @@ void SoundCB( float * out, float * in, int samplesr, int * samplesp, struct Soun float f = in[i*channelin+sample_channel]; if( f > -1 && f < 1 ) { - sound[soundhead] = f; - soundhead = (soundhead+1)%SOUNDCBSIZE; + f = (f>0)?1:-1; } + + //printf( "Sound fault B %d/%d\n", i, samplesr ); + sound[soundhead] = f; + soundhead = (soundhead+1)%SOUNDCBSIZE; + } } } @@ -374,6 +383,7 @@ int main(int argc, char ** argv) int thisy = sound[thissoundhead] * 128 + 128; thissoundhead = (thissoundhead-1+SOUNDCBSIZE)%SOUNDCBSIZE; for( i = 0; i < screenx; i++ ) { + if( thisy < 0 || thisy > 256 ) printf( "%d/%d\n", thisy,thissoundhead ); CNFGTackSegment( i, lasty, i+1, thisy ); lasty = thisy; thisy = sound[thissoundhead] * 128 + 128; thissoundhead = (thissoundhead-1+SOUNDCBSIZE)%SOUNDCBSIZE; diff --git a/quickwash.conf b/quickwash.conf new file mode 100644 index 0000000..ab598e8 --- /dev/null +++ b/quickwash.conf @@ -0,0 +1,26 @@ + +This is a vornoi thing: +outdrivers = DisplayArray, OutputProminent +lightx = 2 +lighty = 2 +leds = 4 +fromsides = 1 +shape_cutoff = 0.03 +satamp = 5.000 +amppow = 2.510 +distpow = 1.500 + +samplerate = 11025 +buffer = 64 + +sourcename = default + +amplify = 2.5 +note_attach_amp_iir = 0.9000 +note_attach_amp_iir2 = 0.550 +note_attach_freq_iir = 0.9000 +dft_iir = .6 +dft_q = 20.0000 +dft_speedup = 1000.0000 +note_jumpability = 1.0000 + diff --git a/sound_pulse.c b/sound_pulse.c index 513b53a..7033db8 100644 --- a/sound_pulse.c +++ b/sound_pulse.c @@ -267,6 +267,11 @@ void * InitSoundPulse( SoundCBType cb ) r->channelsRec = r->channelsPlay; r->sourceName = GetParameterS( "sourcename", NULL ); + if( strcmp( r->sourceName, "default" ) == 0 ) + { + r->sourceName = 0; + } + r->play = 0; r->rec = 0; r->buffer = GetParameterI( "buffer", 1024 ); From 09be0f349bcd15a14559134f788d14b5edf095fa Mon Sep 17 00:00:00 2001 From: cnlohr Date: Wed, 1 Apr 2015 22:59:12 -0400 Subject: [PATCH 11/22] okay, things are moving along quite well. Almost ready for my first test. --- Makefile | 2 +- dft.c | 4 +- dft.h | 7 ++ embeddedcc.c | 96 +-------------- embeddednf.c | 342 +++++++++++++++++++++++++++++++++++++++++++++++++++ embeddednf.h | 53 ++++++++ 6 files changed, 406 insertions(+), 98 deletions(-) create mode 100644 embeddednf.c create mode 100644 embeddednf.h diff --git a/Makefile b/Makefile index c42a863..6046917 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ 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) parameters.o chash.o gcc -o $@ $^ $(CFLAGS) $(LDLIBS) $(EXTRALIBS) $(RAWDRAWLIBS) -embeddedcc : os_generic.c embeddedcc.c dft.c +embeddedcc : os_generic.c embeddedcc.c dft.c embeddednf.c gcc -o $@ $^ $(CFLAGS) -DCCEMBEDDED $(LDFLAGS) $(EXTRALIBS) $(RAWDRAWLIBS) runembedded : embeddedcc diff --git a/dft.c b/dft.c index bfa3d02..75aab1c 100644 --- a/dft.c +++ b/dft.c @@ -559,13 +559,13 @@ void HandleProgressiveIntSkippy( int8_t sample1 ) //Add TS and TC to the datspace stuff. (24 instructions) tmp1 = (*ds); //Read out, sin component. 4 Accurate. // tmp1 -= tmp1>>4; //Subtract from the MSB (with carry) 2 -> 6 AS/IS: 7+7 = 14 - tmp1 += ts>>4; //Add MSBs with carry 2 -> 6 AS/IS: 6 + tmp1 += ts>>SHIFT_ADD_DETAIL; //Add MSBs with carry 2 -> 6 AS/IS: 6 *(ds++) = tmp1; //Store values back 4 tmp1 = *ds; //Read out, sin component. 4 // tmp1 -= tmp1>>4; //Subtract from the MSB (with carry) 2 -> 6 AS/IS: 7+7 = 14 - tmp1 += tc>>4; //Add MSBs with carry 2 -> 6 AS/IS: 6 + tmp1 += tc>>SHIFT_ADD_DETAIL; //Add MSBs with carry 2 -> 6 AS/IS: 6 *ds++ = tmp1; //Store values back 4 diff --git a/dft.h b/dft.h index 1589c22..531d0cc 100644 --- a/dft.h +++ b/dft.h @@ -56,6 +56,13 @@ void Push8BitIntegerSkippy( int8_t dat ); //Call this to push on new frames of s #define FIXBINS (FIXBPERO*OCTAVES) #define BINCYCLE (1< - +#include "embeddednf.h" #include "dft.h" -#define DFREQ 8000 -#define BASE_FREQ 55.0 - -const float bf_table[24] = { - 1.000000, 1.029302, 1.059463, 1.090508, 1.122462, 1.155353, - 1.189207, 1.224054, 1.259921, 1.296840, 1.334840, 1.373954, - 1.414214, 1.455653, 1.498307, 1.542211, 1.587401, 1.633915, - 1.681793, 1.731073, 1.781797, 1.834008, 1.887749, 1.943064 }; - -#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) - -/* The above table was generated using the following code: - -#include -#include - -int main() -{ - int i; - #define FIXBPERO 24 - printf( "const float bf_table[%d] = {", FIXBPERO ); - for( i = 0; i < FIXBPERO; i++ ) - { - if( ( i % 6 ) == 0 ) - printf( "\n\t" ); - printf( "%f, ", pow( 2, (float)i / (float)FIXBPERO ) ); - } - printf( "};\n" ); - return 0; -} -*/ - -void UpdateFreqs() -{ - uint16_t fbins[FIXBPERO]; - int i; - - BUILD_BUG_ON( sizeof(bf_table) != FIXBPERO*4 ); - - for( i = 0; i < FIXBPERO; i++ ) - { - float frq = ( bf_table[i] * BASE_FREQ ); - fbins[i] = ( 65536.0 ) / ( DFREQ ) * frq * 16; - } - - UpdateBinsForProgressiveIntegerSkippyInt( fbins ); -} - -void Init() -{ - //Step 1: Initialize the Integer DFT. - SetupDFTProgressiveIntegerSkippy(); - - //Step 2: Set up the frequency list. - UpdateFreqs(); -} - -void HandleFrameInfo() -{ - uint16_t folded_bins[FIXBPERO]; - - int i, j, k = 0; - - for( i = 0; i < FIXBPERO; i++ ) - folded_bins[i] = 0; - - for( j = 0; j < OCTAVES; j++ ) - { - for( i = 0; i < FIXBPERO; i++ ) - { - folded_bins[i] += embeddedbins[k++]; - } - } - - - - //XXX TODO Taper the first and last octaves. -// for( i = 0; i < freqbins; i++ ) -// { -// nf->outbins[i] *= (i+1.0)/nf->freqbins; -// } -// for( i = 0; i < freqbins; i++ ) -// { -// nf->outbins[freqs-i-1] *= (i+1.0)/nf->freqbins; -// } - - //We now have the system folded into one - - for( i = 0; i < FIXBPERO; i++ ) - { - printf( "%5d ", folded_bins[i] ); - } - printf( "\n" ); -} int main() { diff --git a/embeddednf.c b/embeddednf.c new file mode 100644 index 0000000..07e7930 --- /dev/null +++ b/embeddednf.c @@ -0,0 +1,342 @@ +#include "embeddednf.h" +#include + +uint16_t folded_bins[FIXBPERO]; +uint16_t fuzzed_bins[FIXBINS]; +uint8_t note_peak_freqs[MAXNOTES]; +uint16_t note_peak_amps[MAXNOTES]; +uint16_t note_peak_amps2[MAXNOTES]; + + +static const float bf_table[24] = { + 1.000000, 1.029302, 1.059463, 1.090508, 1.122462, 1.155353, + 1.189207, 1.224054, 1.259921, 1.296840, 1.334840, 1.373954, + 1.414214, 1.455653, 1.498307, 1.542211, 1.587401, 1.633915, + 1.681793, 1.731073, 1.781797, 1.834008, 1.887749, 1.943064 }; + +/* The above table was generated using the following code: + +#include +#include + +int main() +{ + int i; + #define FIXBPERO 24 + printf( "const float bf_table[%d] = {", FIXBPERO ); + for( i = 0; i < FIXBPERO; i++ ) + { + if( ( i % 6 ) == 0 ) + printf( "\n\t" ); + printf( "%f, ", pow( 2, (float)i / (float)FIXBPERO ) ); + } + printf( "};\n" ); + return 0; +} +*/ + + +#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) + + +void UpdateFreqs() +{ + uint16_t fbins[FIXBPERO]; + int i; + + BUILD_BUG_ON( sizeof(bf_table) != FIXBPERO*4 ); + + //Warning: This does floating point. Avoid doing this frequently. If you + //absolutely cannot have floating point on your system, you may precompute + //this and store it as a table. It does preclude you from changing + //BASE_FREQ in runtime. + + for( i = 0; i < FIXBPERO; i++ ) + { + float frq = ( bf_table[i] * BASE_FREQ ); + fbins[i] = ( 65536.0 ) / ( DFREQ ) * frq * 16; + } + + UpdateBinsForProgressiveIntegerSkippyInt( fbins ); +} + +void Init() +{ + int i; + //Set up and initialize arrays. + for( i = 0; i < MAXNOTES; i++ ) + { + note_peak_freqs[i] = 255; + note_peak_amps[i] = 0; + note_peak_amps2[i] = 0; + } + + for( i = 0; i < FIXBPERO; i++ ) + { + folded_bins[i] = 0; + } + + for( i = 0; i < FIXBINS; i++ ) + { + fuzzed_bins[i] = 0; + } + + //Step 1: Initialize the Integer DFT. + SetupDFTProgressiveIntegerSkippy(); + + //Step 2: Set up the frequency list. You could do this multiple times + //if you want to change the loadout of the frequencies. + UpdateFreqs(); +} + +void HandleFrameInfo() +{ + int i, j, k; + + //Copy out the bins from the DFT to our fuzzed bins. + for( i = 0; i < FIXBINS; i++ ) + { + fuzzed_bins[i] = (fuzzed_bins[i] + (embeddedbins[i]>>FUZZ_IIR_BITS) - + (fuzzed_bins[i]>>FUZZ_IIR_BITS)); + } + + //Taper first octave + for( i = 0; i < FIXBPERO; i++ ) + { + uint32_t taperamt = (65536 / FIXBPERO) * i; + fuzzed_bins[i] = (taperamt * fuzzed_bins[i]) >> 16; + } + + //Taper last octave + for( i = 0; i < FIXBPERO; i++ ) + { + int newi = FIXBINS - i - 1; + uint32_t taperamt = (65536 / FIXBPERO) * i; + fuzzed_bins[newi] = (taperamt * fuzzed_bins[newi]) >> 16; + } + + //Fold the bins from fuzzedbins into one octave. + for( i = 0; i < FIXBPERO; i++ ) + folded_bins[i] = 0; + + k = 0; + for( j = 0; j < OCTAVES; j++ ) + { + for( i = 0; i < FIXBPERO; i++ ) + { + folded_bins[i] += fuzzed_bins[k++]; + } + } + + //Now, we must blur the folded bins to get a good result. + //Sometimes you may notice every other bin being out-of + //line, and this fixes that. We may consider running this + //more than once, but in my experience, once is enough. + { + //Extra scoping because this is a large on-stack buffer. + uint16_t folded_out[FIXBPERO]; + uint8_t adjLeft = FIXBPERO-1; + uint8_t adjRight = 1; + for( i = 0; i < FIXBPERO; i++ ) + { + uint16_t lbin = folded_bins[adjLeft]>>2; + uint16_t rbin = folded_bins[adjRight]>>2; + uint16_t tbin = folded_bins[i]>>1; + folded_out[i] = lbin + rbin + tbin; + + //We do this funny dance to avoid a modulus operation. On some + //processors, a modulus operation is slow. This is cheap. + adjLeft++; if( adjLeft == FIXBPERO ) adjLeft = 0; + adjRight++; if( adjRight == FIXBPERO ) adjRight = 0; + } + + for( i = 0; i < FIXBPERO; i++ ) + { + folded_bins[i] = folded_out[i]; + } + } + + //Next, we have to find the peaks, this is what "decompose" does in our + //normal tool. As a warning, it expects that the values in foolded_bins + //do NOT exceed 32767. + { + uint8_t adjLeft = FIXBPERO-1; + uint8_t adjRight = 1; + for( i = 0; i < FIXBPERO; i++ ) + { + int16_t prev = folded_bins[adjLeft]; + int16_t next = folded_bins[adjRight]; + int16_t this = folded_bins[i]; + uint8_t thisfreq = i< this || next > this ) continue; + if( prev == this && next == this ) continue; + + //i is at a peak... + int32_t totaldiff = (( this - prev ) + ( this - next )); + int32_t porpdiffP = ((this-prev)<<16) / totaldiff; //close to 0 = + //closer to this side, 32768 = in the middle, 65535 away. + int32_t porpdiffN = ((this-next)<<16) / totaldiff; + + if( porpdiffP < porpdiffN ) + { + //Closer to prev. + offset = -(32768 - porpdiffP); + } + else + { + //Closer to next + offset = (32768 - porpdiffN); + } + + //Need to round. That's what that extra +(15.. is in the center. + thisfreq += (offset+(1<<(15-SEMIBITSPERBIN)))>>(16-SEMIBITSPERBIN); + + //In the event we went 'below zero' need to wrap to the top. + if( thisfreq > 255-(1< ((1<<(SEMIBITSPERBIN-1))*FIXBPERO) ) + { + distance = ((1<<(SEMIBITSPERBIN))*FIXBPERO) - distance; + } + + if( distance < closest_note_distance ) + { + closest_note_id = j; + closest_note_distance = distance; + } + } + + int8_t marked_note = -1; + + if( closest_note_distance <= MAX_JUMP_DISTANCE ) + { + //We found the note we need to augment. + //XXX: TODO: Should we be IIRing this? + + note_peak_freqs[closest_note_id] = thisfreq; + marked_note = closest_note_id; + } + //The note was not found. + else if( lowest_found_free_note != -1 ) + { + note_peak_freqs[lowest_found_free_note] = thisfreq; + marked_note = lowest_found_free_note; + } + + 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; + } + } + } + + //Now we need to handle combining notes. + for( i = 0; i < MAXNOTES; i++ ) + for( j = 0; j < i; j++ ) + { + //We'd be combining nf2 (j) into nf1 (i) if they're close enough. + uint8_t nf1 = note_peak_freqs[i]; + uint8_t nf2 = note_peak_freqs[j]; + int16_t distance = nf1 - nf2; + + if( nf1 == 255 || nf2 == 255 ) continue; + + if( distance < 0 ) distance = -distance; + + if( distance > ((1<<(SEMIBITSPERBIN-1))*FIXBPERO) ) + { + distance = ((1<<(SEMIBITSPERBIN))*FIXBPERO) - distance; + } + + if( distance > MAX_JUMP_DISTANCE * 2 ) + { + continue; + } + + //We need to combine the notes. We need to move the new note freq + //towards the stronger of the two notes. + int16_t amp1 = note_peak_amps[i]; + int16_t amp2 = note_peak_amps[j]; + + //0 to 32768 porportional to how much of amp1 we want. + uint32_t porp = (amp1<<15) / (amp1+amp2); + uint16_t newnote = (nf1 * porp + nf2 * (32768-porp))>>15; + + note_peak_amps[i] = amp1 + amp2; + note_peak_amps[j] = 0; + note_peak_freqs[i] = newnote; + note_peak_freqs[j] = 255; + note_peak_amps2[i] += note_peak_amps2[j]; + } + + + for( i = 0; i < MAXNOTES; i++ ) + { + if( note_peak_freqs[i] == 255 ) 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; + + if( note_peak_amps[i] < MINIMUM_AMP_FOR_NOTE_TO_DISAPPEAR ) + { + note_peak_freqs[i] = 255; + note_peak_amps[i] = 0; + note_peak_amps2[i] = 0; + } + } + + //We now have notes!!! +/* + for( i = 0; i < MAXNOTES; i++ ) + { + if( note_peak_freqs[i] == 255 ) continue; + printf( "(%3d %4d %4d) ", note_peak_freqs[i], note_peak_amps[i], note_peak_amps2[i] ); + } + printf( "\n") ; +*/ + +/* + for( i = 0; i < FIXBPERO; i++ ) + { + printf( "%5d ", folded_bins[i] ); + } + printf( "\n" );*/ +} + + diff --git a/embeddednf.h b/embeddednf.h new file mode 100644 index 0000000..a28e930 --- /dev/null +++ b/embeddednf.h @@ -0,0 +1,53 @@ +#ifndef _EMBEDDEDNF_H +#define _EMBEDDEDNF_H + +#include "dft.h" + +#define DFREQ 8000 +#define BASE_FREQ 55.0 // You may make this a float. + +//The higher the number the slackier your FFT will be come. +#define FUZZ_IIR_BITS 1 + +//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 + +//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. +//note_frequency = 0..((1< Date: Fri, 3 Apr 2015 14:10:25 -0400 Subject: [PATCH 12/22] Move the embedded stuff into architecture-specific folders --- DFT32.c | 342 +++++++++++++++++++++++ DFT32.h | 69 +++++ Makefile | 11 +- default.conf | 3 +- dft.c | 10 +- dft.h | 7 +- embeddednf.c | 27 +- embeddednf.h | 11 +- embeddedx86/Makefile | 13 + embeddedcc.c => embeddedx86/embeddedcc.c | 5 +- notefinder.c | 4 + 11 files changed, 479 insertions(+), 23 deletions(-) create mode 100644 DFT32.c create mode 100644 DFT32.h create mode 100644 embeddedx86/Makefile rename embeddedcc.c => embeddedx86/embeddedcc.c (87%) diff --git a/DFT32.c b/DFT32.c new file mode 100644 index 0000000..ded5ea7 --- /dev/null +++ b/DFT32.c @@ -0,0 +1,342 @@ +#include "DFT32.h" +#include + +#ifndef CCEMBEDDED +#include +#include +#include +static float * goutbins; +#endif + +uint16_t embeddedbins32[FIXBINS]; + +//NOTES to self: +// +// Let's say we want to try this on an AVR. +// 24 bins, 5 octaves = 120 bins. +// 20 MHz clock / 4.8k sps = 4096 IPS = 34 clocks per bin = :( +// We can do two at the same time, this frees us up some + +static uint8_t Sdonefirstrun; + +//A table of precomputed sin() values. Ranging -1500 to +1500 +//If we increase this, it may cause overflows elsewhere in code. +const int16_t Ssinonlytable[256] = { + 0, 36, 73, 110, 147, 183, 220, 256, + 292, 328, 364, 400, 435, 470, 505, 539, + 574, 607, 641, 674, 707, 739, 771, 802, + 833, 863, 893, 922, 951, 979, 1007, 1034, + 1060, 1086, 1111, 1135, 1159, 1182, 1204, 1226, + 1247, 1267, 1286, 1305, 1322, 1339, 1355, 1371, + 1385, 1399, 1412, 1424, 1435, 1445, 1455, 1463, + 1471, 1477, 1483, 1488, 1492, 1495, 1498, 1499, + 1500, 1499, 1498, 1495, 1492, 1488, 1483, 1477, + 1471, 1463, 1455, 1445, 1435, 1424, 1412, 1399, + 1385, 1371, 1356, 1339, 1322, 1305, 1286, 1267, + 1247, 1226, 1204, 1182, 1159, 1135, 1111, 1086, + 1060, 1034, 1007, 979, 951, 922, 893, 863, + 833, 802, 771, 739, 707, 674, 641, 607, + 574, 539, 505, 470, 435, 400, 364, 328, + 292, 256, 220, 183, 147, 110, 73, 36, + 0, -36, -73, -110, -146, -183, -219, -256, + -292, -328, -364, -399, -435, -470, -505, -539, + -573, -607, -641, -674, -706, -739, -771, -802, + -833, -863, -893, -922, -951, -979, -1007, -1034, + -1060, -1086, -1111, -1135, -1159, -1182, -1204, -1226, + -1247, -1267, -1286, -1305, -1322, -1339, -1355, -1371, + -1385, -1399, -1412, -1424, -1435, -1445, -1454, -1463, + -1471, -1477, -1483, -1488, -1492, -1495, -1498, -1499, + -1500, -1499, -1498, -1495, -1492, -1488, -1483, -1477, + -1471, -1463, -1455, -1445, -1435, -1424, -1412, -1399, + -1385, -1371, -1356, -1339, -1322, -1305, -1286, -1267, + -1247, -1226, -1204, -1182, -1159, -1135, -1111, -1086, + -1060, -1034, -1007, -979, -951, -923, -893, -863, + -833, -802, -771, -739, -707, -674, -641, -608, + -574, -540, -505, -470, -435, -400, -364, -328, + -292, -256, -220, -183, -147, -110, -73, -37,}; + + +/** The above table was created using the following code: +#include +#include +#include + +int16_t Ssintable[256]; //Actually, just [sin]. + +int main() +{ + int i; + for( i = 0; i < 256; i++ ) + { + Ssintable[i] = (int16_t)((sinf( i / 256.0 * 6.283 ) * 1500.0)); + } + + printf( "const int16_t Ssinonlytable[256] = {" ); + for( i = 0; i < 256; i++ ) + { + if( !(i & 0x7 ) ) + { + printf( "\n\t" ); + } + printf( "%6d," ,Ssintable[i] ); + } + printf( "};\n" ); +} */ + + + +uint16_t Sdatspace32A[FIXBINS*2]; //(advances,places) +int32_t Sdatspace32B[FIXBINS*2]; //(isses,icses) +int32_t Sdatspace32BOut[FIXBINS*2]; //(isses,icses) + +//For +static uint8_t Sdo_this_octave[BINCYCLE]; +static int32_t Saccum_octavebins[OCTAVES]; +static uint8_t Swhichoctaveplace; +uint16_t embeddedbins[FIXBINS]; //This is updated every time the DFT hits the octavecount, or 1/32 updates. + +//From: http://stackoverflow.com/questions/1100090/looking-for-an-efficient-integer-square-root-algorithm-for-arm-thumb2 +/** + * \brief Fast Square root algorithm, with rounding + * + * This does arithmetic rounding of the result. That is, if the real answer + * would have a fractional part of 0.5 or greater, the result is rounded up to + * the next integer. + * - SquareRootRounded(2) --> 1 + * - SquareRootRounded(3) --> 2 + * - SquareRootRounded(4) --> 2 + * - SquareRootRounded(6) --> 2 + * - SquareRootRounded(7) --> 3 + * - SquareRootRounded(8) --> 3 + * - SquareRootRounded(9) --> 3 + * + * \param[in] a_nInput - unsigned integer for which to find the square root + * + * \return Integer square root of the input value. + */ +static uint16_t SquareRootRounded(uint32_t a_nInput) +{ + uint32_t op = a_nInput; + uint32_t res = 0; + uint32_t one = 1uL << 30; // The second-to-top bit is set: use 1u << 14 for uint16_t type; use 1uL<<30 for uint32_t type + + + // "one" starts at the highest power of four <= than the argument. + while (one > op) + { + one >>= 2; + } + + while (one != 0) + { + if (op >= res + one) + { + op = op - (res + one); + res = res + 2 * one; + } + res >>= 1; + one >>= 2; + } + + /* Do arithmetic rounding to nearest integer */ + if (op > res) + { + res++; + } + + return res; +} + +void UpdateOutputBins32() +{ + int i; + int * ipt = &Sdatspace32BOut[0]; + for( i = 0; i < FIXBINS; i++ ) + { + int16_t isps = *(ipt++)>>16; + int16_t ispc = *(ipt++)>>16; + + int octave = i / FIXBPERO; + +#ifndef CCEMBEDDED + uint32_t mux = ( (isps) * (isps)) + ((ispc) * (ispc)); + goutbins[i] = sqrtf( (float)mux ); + goutbins[i] /= (78<> octave; + } +} + +static void HandleInt( int16_t sample ) +{ + int i; + uint16_t adv; + uint8_t localipl; + + uint8_t oct = Sdo_this_octave[Swhichoctaveplace]; + Swhichoctaveplace ++; + Swhichoctaveplace &= BINCYCLE-1; + + if( oct > 128 ) + { + //Special: This is when we can update everything. + + int32_t * bins = &Sdatspace32B[0]; + int32_t * binsOut = &Sdatspace32BOut[0]; + + for( i = 0; i < FIXBINS; i++ ) + { + //First for the SIN then the COS. + int32_t val = *(bins); + *(binsOut++) = val; + *(bins++) -= val>>DFTIIR; + + val = *(bins); + *(binsOut++) = val; + *(bins++) -= val>>DFTIIR; + } + return; + } + + + for( i = 0; i < OCTAVES;i++ ) + { + Saccum_octavebins[i] += sample; + } + + uint16_t * dsA = &Sdatspace32A[oct*FIXBPERO*2]; + int32_t * dsB = &Sdatspace32B[oct*FIXBPERO*2]; + + sample = Saccum_octavebins[oct]>>(OCTAVES-oct); + Saccum_octavebins[oct] = 0; + + for( i = 0; i < FIXBPERO; i++ ) + { + adv = *(dsA++); + localipl = *(dsA) >> 8; + *(dsA++) += adv; + + *(dsB++) += (Ssinonlytable[localipl] * sample); + //Get the cosine (1/4 wavelength out-of-phase with sin) + localipl += 64; + *(dsB++) += (Ssinonlytable[localipl] * sample); + } +} + +int SetupDFTProgressive32() +{ + int i; + int j; + //Sdatspace = malloc(FIXBPERO*OCTAVES*8); + //memset(Sdatspace,0,FIXBPERO*OCTAVES*8); + //printf( "MS: %d\n", FIXBPERO*OCTAVES*8); + Sdonefirstrun = 1; + + for( i = 0; i < BINCYCLE; i++ ) + { + // Sdo_this_octave = + // 4 3 4 2 4 3 4 ... + //search for "first" zero + + for( j = 0; j <= OCTAVES; j++ ) + { + if( ((1< OCTAVES ) + { +#ifndef CCEMBEDDED + fprintf( stderr, "Error: algorithm fault.\n" ); + exit( -1 ); +#endif + return -1; + } + Sdo_this_octave[i] = OCTAVES-j-1; + } + return 0; +} + + + +void UpdateBins32( const uint16_t * frequencies ) +{ + int i; + for( i = 0; i < FIXBINS; i++ ) + { + uint16_t freq = frequencies[i%FIXBPERO]; + Sdatspace32A[i*2] = freq;// / oneoveroctave; + } +} + +void PushSample32( int16_t dat ) +{ + HandleInt( dat ); + HandleInt( dat ); +} + + +#ifndef CCEMBEDDED + +void UpdateBinsForDFT32( const float * frequencies ) +{ + int i; + for( i = 0; i < FIXBINS; i++ ) + { + float freq = frequencies[(i%FIXBPERO) + (FIXBPERO*(OCTAVES-1))]; + Sdatspace32A[i*2] = (65536.0/freq);// / oneoveroctave; + } +} + +#endif + + +#ifndef CCEMBEDDED + +void DoDFTProgressive32( float * outbins, float * frequencies, int bins, const float * databuffer, int place_in_data_buffer, int size_of_data_buffer, float q, float speedup ) +{ + static float backupbins[FIXBINS]; + int i; + static int last_place; + + memset( outbins, 0, bins * sizeof( float ) ); + goutbins = outbins; + + memcpy( outbins, backupbins, FIXBINS*4 ); + + if( FIXBINS != bins ) + { + fprintf( stderr, "Error: Bins was reconfigured. skippy requires a constant number of bins.\n" ); + return; + } + + +//printf( "SKIPPY\n" ); + + if( !Sdonefirstrun ) + { + SetupDFTProgressive32(); + Sdonefirstrun = 1; + } + + UpdateBinsForDFT32( frequencies ); + + for( i = last_place; i != place_in_data_buffer; i = (i+1)%size_of_data_buffer ) + { + int16_t ifr1 = (int16_t)( ((databuffer[i]) ) * 4095 ); + HandleInt( ifr1 ); + HandleInt( ifr1 ); + } + + UpdateOutputBins32(); + + last_place = place_in_data_buffer; + + memcpy( backupbins, outbins, FIXBINS*4 ); +} + +#endif + + + + diff --git a/DFT32.h b/DFT32.h new file mode 100644 index 0000000..6bce18d --- /dev/null +++ b/DFT32.h @@ -0,0 +1,69 @@ +#ifndef _DFT32_H +#define _DFT32_H + +#include + +//A 32-bit version of the DFT used for ColorChord. +//This header makes it convenient to use for an embedded system. +//The 32-bit DFT avoids some bit shifts, however it uses slightly +//more RAM and it uses a lot of 32-bit arithmatic. +// +//This is basically a clone of "ProgressiveIntegerSkippy" and changes +//made here should be backported there as well. + +//You can # define these to be other things elsewhere. +#ifndef OCTAVES +#define OCTAVES 5 +#endif + +#ifndef FIXBPERO +#define FIXBPERO 24 +#endif + +#ifndef FIXBINS +#define FIXBINS (FIXBPERO*OCTAVES) +#endif + +#ifndef BINCYCLE +#define BINCYCLE (1<>FUZZ_IIR_BITS) - + fuzzed_bins[i] = (fuzzed_bins[i] + (strens[i]>>FUZZ_IIR_BITS) - (fuzzed_bins[i]>>FUZZ_IIR_BITS)); } @@ -322,21 +338,22 @@ void HandleFrameInfo() } //We now have notes!!! -/* +#if 1 for( i = 0; i < MAXNOTES; i++ ) { if( note_peak_freqs[i] == 255 ) continue; printf( "(%3d %4d %4d) ", note_peak_freqs[i], note_peak_amps[i], note_peak_amps2[i] ); } printf( "\n") ; -*/ +#endif -/* +#if 0 for( i = 0; i < FIXBPERO; i++ ) { printf( "%5d ", folded_bins[i] ); } - printf( "\n" );*/ + printf( "\n" ); +#endif } diff --git a/embeddednf.h b/embeddednf.h index a28e930..bc953da 100644 --- a/embeddednf.h +++ b/embeddednf.h @@ -1,7 +1,9 @@ #ifndef _EMBEDDEDNF_H #define _EMBEDDEDNF_H -#include "dft.h" +//Use a 32-bit DFT. It won't work for AVRs, but for any 32-bit systems where +//they can multiply quickly, this is the bees knees. +#define USE_32DFT #define DFREQ 8000 #define BASE_FREQ 55.0 // You may make this a float. @@ -32,6 +34,13 @@ #define AMP_1_NERFING_BITS 5 #define AMP_2_NERFING_BITS 3 + +#ifdef USE_32DFT +#include "DFT32.h" +#else +#include "dft.h" +#endif + extern uint16_t folded_bins[]; //[FIXBPERO] <- The folded fourier output. extern uint16_t fuzzed_bins[]; //[FIXBINS] <- The Full DFT after IIR, Blur and Taper diff --git a/embeddedx86/Makefile b/embeddedx86/Makefile new file mode 100644 index 0000000..5a0d78b --- /dev/null +++ b/embeddedx86/Makefile @@ -0,0 +1,13 @@ +all : embeddedcc + +CFLAGS:=-Ofast -DCCEMBEDDED -I.. -flto -m32 +LDFLAGS:=-ffunction-sections -Wl,--gc-sections -fno-asynchronous-unwind-tables -Wl,--strip-all + +embeddedcc : ../embeddednf.c ../DFT32.c embeddedcc.c + gcc -o $@ $^ $(CFLAGS) $(LDFLAGS) + +runembedded : embeddedcc + parec --format=u8 --rate=8000 --channels=1 --device=alsa_output.pci-0000_00_1b.0.analog-stereo.monitor | ./embeddedcc + +clean : + rm -rf embeddedcc *~ diff --git a/embeddedcc.c b/embeddedx86/embeddedcc.c similarity index 87% rename from embeddedcc.c rename to embeddedx86/embeddedcc.c index ee6f066..127d68f 100644 --- a/embeddedcc.c +++ b/embeddedx86/embeddedcc.c @@ -5,7 +5,6 @@ #include #include "embeddednf.h" -#include "dft.h" int main() { @@ -15,7 +14,11 @@ int main() while( ( ci = getchar() ) != EOF ) { int cs = ci - 0x80; +#ifdef USE_32DFT + PushSample32( ((int8_t)cs)*32 ); +#else Push8BitIntegerSkippy( (int8_t)cs ); +#endif //printf( "%d ", cs ); fflush( stdout ); wf++; if( wf == 64 ) diff --git a/notefinder.c b/notefinder.c index 3322929..8f7b8f0 100644 --- a/notefinder.c +++ b/notefinder.c @@ -9,6 +9,7 @@ #include "filter.h" #include "decompose.h" #include "sort.h" +#include "DFT32.h" struct NoteFinder * CreateNoteFinder( int spsRec ) { @@ -193,6 +194,9 @@ void RunNoteFinder( struct NoteFinder * nf, const float * audio_stream, int head case 3: DoDFTProgressiveIntegerSkippy( dftbins, nf->frequencies, freqs, audio_stream, head, buffersize, nf->dft_q, nf->dft_speedup ); break; + case 4: + DoDFTProgressive32( dftbins, nf->frequencies, freqs, audio_stream, head, buffersize, nf->dft_q, nf->dft_speedup ); + break; default: fprintf( stderr, "Error: No DFT Seleced\n" ); } From 4f7eabb24ec91a4331bb862f29b2179c5f87ef06 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Fri, 3 Apr 2015 15:34:11 -0400 Subject: [PATCH 13/22] update : use 11025 Hz. also, fix overflow bug with combining notes --- default.conf | 2 +- embeddednf.c | 17 +++++++++++------ embeddednf.h | 9 +++++++-- embeddedx86/Makefile | 4 ++-- 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/default.conf b/default.conf index 0ccc958..e441a2d 100644 --- a/default.conf +++ b/default.conf @@ -17,7 +17,7 @@ buffer = 128 play = 0 rec = 1 channels = 2 -samplerate = 8000 +samplerate = 11025 wininput = 0 #Compiled version will default this. diff --git a/embeddednf.c b/embeddednf.c index ff69855..3a3f9e1 100644 --- a/embeddednf.c +++ b/embeddednf.c @@ -6,6 +6,7 @@ uint16_t fuzzed_bins[FIXBINS]; uint8_t note_peak_freqs[MAXNOTES]; uint16_t note_peak_amps[MAXNOTES]; uint16_t note_peak_amps2[MAXNOTES]; +uint8_t note_jumped_to[MAXNOTES]; static const float bf_table[24] = { @@ -215,7 +216,7 @@ void HandleFrameInfo() if( thisfreq > 255-(1<>15; - note_peak_amps[i] = amp1 + amp2; - note_peak_amps[j] = 0; note_peak_freqs[i] = newnote; + note_peak_amps[i] = (note_peak_amps[i]+note_peak_amps[j])>>1; + note_peak_amps2[i] = (note_peak_amps2[i]+note_peak_amps2[j])>>1; + note_peak_freqs[j] = 255; - note_peak_amps2[i] += note_peak_amps2[j]; + note_peak_amps[j] = 0; + note_jumped_to[j] = i; } @@ -338,7 +341,7 @@ void HandleFrameInfo() } //We now have notes!!! -#if 1 +#if 0 for( i = 0; i < MAXNOTES; i++ ) { if( note_peak_freqs[i] == 255 ) continue; @@ -350,10 +353,12 @@ void HandleFrameInfo() #if 0 for( i = 0; i < FIXBPERO; i++ ) { - printf( "%5d ", folded_bins[i] ); + printf( "%4d ", folded_bins[i] ); } printf( "\n" ); #endif + + } diff --git a/embeddednf.h b/embeddednf.h index bc953da..098b0ac 100644 --- a/embeddednf.h +++ b/embeddednf.h @@ -5,7 +5,10 @@ //they can multiply quickly, this is the bees knees. #define USE_32DFT +#ifndef DFREQ #define DFREQ 8000 +#endif + #define BASE_FREQ 55.0 // You may make this a float. //The higher the number the slackier your FFT will be come. @@ -23,14 +26,14 @@ //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 128 +#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 MINIMUM_AMP_FOR_NOTE_TO_DISAPPEAR 64 +#define MINIMUM_AMP_FOR_NOTE_TO_DISAPPEAR 32 #define AMP_1_NERFING_BITS 5 #define AMP_2_NERFING_BITS 3 @@ -48,6 +51,8 @@ extern uint16_t fuzzed_bins[]; //[FIXBINS] <- The Full DFT after IIR, Blur and extern uint8_t note_peak_freqs[]; extern uint16_t note_peak_amps[]; //[MAXNOTES] extern uint16_t note_peak_amps2[]; //[MAXNOTES] (Responds quicker) +extern uint8_t note_jumped_to[]; //[MAXNOTES] When a note combines into another one, + //this records where it went. I.e. if your note just disappeared, check this flag. //XXX: TODO: Consider doing the fuzz IIR on the folded bins. That way we can //save several bytes of RAM on not having to keep fuzzed_bins around. diff --git a/embeddedx86/Makefile b/embeddedx86/Makefile index 5a0d78b..af6483a 100644 --- a/embeddedx86/Makefile +++ b/embeddedx86/Makefile @@ -1,13 +1,13 @@ all : embeddedcc -CFLAGS:=-Ofast -DCCEMBEDDED -I.. -flto -m32 +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 gcc -o $@ $^ $(CFLAGS) $(LDFLAGS) runembedded : embeddedcc - parec --format=u8 --rate=8000 --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 | ./embeddedcc clean : rm -rf embeddedcc *~ From 18ac6e9acbce91618879ccffa25f8197edfcaaa9 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Fri, 3 Apr 2015 17:50:09 -0400 Subject: [PATCH 14/22] progress! --- embeddedout.c | 236 ++++++++++++++++++++++++++++++++++++++++++++++++++ embeddedout.h | 19 ++++ 2 files changed, 255 insertions(+) create mode 100644 embeddedout.c create mode 100644 embeddedout.h diff --git a/embeddedout.c b/embeddedout.c new file mode 100644 index 0000000..807b57b --- /dev/null +++ b/embeddedout.c @@ -0,0 +1,236 @@ +#include "embeddedout.h" + +//uint8_t ledArray[NUM_LIN_LEDS]; //Points to which notes correspond to these LEDs +uint8_t ledOut[NUM_LIN_LEDS*3]; + +void UpdateLinear() +{ + //Source material: + /* + extern uint8_t note_peak_freqs[]; + extern uint16_t note_peak_amps[]; //[MAXNOTES] + extern uint16_t note_peak_amps2[]; //[MAXNOTES] (Responds quicker) + extern uint8_t note_jumped_to[]; //[MAXNOTES] When a note combines into another one, + */ + + //Goal: Make splotches of light that are porportional to the strength of notes. + //Color them according to value in note_peak_amps2. + + uint8_t i; + uint16_t j; + uint32_t total_size_all_notes = 0; + uint16_t porpamps[MAXNOTES]; //LEDs for each corresponding note. + + for( i = 0; i < MAXNOTES; i++ ) + { + porpamps[i] = 0; + if( note_peak_freqs[i] == 255 ) continue; + total_size_all_notes += note_peak_amps[i]; + } + + uint32_t porportional = (total_size_for_all_notes << 8) / NUM_LIN_LEDS; + + 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; + total_accounted_leds += porpamps[i]; + } + + uint16_t total_unaccounted_leds = NUM_LIN_LEDS - total_accounted_leds; + + for( i = 0; i < MAXNOTES, total_unaccounted_leds; i++ ) + { + if( note_peak_freqs[i] == 255 ) continue; + porpamps[i]++; + } + + //Now, we use porpamps to march through the LEDs, coloring them. + j = 0; + for( i = 0; i < MAXNOTES; i++ ) + { + while( porpamps[i] ) + { + uint16_t amp = note_peak_amps2[i]; + 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; + j++; + porpamps[i]--; + } + } +} + + +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; + + //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) ) + { + //Red to Blue + hue = (third-renote); + } + else + { + hue = (((65535-renote) * third) >> 1) + (third>>1); + } + + hue >>= 8; + 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 + + uint16_t or = 0, og = 0, ob = 0; + + hue += SIXTH2; //Off by 60 degrees. + + //TODO: There are colors that overlap here, consider + //tweaking this to make the best use of the colorspace. + + if( hue < SIXTH1 ) //Ok: Yellow->Red. + { + or = 255; + og = 255 - ((uint16_t)hue * 255) / (SIXTH1); + } + else if( hue < SIXTH2 ) //Ok: Red->Purple + { + or = 255; + ob = (uint16_t)hue*255 / SIXTH1 - 255; + } + else if( hue < SIXTH3 ) //Ok: Purple->Blue + { + ob = 255; + or = ((SIXTH3-hue) * 255) / (SIXTH1); + } + else if( hue < SIXTH4 ) //Ok: Blue->Cyan + { + ob = 255; + og = (hue - SIXTH3)*255 / SIXTH1; + } + else if( hue < SIXTH5 ) //Ok: Cyan->Green. + { + og = 255; + ob = ((SIXTH5-hue)*255) / SIXTH1; + } + else //Green->Yellow + { + og = 255; + or = (hue - SIXTH5) * 255 / SIXTH1; + } + + uint16_t rv = val; + if( rv > 128 ) rv++; + uint16_t rs = sat; + if( rs > 128 ) rs++; + + //or, og, ob range from 0...255 now. + //Need to apply saturation and value. + + or = (or * val)>>8; + og = (og * val)>>8; + ob = (ob * val)>>8; + + //OR..OB == 0..65025 + or = or * rs + 255 * (256-rs); + or = or * rs + 255 * (256-rs); + or = or * rs + 255 * (256-rs); + + or >>= 8; + og >>= 8; + ob >>= 8; + return or | (og<<8) | (ob<<16); +} + +uint32_t HSVtoHEX( float hue, float sat, float value ) +{ + + float pr = 0; + float pg = 0; + float pb = 0; + + short ora = 0; + short og = 0; + short ob = 0; + + float ro = fmod( hue * 6, 6. ); + + float avg = 0; + + ro = fmod( ro + 6 + 1, 6 ); //Hue was 60* off... + + if( ro < 1 ) //yellow->red + { + pr = 1; + pg = 1. - ro; + } else if( ro < 2 ) + { + pr = 1; + pb = ro - 1.; + } else if( ro < 3 ) + { + pr = 3. - ro; + pb = 1; + } else if( ro < 4 ) + { + pb = 1; + pg = ro - 3; + } else if( ro < 5 ) + { + pb = 5 - ro; + pg = 1; + } else + { + pg = 1; + pr = ro - 5; + } + + //Actually, above math is backwards, oops! + pr *= value; + pg *= value; + pb *= value; + + avg += pr; + avg += pg; + avg += pb; + + pr = pr * sat + avg * (1.-sat); + pg = pg * sat + avg * (1.-sat); + pb = pb * sat + avg * (1.-sat); + + ora = pr * 255; + og = pb * 255; + ob = pg * 255; + + if( ora < 0 ) ora = 0; + if( ora > 255 ) ora = 255; + if( og < 0 ) og = 0; + if( og > 255 ) og = 255; + if( ob < 0 ) ob = 0; + if( ob > 255 ) ob = 255; + + return (ob<<16) | (og<<8) | ora; +} + diff --git a/embeddedout.h b/embeddedout.h new file mode 100644 index 0000000..54d1050 --- /dev/null +++ b/embeddedout.h @@ -0,0 +1,19 @@ +#ifndef _EMBEDDEDOUT_H +#define _EMBEDDEDOUT_H + +#include "embeddednf.h" + +#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(); + +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!!! + + +#endif + From 5e9023c6a0f6492435d2f18a993d83adec3d94c5 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Fri, 3 Apr 2015 17:50:14 -0400 Subject: [PATCH 15/22] formalize boundary condition --- embeddednf.h | 1 + 1 file changed, 1 insertion(+) diff --git a/embeddednf.h b/embeddednf.h index 098b0ac..c0566e7 100644 --- a/embeddednf.h +++ b/embeddednf.h @@ -23,6 +23,7 @@ //We have to define all of the possible locations on the note line in this. //note_frequency = 0..((1< Date: Sat, 4 Apr 2015 02:23:53 -0400 Subject: [PATCH 16/22] made progress... getting very close to an embedded colorchord --- DFT32.h | 2 +- embeddednf.c | 16 ++++-- embeddednf.h | 15 +++--- embeddedout.c | 108 +++++++++++++++++++++++++++------------ embeddedout.h | 9 +++- embeddedx86/Makefile | 4 +- embeddedx86/embeddedcc.c | 48 +++++++++++++++-- 7 files changed, 152 insertions(+), 50 deletions(-) diff --git a/DFT32.h b/DFT32.h index 6bce18d..1b64482 100644 --- a/DFT32.h +++ b/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. diff --git a/embeddednf.c b/embeddednf.c index 3a3f9e1..095d5ca 100644 --- a/embeddednf.c +++ b/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; diff --git a/embeddednf.h b/embeddednf.h index c0566e7..6841ccb 100644 --- a/embeddednf.h +++ b/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<> 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; } - +*/ diff --git a/embeddedout.h b/embeddedout.h index 54d1050..7d52369 100644 --- a/embeddedout.h +++ b/embeddedout.h @@ -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!!! diff --git a/embeddedx86/Makefile b/embeddedx86/Makefile index af6483a..80ba9c9 100644 --- a/embeddedx86/Makefile +++ b/embeddedx86/Makefile @@ -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 *~ diff --git a/embeddedx86/embeddedcc.c b/embeddedx86/embeddedcc.c index 127d68f..b393f30 100644 --- a/embeddedx86/embeddedcc.c +++ b/embeddedx86/embeddedcc.c @@ -3,14 +3,57 @@ // It is intended as a minimal scaffolding for testing Embedded ColorChord. // -#include + #include "embeddednf.h" +#include +#include +#include +#include +#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; } } From 9e0a963355b123cc29440c23259395b337ef6d91 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Sat, 4 Apr 2015 04:33:29 -0400 Subject: [PATCH 17/22] very close. Just cleanup to go. --- embeddednf.h | 2 +- embeddedout.c | 147 +++++++++++++++++++++++++++++++++++++++++++------- embeddedout.h | 4 +- 3 files changed, 130 insertions(+), 23 deletions(-) diff --git a/embeddednf.h b/embeddednf.h index 6841ccb..bb64f7b 100644 --- a/embeddednf.h +++ b/embeddednf.h @@ -32,7 +32,7 @@ #define MAX_JUMP_DISTANCE 5 -#define AMP_1_NERFING_BITS 5 +#define AMP_1_NERFING_BITS 4 #define AMP_2_NERFING_BITS 3 //This is the amplitude, coming from folded_bins. If the value is below this diff --git a/embeddedout.c b/embeddedout.c index 6146214..d2406f3 100644 --- a/embeddedout.c +++ b/embeddedout.c @@ -3,6 +3,11 @@ //uint8_t ledArray[NUM_LIN_LEDS]; //Points to which notes correspond to these LEDs uint8_t ledOut[NUM_LIN_LEDS*3]; +uint16_t ledSpin; +uint16_t ledAmpOut[NUM_LIN_LEDS]; +uint8_t ledFreqOut[NUM_LIN_LEDS]; +uint8_t ledFreqOutOld[NUM_LIN_LEDS]; + void UpdateLinearLEDs() { //Source material: @@ -17,39 +22,64 @@ void UpdateLinearLEDs() //Color them according to value in note_peak_amps2. uint8_t i; - uint16_t j; + int8_t k; + uint16_t j, l; uint32_t total_size_all_notes = 0; 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++ ) { uint16_t ist = note_peak_amps[i]; - if( note_peak_freqs[i] == 255 || ist <= NERF_NOTE_SIZE_VALUE ) + uint8_t nff = note_peak_freqs[i]; + if( nff == 255 || ist <= NERF_NOTE_SIZE_VALUE ) { - local_peak_amps[i] = 0; continue; } for( j = 0; j < sorted_map_count; j++ ) { - //TODO SORT ME + if( note_peak_freqs[ sorted_note_map[j] ] > nff ) + { + break; + } } + for( k = sorted_map_count; k > j; k-- ) + { + sorted_note_map[k] = sorted_note_map[k-1]; + } + + sorted_note_map[j] = i; sorted_map_count++; } - for( i = 0; i < MAXNOTES; i++ ) +#if 0 + for( i = 0; i < sorted_map_count; i++ ) { - uint16_t ist = note_peak_amps[i]; + printf( "%d: %d: %d /", sorted_note_map[i], note_peak_freqs[sorted_note_map[i]], note_peak_amps[sorted_note_map[i]] ); + } + printf( "\n" ); +#endif + + uint16_t local_peak_amps[MAXNOTES]; + uint16_t local_peak_amps2[MAXNOTES]; + uint8_t local_peak_freq[MAXNOTES]; + + for( i = 0; i < sorted_map_count; i++ ) + { + local_peak_amps[i] = note_peak_amps[sorted_note_map[i]]; + local_peak_amps2[i] = note_peak_amps2[sorted_note_map[i]]; + local_peak_freq[i] = note_peak_freqs[sorted_note_map[i]]; + } + + for( i = 0; i < sorted_map_count; i++ ) + { + uint16_t ist = local_peak_amps[i]; porpamps[i] = 0; - if( note_peak_freqs[i] == 255 || ist <= NERF_NOTE_SIZE_VALUE ) + if( ist <= NERF_NOTE_SIZE_VALUE ) { local_peak_amps[i] = 0; continue; @@ -70,30 +100,107 @@ void UpdateLinearLEDs() 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++ ) + for( i = 0; i < sorted_map_count; i++ ) { - if( note_peak_freqs[i] == 255 ) continue; porpamps[i] = (local_peak_amps[i] * porportional) >> 8; total_accounted_leds += porpamps[i]; } int16_t total_unaccounted_leds = NUM_LIN_LEDS - total_accounted_leds; - for( i = 0; i < MAXNOTES && total_unaccounted_leds; i++ ) + for( i = 0; i < sorted_map_count && total_unaccounted_leds; i++ ) { - if( note_peak_freqs[i] == 255 ) continue; porpamps[i]++; total_unaccounted_leds--; } - //Now, we use porpamps to march through the LEDs, coloring them. + //Put the frequencies on a ring. j = 0; - for( i = 0; i < MAXNOTES; i++ ) + for( i = 0; i < sorted_map_count; i++ ) { while( porpamps[i] > 0 ) { - uint16_t amp = ((uint32_t)note_peak_amps2[i] * NOTE_FINAL_AMP) >> 8; + ledFreqOut[j] = local_peak_freq[i]; + ledAmpOut[j] = (local_peak_amps2[i]*NOTE_FINAL_AMP)>>8; + j++; + porpamps[i]--; + } + } + + //This part totally can't run on an embedded system. +#if LIN_WRAPAROUND + uint16_t midx = 0; + uint32_t mqty = 100000000; + for( j = 0; j < NUM_LIN_LEDS; j++ ) + { + uint32_t dqty; + uint16_t localj; + + dqty = 0; + localj = j; + for( l = 0; l < NUM_LIN_LEDS; l++ ) + { + int32_t d = (int32_t)ledFreqOut[localj] - (int32_t)ledFreqOutOld[l]; + if( d < 0 ) d *= -1; + if( d > (NOTERANGE>>1) ) { d = NOTERANGE - d + 1; } + dqty += ( d * d ); + + localj++; + if( localj == NUM_LIN_LEDS ) localj = 0; + } + + if( dqty < mqty ) + { + mqty = dqty; + midx = j; + } + } + + ledSpin = midx; + +#else + ledSpin = 0; +#endif + + j = ledSpin; + for( l = 0; l < NUM_LIN_LEDS; l++, j++ ) + { + if( j >= NUM_LIN_LEDS ) j = 0; + ledFreqOutOld[l] = ledFreqOut[j]; + + uint16_t amp = ledAmpOut[j]; + if( amp > 255 ) amp = 255; + uint32_t color = ECCtoHEX( ledFreqOut[j], 255, amp ); + ledOut[l*3+0] = ( color >> 0 ) & 0xff; + ledOut[l*3+1] = ( color >> 8 ) & 0xff; + ledOut[l*3+2] = ( color >>16 ) & 0xff; + } +/* j = ledSpin; + for( i = 0; i < sorted_map_count; i++ ) + { + while( porpamps[i] > 0 ) + { + uint16_t amp = ((uint32_t)local_peak_amps2[i] * NOTE_FINAL_AMP) >> 8; if( amp > 255 ) amp = 255; - uint32_t color = ECCtoHEX( note_peak_freqs[i], 255, amp ); + uint32_t color = ECCtoHEX( local_peak_freq[i], 255, amp ); + ledOut[j*3+0] = ( color >> 0 ) & 0xff; + ledOut[j*3+1] = ( color >> 8 ) & 0xff; + ledOut[j*3+2] = ( color >>16 ) & 0xff; + + j++; + if( j == NUM_LIN_LEDS ) j = 0; + porpamps[i]--; + } + }*/ + + //Now, we use porpamps to march through the LEDs, coloring them. +/* j = 0; + for( i = 0; i < sorted_map_count; i++ ) + { + while( porpamps[i] > 0 ) + { + uint16_t amp = ((uint32_t)local_peak_amps2[i] * NOTE_FINAL_AMP) >> 8; + if( amp > 255 ) amp = 255; + uint32_t color = ECCtoHEX( local_peak_freq[i], 255, amp ); ledOut[j*3+0] = ( color >> 0 ) & 0xff; ledOut[j*3+1] = ( color >> 8 ) & 0xff; ledOut[j*3+2] = ( color >>16 ) & 0xff; @@ -101,7 +208,7 @@ void UpdateLinearLEDs() j++; porpamps[i]--; } - } + }*/ } diff --git a/embeddedout.h b/embeddedout.h index 7d52369..9d68137 100644 --- a/embeddedout.h +++ b/embeddedout.h @@ -8,11 +8,11 @@ #define NOTE_FINAL_AMP 255 //Number from 0...255 //Controls, basically, the minimum size of the splotches. -#define NERF_NOTE_SIZE_VALUE 10 +#define NERF_NOTE_SIZE_VALUE 1 #define NUM_LIN_LEDS 296 -#define LIN_WRAPAROUND 0 //Whether the output lights wrap around. (TODO) +#define LIN_WRAPAROUND 1 //Whether the output lights wrap around. extern uint8_t ledArray[]; extern uint8_t ledOut[]; //[NUM_LIN_LEDS*3] From 96002c5583a677d6309cf8d79efad0381c51c0ba Mon Sep 17 00:00:00 2001 From: cnlohr Date: Sat, 4 Apr 2015 18:35:03 -0400 Subject: [PATCH 18/22] OKAY! EmbeddedCC is almost ready! --- TODO | 2 +- embeddednf.c | 46 ++++++++++++++------ embeddednf.h | 10 +++-- embeddedout.c | 114 +++++++++++++------------------------------------- embeddedout.h | 7 ++-- 5 files changed, 75 insertions(+), 104 deletions(-) diff --git a/TODO b/TODO index 9dd1cb9..a7c2c83 100644 --- a/TODO +++ b/TODO @@ -1,7 +1,7 @@ Still to do: Try this: -* Separate "LED Selection" from "output" algorithms. << Do this by allowing arbitrary Lights Drivers +* Make Linear keep the order of the notes in-order. * 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. diff --git a/embeddednf.c b/embeddednf.c index 095d5ca..ddc5a5b 100644 --- a/embeddednf.c +++ b/embeddednf.c @@ -154,6 +154,7 @@ void HandleFrameInfo() //Sometimes you may notice every other bin being out-of //line, and this fixes that. We may consider running this //more than once, but in my experience, once is enough. + for( j = 0; j < FILTER_BLUR_PASSES; j++ ) { //Extra scoping because this is a large on-stack buffer. uint16_t folded_out[FIXBPERO]; @@ -281,14 +282,21 @@ void HandleFrameInfo() if( marked_note != -1 ) { 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); + note_peak_amps[marked_note] = note_peak_amps[marked_note] - (note_peak_amps[marked_note]>>AMP_1_NERFING_BITS) + (this>>(AMP_1_NERFING_BITS-3)); + note_peak_amps2[marked_note] = note_peak_amps2[marked_note] - (note_peak_amps2[marked_note]>>AMP_2_NERFING_BITS) + (this>>(AMP_2_NERFING_BITS-3)); } } } +#if 0 + for( i = 0; i < MAXNOTES; i++ ) + { + if( note_peak_freqs[i] == 255 ) continue; + printf( "%d / ", note_peak_amps[i] ); + } + printf( "\n" ); +#endif + //Now we need to handle combining notes. for( i = 0; i < MAXNOTES; i++ ) for( j = 0; j < i; j++ ) @@ -312,22 +320,36 @@ void HandleFrameInfo() continue; } + int into; + int from; + + if( note_peak_amps[i] > note_peak_amps[j] ) + { + into = i; + from = j; + } + else + { + into = j; + from = i; + } + //We need to combine the notes. We need to move the new note freq //towards the stronger of the two notes. - int16_t amp1 = note_peak_amps[i]; - int16_t amp2 = note_peak_amps[j]; + int16_t amp1 = note_peak_amps[into]; + int16_t amp2 = note_peak_amps[from]; //0 to 32768 porportional to how much of amp1 we want. uint32_t porp = (amp1<<15) / (amp1+amp2); uint16_t newnote = (nf1 * porp + nf2 * (32768-porp))>>15; - note_peak_freqs[i] = newnote; - note_peak_amps[i] = (note_peak_amps[i]+note_peak_amps[j])>>1; - note_peak_amps2[i] = (note_peak_amps2[i]+note_peak_amps2[j])>>1; + note_peak_freqs[into] = newnote; + note_peak_amps[into] = (note_peak_amps[into]>note_peak_amps[from])?note_peak_amps[into]:note_peak_amps[j]; + note_peak_amps2[into] = (note_peak_amps2[into]>note_peak_amps2[from])?note_peak_amps2[into]:note_peak_amps2[j]; - note_peak_freqs[j] = 255; - note_peak_amps[j] = 0; - note_jumped_to[j] = i; + note_peak_freqs[from] = 255; + note_peak_amps[from] = 0; + note_jumped_to[from] = i; } diff --git a/embeddednf.h b/embeddednf.h index bb64f7b..290cb2e 100644 --- a/embeddednf.h +++ b/embeddednf.h @@ -19,6 +19,8 @@ //vaporize in one frame doesn't mean it is annihilated immediately. #define MAXNOTES 12 +#define FILTER_BLUR_PASSES 2 + //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. //note_frequency = 0..((1<>8); + for( i = 0; i < MAXNOTES; i++ ) { uint16_t ist = note_peak_amps[i]; uint8_t nff = note_peak_freqs[i]; - if( nff == 255 || ist <= NERF_NOTE_SIZE_VALUE ) + if( nff == 255 ) + { + continue; + } + if( ist < note_nerf_a ) { continue; } +#if SORT_NOTES for( j = 0; j < sorted_map_count; j++ ) { if( note_peak_freqs[ sorted_note_map[j] ] > nff ) @@ -51,8 +64,10 @@ void UpdateLinearLEDs() { sorted_note_map[k] = sorted_note_map[k-1]; } - sorted_note_map[j] = i; +#else +#endif + sorted_note_map[sorted_map_count] = i; sorted_map_count++; } @@ -70,21 +85,17 @@ void UpdateLinearLEDs() for( i = 0; i < sorted_map_count; i++ ) { - local_peak_amps[i] = note_peak_amps[sorted_note_map[i]]; + printf( "%5d ", local_peak_amps[i] ); + local_peak_amps[i] = note_peak_amps[sorted_note_map[i]] - note_nerf_a; local_peak_amps2[i] = note_peak_amps2[sorted_note_map[i]]; local_peak_freq[i] = note_peak_freqs[sorted_note_map[i]]; } + printf( "\n" ); for( i = 0; i < sorted_map_count; i++ ) { uint16_t ist = local_peak_amps[i]; porpamps[i] = 0; - if( 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]; } @@ -108,10 +119,15 @@ void UpdateLinearLEDs() int16_t total_unaccounted_leds = NUM_LIN_LEDS - total_accounted_leds; - for( i = 0; i < sorted_map_count && total_unaccounted_leds; i++ ) + int addedlast = 1; + do { - porpamps[i]++; total_unaccounted_leds--; - } + for( i = 0; i < sorted_map_count && total_unaccounted_leds; i++ ) + { + porpamps[i]++; total_unaccounted_leds--; + addedlast = 1; + } + } while( addedlast && total_unaccounted_leds ); //Put the frequencies on a ring. j = 0; @@ -314,74 +330,4 @@ uint32_t EHSVtoHEX( uint8_t hue, uint8_t sat, uint8_t val ) return or | (og<<8) | ((uint32_t)ob<<16); } -/* -uint32_t HSVtoHEX( float hue, float sat, float value ) -{ - float pr = 0; - float pg = 0; - float pb = 0; - - short ora = 0; - short og = 0; - short ob = 0; - - float ro = fmod( hue * 6, 6. ); - - float avg = 0; - - ro = fmod( ro + 6 + 1, 6 ); //Hue was 60* off... - - if( ro < 1 ) //yellow->red - { - pr = 1; - pg = 1. - ro; - } else if( ro < 2 ) - { - pr = 1; - pb = ro - 1.; - } else if( ro < 3 ) - { - pr = 3. - ro; - pb = 1; - } else if( ro < 4 ) - { - pb = 1; - pg = ro - 3; - } else if( ro < 5 ) - { - pb = 5 - ro; - pg = 1; - } else - { - pg = 1; - pr = ro - 5; - } - - //Actually, above math is backwards, oops! - pr *= value; - pg *= value; - pb *= value; - - avg += pr; - avg += pg; - avg += pb; - - pr = pr * sat + avg * (1.-sat); - pg = pg * sat + avg * (1.-sat); - pb = pb * sat + avg * (1.-sat); - - ora = pr * 255; - og = pb * 255; - ob = pg * 255; - - if( ora < 0 ) ora = 0; - if( ora > 255 ) ora = 255; - if( og < 0 ) og = 0; - if( og > 255 ) og = 255; - if( ob < 0 ) ob = 0; - if( ob > 255 ) ob = 255; - - return (ob<<16) | (og<<8) | ora; -} -*/ diff --git a/embeddedout.h b/embeddedout.h index 9d68137..25c755b 100644 --- a/embeddedout.h +++ b/embeddedout.h @@ -5,14 +5,15 @@ //Controls brightness -#define NOTE_FINAL_AMP 255 //Number from 0...255 +#define NOTE_FINAL_AMP 16 //Number from 0...255 //Controls, basically, the minimum size of the splotches. -#define NERF_NOTE_SIZE_VALUE 1 +#define NERF_NOTE_PORP 15 //value from 0 to 255 #define NUM_LIN_LEDS 296 -#define LIN_WRAPAROUND 1 //Whether the output lights wrap around. +#define LIN_WRAPAROUND 0 //Whether the output lights wrap around. +#define SORT_NOTES 0 //Whether the notes will be sorted. extern uint8_t ledArray[]; extern uint8_t ledOut[]; //[NUM_LIN_LEDS*3] From ec4f175c2b33a9f1269ee8cfd7e7a575de75d4a6 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Sat, 4 Apr 2015 21:19:46 -0400 Subject: [PATCH 19/22] Add a lot of documentation, etc. for ColorChord Embedded. --- DFT32.c | 36 +++++++++++------ DFT32.h | 16 +++++--- README.md | 9 ++++- {embeddedx86 => embeddedlinux}/Makefile | 0 {embeddedx86 => embeddedlinux}/embeddedcc.c | 2 +- embeddednf.c | 43 ++++++++++++++------- embeddednf.h | 29 ++++++++------ embeddedout.c | 1 - 8 files changed, 92 insertions(+), 44 deletions(-) rename {embeddedx86 => embeddedlinux}/Makefile (100%) rename {embeddedx86 => embeddedlinux}/embeddedcc.c (99%) diff --git a/DFT32.c b/DFT32.c index ded5ea7..5e5dc8d 100644 --- a/DFT32.c +++ b/DFT32.c @@ -87,13 +87,22 @@ int main() uint16_t Sdatspace32A[FIXBINS*2]; //(advances,places) int32_t Sdatspace32B[FIXBINS*2]; //(isses,icses) + +//This is updated every time the DFT hits the octavecount, or 1/32 updates. int32_t Sdatspace32BOut[FIXBINS*2]; //(isses,icses) -//For +//Sdo_this_octave is a scheduling state for the running SIN/COS states for +//each bin. We have to execute the highest octave every time, however, we can +//get away with updating the next octave down every-other-time, then the next +//one down yet, every-other-time from that one. That way, no matter how many +//octaves we have, we only need to update FIXBPERO*2 DFT bins. static uint8_t Sdo_this_octave[BINCYCLE]; + static int32_t Saccum_octavebins[OCTAVES]; static uint8_t Swhichoctaveplace; -uint16_t embeddedbins[FIXBINS]; //This is updated every time the DFT hits the octavecount, or 1/32 updates. + +// +uint16_t embeddedbins[FIXBINS]; //From: http://stackoverflow.com/questions/1100090/looking-for-an-efficient-integer-square-root-algorithm-for-arm-thumb2 /** @@ -158,13 +167,22 @@ void UpdateOutputBins32() int octave = i / FIXBPERO; + //If we are running DFT32 on regular ColorChord, then we will need to + //also update goutbins[]... But if we're on embedded systems, we only + //update embeddedbins32. #ifndef CCEMBEDDED uint32_t mux = ( (isps) * (isps)) + ((ispc) * (ispc)); goutbins[i] = sqrtf( (float)mux ); - goutbins[i] /= (78<> octave; } } @@ -182,7 +200,8 @@ static void HandleInt( int16_t sample ) if( oct > 128 ) { //Special: This is when we can update everything. - + //This gets run one out of every 1/(1< 255-(1<>AMP_1_NERFING_BITS) + (this>>(AMP_1_NERFING_BITS-3)); - note_peak_amps2[marked_note] = note_peak_amps2[marked_note] - (note_peak_amps2[marked_note]>>AMP_2_NERFING_BITS) + (this>>(AMP_2_NERFING_BITS-3)); + + note_peak_amps[marked_note] = + note_peak_amps[marked_note] - + (note_peak_amps[marked_note]>>AMP_1_IIR_BITS) + + (this>>(AMP_1_IIR_BITS-3)); + + note_peak_amps2[marked_note] = + note_peak_amps2[marked_note] - + (note_peak_amps2[marked_note]>>AMP_2_IIR_BITS) + + (this>>(AMP_2_IIR_BITS-3)); } } } @@ -310,6 +318,8 @@ void HandleFrameInfo() if( distance < 0 ) distance = -distance; + //If it wraps around above the halfway point, then we're closer to it + //on the other side. if( distance > ((1<<(SEMIBITSPERBIN-1))*FIXBPERO) ) { distance = ((1<<(SEMIBITSPERBIN))*FIXBPERO) - distance; @@ -343,23 +353,30 @@ void HandleFrameInfo() uint32_t porp = (amp1<<15) / (amp1+amp2); uint16_t newnote = (nf1 * porp + nf2 * (32768-porp))>>15; + //When combining notes, we have to use the stronger amplitude note. + //trying to average or combine the power of the notes looks awful. note_peak_freqs[into] = newnote; - note_peak_amps[into] = (note_peak_amps[into]>note_peak_amps[from])?note_peak_amps[into]:note_peak_amps[j]; - note_peak_amps2[into] = (note_peak_amps2[into]>note_peak_amps2[from])?note_peak_amps2[into]:note_peak_amps2[j]; + note_peak_amps[into] = (note_peak_amps[into]>note_peak_amps[from])? + note_peak_amps[into]:note_peak_amps[j]; + note_peak_amps2[into] = (note_peak_amps2[into]>note_peak_amps2[from])? + note_peak_amps2[into]:note_peak_amps2[j]; note_peak_freqs[from] = 255; note_peak_amps[from] = 0; note_jumped_to[from] = i; } - + //For al lof the notes that have not been hit, we have to allow them to + //to decay. We only do this for notes that have not found a peak. for( i = 0; i < MAXNOTES; i++ ) { 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; + note_peak_amps[i] -= note_peak_amps[i]>>AMP_1_IIR_BITS; + note_peak_amps2[i] -= note_peak_amps2[i]>>AMP_2_IIR_BITS; + //In the event a note is not strong enough anymore, it is to be + //returned back into the great pool of unused notes. if( note_peak_amps[i] < MINIMUM_AMP_FOR_NOTE_TO_DISAPPEAR ) { note_peak_freqs[i] = 255; diff --git a/embeddednf.h b/embeddednf.h index 290cb2e..90087f4 100644 --- a/embeddednf.h +++ b/embeddednf.h @@ -19,27 +19,36 @@ //vaporize in one frame doesn't mean it is annihilated immediately. #define MAXNOTES 12 +//We take the raw signal off of the #define FILTER_BLUR_PASSES 2 -//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. -//note_frequency = 0..((1<>1); // ((((65535-renote)>>8) * (uint32_t)(third>>8)) >> 1) + (third<<1); } hue >>= 8; -// printf( "%d;", hue ); return EHSVtoHEX( hue, sat, val ); } From f80dd24a8d11303619b9ddc5badc33c611b45580 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Sat, 4 Apr 2015 22:16:55 -0400 Subject: [PATCH 20/22] rearrange files some a few cleanups, too. --- Makefile | 4 ++-- DFT32.c => embeddedcommon/DFT32.c | 0 DFT32.h => embeddedcommon/DFT32.h | 0 embeddednf.c => embeddedcommon/embeddednf.c | 4 ++-- embeddednf.h => embeddedcommon/embeddednf.h | 8 +++++--- embeddedout.c => embeddedcommon/embeddedout.c | 5 +++-- embeddedout.h => embeddedcommon/embeddedout.h | 2 +- embeddedlinux/Makefile | 4 ++-- embeddedlinux/embeddedcc.c | 2 +- 9 files changed, 16 insertions(+), 13 deletions(-) rename DFT32.c => embeddedcommon/DFT32.c (100%) rename DFT32.h => embeddedcommon/DFT32.h (100%) rename embeddednf.c => embeddedcommon/embeddednf.c (99%) rename embeddednf.h => embeddedcommon/embeddednf.h (95%) rename embeddedout.c => embeddedcommon/embeddedout.c (97%) rename embeddedout.h => embeddedcommon/embeddedout.h (92%) diff --git a/Makefile b/Makefile index dda437d..cd78272 100644 --- a/Makefile +++ b/Makefile @@ -13,10 +13,10 @@ LDLIBS:=-lpthread -lasound -lm -lpulse-simple -lpulse CFLAGS:=-g -Os -flto -Wall 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) parameters.o chash.o DFT32.o +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 embeddedcommon/DFT32.o gcc -o $@ $^ $(CFLAGS) $(LDLIBS) $(EXTRALIBS) $(RAWDRAWLIBS) -colorchord.exe : os_generic.c main.c dft.c decompose.c filter.c color.c sort.c notefinder.c util.c outdrivers.c DrawFunctions.c parameters.c chash.c WinDriver.c sound.c sound_null.c sound_win.c OutputVoronoi.c DisplayArray.c OutputLinear.c DisplayPie.c DisplayNetwork.c DFT32.c +colorchord.exe : os_generic.c main.c dft.c decompose.c filter.c color.c sort.c notefinder.c util.c outdrivers.c DrawFunctions.c parameters.c chash.c WinDriver.c sound.c sound_null.c sound_win.c OutputVoronoi.c DisplayArray.c OutputLinear.c DisplayPie.c DisplayNetwork.c embeddedcommon/DFT32.c $(WINGCC) $(WINGCCFLAGS) -o $@ $^ $(WINLDFLAGS) diff --git a/DFT32.c b/embeddedcommon/DFT32.c similarity index 100% rename from DFT32.c rename to embeddedcommon/DFT32.c diff --git a/DFT32.h b/embeddedcommon/DFT32.h similarity index 100% rename from DFT32.h rename to embeddedcommon/DFT32.h diff --git a/embeddednf.c b/embeddedcommon/embeddednf.c similarity index 99% rename from embeddednf.c rename to embeddedcommon/embeddednf.c index aac3933..0c5349e 100644 --- a/embeddednf.c +++ b/embeddedcommon/embeddednf.c @@ -291,7 +291,7 @@ void HandleFrameInfo() note_peak_amps2[marked_note] = note_peak_amps2[marked_note] - (note_peak_amps2[marked_note]>>AMP_2_IIR_BITS) + - (this>>(AMP_2_IIR_BITS-3)); + ((this<<3)>>(AMP_2_IIR_BITS)); } } } @@ -325,7 +325,7 @@ void HandleFrameInfo() distance = ((1<<(SEMIBITSPERBIN))*FIXBPERO) - distance; } - if( distance > MAX_JUMP_DISTANCE * 2 ) + if( distance > MAX_COMBINE_DISTANCE ) { continue; } diff --git a/embeddednf.h b/embeddedcommon/embeddednf.h similarity index 95% rename from embeddednf.h rename to embeddedcommon/embeddednf.h index 90087f4..4619300 100644 --- a/embeddednf.h +++ b/embeddedcommon/embeddednf.h @@ -35,21 +35,23 @@ //distance times two. #define MAX_JUMP_DISTANCE 4 +#define MAX_COMBINE_DISTANCE 7 + //These control how quickly the IIR for the note strengths respond. AMP 1 is //the response for the slow-response, or what we use to determine size of //splotches, AMP 2 is the quick response, or what we use to see the visual //strength of the notes. #define AMP_1_IIR_BITS 5 -#define AMP_2_IIR_BITS 3 +#define AMP_2_IIR_BITS 2 //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 128 +#define MIN_AMP_FOR_NOTE 80 //If the strength of a note falls below this, the note will disappear, and be //recycled back into the unused list of notes. -#define MINIMUM_AMP_FOR_NOTE_TO_DISAPPEAR 100 +#define MINIMUM_AMP_FOR_NOTE_TO_DISAPPEAR 64 diff --git a/embeddedout.c b/embeddedcommon/embeddedout.c similarity index 97% rename from embeddedout.c rename to embeddedcommon/embeddedout.c index c429766..f4eb756 100644 --- a/embeddedout.c +++ b/embeddedcommon/embeddedout.c @@ -83,14 +83,15 @@ void UpdateLinearLEDs() uint16_t local_peak_amps2[MAXNOTES]; uint8_t local_peak_freq[MAXNOTES]; + //Make a copy of all of the variables into local ones so we don't have to keep double-dereferencing. for( i = 0; i < sorted_map_count; i++ ) { - printf( "%5d ", local_peak_amps[i] ); + //printf( "%5d ", local_peak_amps[i] ); local_peak_amps[i] = note_peak_amps[sorted_note_map[i]] - note_nerf_a; local_peak_amps2[i] = note_peak_amps2[sorted_note_map[i]]; local_peak_freq[i] = note_peak_freqs[sorted_note_map[i]]; } - printf( "\n" ); +// printf( "\n" ); for( i = 0; i < sorted_map_count; i++ ) { diff --git a/embeddedout.h b/embeddedcommon/embeddedout.h similarity index 92% rename from embeddedout.h rename to embeddedcommon/embeddedout.h index 25c755b..8a9685f 100644 --- a/embeddedout.h +++ b/embeddedcommon/embeddedout.h @@ -5,7 +5,7 @@ //Controls brightness -#define NOTE_FINAL_AMP 16 //Number from 0...255 +#define NOTE_FINAL_AMP 12 //Number from 0...255 //Controls, basically, the minimum size of the splotches. #define NERF_NOTE_PORP 15 //value from 0 to 255 diff --git a/embeddedlinux/Makefile b/embeddedlinux/Makefile index 80ba9c9..28b9233 100644 --- a/embeddedlinux/Makefile +++ b/embeddedlinux/Makefile @@ -1,9 +1,9 @@ all : embeddedcc -CFLAGS:=-Ofast -DCCEMBEDDED -I.. -flto -m32 -DDFREQ=11025 +CFLAGS:=-Ofast -DCCEMBEDDED -I.. -flto -m32 -DDFREQ=11025 -I../embeddedcommon LDFLAGS:=-ffunction-sections -Wl,--gc-sections -fno-asynchronous-unwind-tables -Wl,--strip-all -embeddedcc : ../embeddednf.c ../DFT32.c embeddedcc.c ../embeddedout.c +embeddedcc : ../embeddedcommon/embeddednf.c ../embeddedcommon/DFT32.c embeddedcc.c ../embeddedcommon/embeddedout.c gcc -o $@ $^ $(CFLAGS) $(LDFLAGS) runembedded : embeddedcc diff --git a/embeddedlinux/embeddedcc.c b/embeddedlinux/embeddedcc.c index eb73181..2b25c1e 100644 --- a/embeddedlinux/embeddedcc.c +++ b/embeddedlinux/embeddedcc.c @@ -63,7 +63,7 @@ int main() Push8BitIntegerSkippy( (int8_t)cs ); #endif wf++; - if( wf == 64 ) + if( wf == 128 ) { NewFrame(); wf = 0; From 202a67326a27e0f9c6e523300d92fe9a4b4e5630 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Sat, 11 Apr 2015 22:33:36 -0400 Subject: [PATCH 21/22] forgot to add embedded common --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index cd78272..f86b848 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ WINLDFLAGS:=-lwinmm -lgdi32 -lws2_32 RAWDRAWLIBS:=-lX11 -lm -lpthread -lXinerama -lXext LDLIBS:=-lpthread -lasound -lm -lpulse-simple -lpulse -CFLAGS:=-g -Os -flto -Wall +CFLAGS:=-g -Os -flto -Wall -Iembeddedcommon 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) parameters.o chash.o embeddedcommon/DFT32.o From 518d69c0aabfaf41bfeccf4f0902776adfd87eb7 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Thu, 4 Jun 2015 01:51:24 -0400 Subject: [PATCH 22/22] I am on my way with this, but it's going slowly. --- embedded8266/0x00000.bin | Bin 0 -> 29728 bytes embedded8266/0x40000.bin | Bin 0 -> 140460 bytes embedded8266/LICENSE | 27 +++ embedded8266/Makefile | 81 +++++++ embedded8266/README.md | 5 + embedded8266/driver/uart.c | 247 ++++++++++++++++++++ embedded8266/image.elf | Bin 0 -> 238337 bytes embedded8266/include/driver/uart.h | 101 ++++++++ embedded8266/include/driver/uart_register.h | 128 ++++++++++ embedded8266/include/string.h | 1 + embedded8266/include/user_config.h | 10 + embedded8266/user/colorchord.c | 150 ++++++++++++ embedded8266/user/colorchord.h | 17 ++ embedded8266/user/mystuff.c | 3 + embedded8266/user/mystuff.h | 8 + embedded8266/user/user_main.c | 143 ++++++++++++ embedded8266/user/ws2812.c | 61 +++++ embedded8266/user/ws2812.h | 16 ++ 18 files changed, 998 insertions(+) create mode 100644 embedded8266/0x00000.bin create mode 100644 embedded8266/0x40000.bin create mode 100644 embedded8266/LICENSE create mode 100644 embedded8266/Makefile create mode 100644 embedded8266/README.md create mode 100644 embedded8266/driver/uart.c create mode 100755 embedded8266/image.elf create mode 100644 embedded8266/include/driver/uart.h create mode 100644 embedded8266/include/driver/uart_register.h create mode 100644 embedded8266/include/string.h create mode 100644 embedded8266/include/user_config.h create mode 100644 embedded8266/user/colorchord.c create mode 100644 embedded8266/user/colorchord.h create mode 100644 embedded8266/user/mystuff.c create mode 100644 embedded8266/user/mystuff.h create mode 100644 embedded8266/user/user_main.c create mode 100644 embedded8266/user/ws2812.c create mode 100644 embedded8266/user/ws2812.h diff --git a/embedded8266/0x00000.bin b/embedded8266/0x00000.bin new file mode 100644 index 0000000000000000000000000000000000000000..af948ab6c45831e3b624bff413cd986c99d7e7d2 GIT binary patch literal 29728 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 literal 0 HcmV?d00001 diff --git a/embedded8266/0x40000.bin b/embedded8266/0x40000.bin new file mode 100644 index 0000000000000000000000000000000000000000..656407321e1e83a3f10b096a5a2f2225209d63e8 GIT binary patch literal 140460 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 literal 0 HcmV?d00001 diff --git a/embedded8266/LICENSE b/embedded8266/LICENSE new file mode 100644 index 0000000..bf1f4f8 --- /dev/null +++ b/embedded8266/LICENSE @@ -0,0 +1,27 @@ +Portions of this code are under various Espressif licenses. + +Please take not of the individual files. All files that are +written without license, by me are under the MIT license as reads below. + +The MIT License (MIT) + +Copyright (c) 2014 Charles Lohr + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/embedded8266/Makefile b/embedded8266/Makefile new file mode 100644 index 0000000..960856d --- /dev/null +++ b/embedded8266/Makefile @@ -0,0 +1,81 @@ +all : image.elf +FW_FILE_1:=0x00000.bin +FW_FILE_2:=0x40000.bin + +TARGET_OUT:=image.elf +OBJS:=driver/uart.o \ + user/mystuff.o \ + user/ws2812.o \ + user/colorchord.o \ + user/user_main.o + +SRCS:=driver/uart.c \ + user/mystuff.c \ + user/ws2812.c \ + user/colorchord.c \ + user/user_main.c + +GCC_FOLDER:=~/esp8266/xtensa-toolchain-build/build-lx106 +ESPTOOL_PY:=~/esp8266/esptool/esptool.py +FW_TOOL:=~/esp8266/other/esptool/esptool +SDK:=/home/cnlohr/esp8266/esp_iot_sdk_v0.9.3 +PORT:=/dev/ttyUSB0 +#PORT:=/dev/ttyACM0 + +XTLIB:=$(SDK)/lib +XTGCCLIB:=$(GCC_FOLDER)/gcc-4.9.1-elf/xtensa-lx106-elf/libgcc/libgcc.a +FOLDERPREFIX:=$(GCC_FOLDER)/root/bin +PREFIX:=$(FOLDERPREFIX)/xtensa-lx106-elf- +CC:=$(PREFIX)gcc + +CFLAGS:=-mlongcalls -I$(SDK)/include -Imyclib -Iinclude -Iuser -Os -I$(SDK)/include/ + +# \ +# + +LDFLAGS_CORE:=\ + -nostdlib \ + -Wl,--relax -Wl,--gc-sections \ + -L$(XTLIB) \ + -L$(XTGCCLIB) \ + $(SDK)/lib/liblwip.a \ + $(SDK)/lib/libssl.a \ + $(SDK)/lib/libupgrade.a \ + $(SDK)/lib/libnet80211.a \ + $(SDK)/lib/liblwip.a \ + $(SDK)/lib/libwpa.a \ + $(SDK)/lib/libnet80211.a \ + $(SDK)/lib/libphy.a \ + $(SDK)/lib/libmain.a \ + $(SDK)/lib/libpp.a \ + $(XTGCCLIB) \ + -T $(SDK)/ld/eagle.app.v6.ld + +LINKFLAGS:= \ + $(LDFLAGS_CORE) \ + -B$(XTLIB) + +#image.elf : $(OBJS) +# $(PREFIX)ld $^ $(LDFLAGS) -o $@ + +$(TARGET_OUT) : $(SRCS) + $(PREFIX)gcc $(CFLAGS) $^ -flto $(LINKFLAGS) -o $@ + + + +$(FW_FILE_1): $(TARGET_OUT) + @echo "FW $@" + $(FW_TOOL) -eo $(TARGET_OUT) -bo $@ -bs .text -bs .data -bs .rodata -bc -ec + +$(FW_FILE_2): $(TARGET_OUT) + @echo "FW $@" + $(FW_TOOL) -eo $(TARGET_OUT) -es .irom0.text $@ -ec + +burn : $(FW_FILE_1) $(FW_FILE_2) + ($(ESPTOOL_PY) --port $(PORT) write_flash 0x00000 0x00000.bin 0x40000 0x40000.bin)||(true) + + +clean : + rm -rf user/*.o driver/*.o $(TARGET_OUT) $(FW_FILE_1) $(FW_FILE_2) + + diff --git a/embedded8266/README.md b/embedded8266/README.md new file mode 100644 index 0000000..555f93b --- /dev/null +++ b/embedded8266/README.md @@ -0,0 +1,5 @@ +#ESP8266 ColorChord Driver + +Please see the main ws2812esp8266 project for help with setting up your environment and programming, etc. + + diff --git a/embedded8266/driver/uart.c b/embedded8266/driver/uart.c new file mode 100644 index 0000000..049dd88 --- /dev/null +++ b/embedded8266/driver/uart.c @@ -0,0 +1,247 @@ +/****************************************************************************** + * Copyright 2013-2014 Espressif Systems (Wuxi) + * + * FileName: uart.c + * + * Description: Two UART mode configration and interrupt handler. + * Check your hardware connection while use this mode. + * + * Modification history: + * 2014/3/12, v1.0 create this file. +*******************************************************************************/ +#include +#include +#include + +#include +//#include "ssc.h" +//#include "at.h" + +// UartDev is defined and initialized in rom code. +extern UartDevice UartDev; +//extern os_event_t at_recvTaskQueue[at_recvTaskQueueLen]; + +LOCAL void uart0_rx_intr_handler(void *para); + +/****************************************************************************** + * FunctionName : uart_config + * Description : Internal used function + * UART0 used for data TX/RX, RX buffer size is 0x100, interrupt enabled + * UART1 just used for debug output + * Parameters : uart_no, use UART0 or UART1 defined ahead + * Returns : NONE +*******************************************************************************/ +LOCAL void ICACHE_FLASH_ATTR +uart_config(uint8 uart_no) +{ + if (uart_no == UART1) + { + PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_U1TXD_BK); + } + else + { + /* rcv_buff size if 0x100 */ + ETS_UART_INTR_ATTACH(uart0_rx_intr_handler, &(UartDev.rcv_buff)); + PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD); +// PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_U0RTS); + } + + uart_div_modify(uart_no, UART_CLK_FREQ / (UartDev.baut_rate)); + + WRITE_PERI_REG(UART_CONF0(uart_no), UartDev.exist_parity + | UartDev.parity + | (UartDev.stop_bits << UART_STOP_BIT_NUM_S) + | (UartDev.data_bits << UART_BIT_NUM_S)); + + //clear rx and tx fifo,not ready + SET_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST); + CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST); + + //set rx fifo trigger +// WRITE_PERI_REG(UART_CONF1(uart_no), +// ((UartDev.rcv_buff.TrigLvl & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S) | +// ((96 & UART_TXFIFO_EMPTY_THRHD) << UART_TXFIFO_EMPTY_THRHD_S) | +// UART_RX_FLOW_EN); + if (uart_no == UART0) + { + //set rx fifo trigger + WRITE_PERI_REG(UART_CONF1(uart_no), + ((0x01 & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S) | + ((0x01 & UART_RX_FLOW_THRHD) << UART_RX_FLOW_THRHD_S) | + UART_RX_FLOW_EN); + } + else + { + WRITE_PERI_REG(UART_CONF1(uart_no), + ((UartDev.rcv_buff.TrigLvl & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S)); + } + + //clear all interrupt + WRITE_PERI_REG(UART_INT_CLR(uart_no), 0xffff); + //enable rx_interrupt + SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA); +} + +/****************************************************************************** + * FunctionName : uart1_tx_one_char + * Description : Internal used function + * Use uart1 interface to transfer one char + * Parameters : uint8 TxChar - character to tx + * Returns : OK +*******************************************************************************/ +LOCAL STATUS +uart_tx_one_char(uint8 uart, uint8 TxChar) +{ + while (true) + { + uint32 fifo_cnt = READ_PERI_REG(UART_STATUS(uart)) & (UART_TXFIFO_CNT<> UART_TXFIFO_CNT_S & UART_TXFIFO_CNT) < 126) { + break; + } + } + + WRITE_PERI_REG(UART_FIFO(uart) , TxChar); + return OK; +} + +/****************************************************************************** + * FunctionName : uart1_write_char + * Description : Internal used function + * Do some special deal while tx char is '\r' or '\n' + * Parameters : char c - character to tx + * Returns : NONE +*******************************************************************************/ +LOCAL void ICACHE_FLASH_ATTR +uart1_write_char(char c) +{ + if (c == '\n') + { + uart_tx_one_char(UART1, '\r'); + uart_tx_one_char(UART1, '\n'); + } + else if (c == '\r') + { + } + else + { + uart_tx_one_char(UART1, c); + } +} +/****************************************************************************** + * FunctionName : uart0_tx_buffer + * Description : use uart0 to transfer buffer + * Parameters : uint8 *buf - point to send buffer + * uint16 len - buffer len + * Returns : +*******************************************************************************/ +void ICACHE_FLASH_ATTR +uart0_tx_buffer(uint8 *buf, uint16 len) +{ + uint16 i; + + for (i = 0; i < len; i++) + { + uart_tx_one_char(UART0, buf[i]); + } +} + +/****************************************************************************** + * FunctionName : uart0_sendStr + * Description : use uart0 to transfer buffer + * Parameters : uint8 *buf - point to send buffer + * uint16 len - buffer len + * Returns : +*******************************************************************************/ +void ICACHE_FLASH_ATTR +uart0_sendStr(const char *str) +{ + while(*str) + { + uart_tx_one_char(UART0, *str++); + } +} + +/****************************************************************************** + * FunctionName : uart0_rx_intr_handler + * Description : Internal used function + * UART0 interrupt handler, add self handle code inside + * Parameters : void *para - point to ETS_UART_INTR_ATTACH's arg + * Returns : NONE +*******************************************************************************/ +extern void at_recvTask(void); + +LOCAL void +uart0_rx_intr_handler(void *para) +{ + /* uart0 and uart1 intr combine togther, when interrupt occur, see reg 0x3ff20020, bit2, bit0 represents + * uart1 and uart0 respectively + */ +// RcvMsgBuff *pRxBuff = (RcvMsgBuff *)para; +// uint8 RcvChar; + uint8 uart_no = UART0;//UartDev.buff_uart_no; + +// if (UART_RXFIFO_FULL_INT_ST != (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_FULL_INT_ST)) +// { +// return; +// } + if (UART_RXFIFO_FULL_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_FULL_INT_ST)) + { + at_recvTask(); + WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_FULL_INT_CLR); + } + +// WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_FULL_INT_CLR); + +// if (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S)) +// { +// RcvChar = READ_PERI_REG(UART_FIFO(uart_no)) & 0xFF; +// at_recvTask(); +// *(pRxBuff->pWritePos) = RcvChar; + +// system_os_post(at_recvTaskPrio, NULL, RcvChar); + +// //insert here for get one command line from uart +// if (RcvChar == '\r') +// { +// pRxBuff->BuffState = WRITE_OVER; +// } +// +// pRxBuff->pWritePos++; +// +// if (pRxBuff->pWritePos == (pRxBuff->pRcvMsgBuff + RX_BUFF_SIZE)) +// { +// // overflow ...we may need more error handle here. +// pRxBuff->pWritePos = pRxBuff->pRcvMsgBuff ; +// } +// } +} + +/****************************************************************************** + * FunctionName : uart_init + * Description : user interface for init uart + * Parameters : UartBautRate uart0_br - uart0 bautrate + * UartBautRate uart1_br - uart1 bautrate + * Returns : NONE +*******************************************************************************/ +void ICACHE_FLASH_ATTR +uart_init(UartBautRate uart0_br, UartBautRate uart1_br) +{ + // rom use 74880 baut_rate, here reinitialize + UartDev.baut_rate = uart0_br; + uart_config(UART0); + UartDev.baut_rate = uart1_br; + uart_config(UART1); + ETS_UART_INTR_ENABLE(); + + // install uart1 putc callback + os_install_putc1((void *)uart1_write_char); +} + +void ICACHE_FLASH_ATTR +uart_reattach() +{ + uart_init(BIT_RATE_74880, BIT_RATE_74880); +// ETS_UART_INTR_ATTACH(uart_rx_intr_handler_ssc, &(UartDev.rcv_buff)); +// ETS_UART_INTR_ENABLE(); +} diff --git a/embedded8266/image.elf b/embedded8266/image.elf new file mode 100755 index 0000000000000000000000000000000000000000..d7a260c4ba4d51634142f6f1ef98fdc7dbde62a9 GIT binary patch literal 238337 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 literal 0 HcmV?d00001 diff --git a/embedded8266/include/driver/uart.h b/embedded8266/include/driver/uart.h new file mode 100644 index 0000000..957621b --- /dev/null +++ b/embedded8266/include/driver/uart.h @@ -0,0 +1,101 @@ +#ifndef UART_APP_H +#define UART_APP_H + +#include "uart_register.h" +#include "eagle_soc.h" +#include "c_types.h" + +#define RX_BUFF_SIZE 256 +#define TX_BUFF_SIZE 100 +#define UART0 0 +#define UART1 1 + +typedef enum { + FIVE_BITS = 0x0, + SIX_BITS = 0x1, + SEVEN_BITS = 0x2, + EIGHT_BITS = 0x3 +} UartBitsNum4Char; + +typedef enum { + ONE_STOP_BIT = 0, + ONE_HALF_STOP_BIT = BIT2, + TWO_STOP_BIT = BIT2 +} UartStopBitsNum; + +typedef enum { + NONE_BITS = 0, + ODD_BITS = 0, + EVEN_BITS = BIT4 +} UartParityMode; + +typedef enum { + STICK_PARITY_DIS = 0, + STICK_PARITY_EN = BIT3 | BIT5 +} UartExistParity; + +typedef enum { + BIT_RATE_9600 = 9600, + BIT_RATE_19200 = 19200, + BIT_RATE_38400 = 38400, + BIT_RATE_57600 = 57600, + BIT_RATE_74880 = 74880, + BIT_RATE_115200 = 115200, + BIT_RATE_230400 = 230400, + BIT_RATE_460800 = 460800, + BIT_RATE_921600 = 921600 +} UartBautRate; + +typedef enum { + NONE_CTRL, + HARDWARE_CTRL, + XON_XOFF_CTRL +} UartFlowCtrl; + +typedef enum { + EMPTY, + UNDER_WRITE, + WRITE_OVER +} RcvMsgBuffState; + +typedef struct { + uint32 RcvBuffSize; + uint8 *pRcvMsgBuff; + uint8 *pWritePos; + uint8 *pReadPos; + uint8 TrigLvl; //JLU: may need to pad + RcvMsgBuffState BuffState; +} RcvMsgBuff; + +typedef struct { + uint32 TrxBuffSize; + uint8 *pTrxBuff; +} TrxMsgBuff; + +typedef enum { + BAUD_RATE_DET, + WAIT_SYNC_FRM, + SRCH_MSG_HEAD, + RCV_MSG_BODY, + RCV_ESC_CHAR, +} RcvMsgState; + +typedef struct { + UartBautRate baut_rate; + UartBitsNum4Char data_bits; + UartExistParity exist_parity; + UartParityMode parity; // chip size in byte + UartStopBitsNum stop_bits; + UartFlowCtrl flow_ctrl; + RcvMsgBuff rcv_buff; + TrxMsgBuff trx_buff; + RcvMsgState rcv_state; + int received; + int buff_uart_no; //indicate which uart use tx/rx buffer +} UartDevice; + +void uart_init(UartBautRate uart0_br, UartBautRate uart1_br); +void uart0_sendStr(const char *str); + +#endif + diff --git a/embedded8266/include/driver/uart_register.h b/embedded8266/include/driver/uart_register.h new file mode 100644 index 0000000..6398879 --- /dev/null +++ b/embedded8266/include/driver/uart_register.h @@ -0,0 +1,128 @@ +//Generated at 2012-07-03 18:44:06 +/* + * Copyright (c) 2010 - 2011 Espressif System + * + */ + +#ifndef UART_REGISTER_H_INCLUDED +#define UART_REGISTER_H_INCLUDED +#define REG_UART_BASE( i ) (0x60000000+(i)*0xf00) +//version value:32'h062000 + +#define UART_FIFO( i ) (REG_UART_BASE( i ) + 0x0) +#define UART_RXFIFO_RD_BYTE 0x000000FF +#define UART_RXFIFO_RD_BYTE_S 0 + +#define UART_INT_RAW( i ) (REG_UART_BASE( i ) + 0x4) +#define UART_RXFIFO_TOUT_INT_RAW (BIT(8)) +#define UART_BRK_DET_INT_RAW (BIT(7)) +#define UART_CTS_CHG_INT_RAW (BIT(6)) +#define UART_DSR_CHG_INT_RAW (BIT(5)) +#define UART_RXFIFO_OVF_INT_RAW (BIT(4)) +#define UART_FRM_ERR_INT_RAW (BIT(3)) +#define UART_PARITY_ERR_INT_RAW (BIT(2)) +#define UART_TXFIFO_EMPTY_INT_RAW (BIT(1)) +#define UART_RXFIFO_FULL_INT_RAW (BIT(0)) + +#define UART_INT_ST( i ) (REG_UART_BASE( i ) + 0x8) +#define UART_RXFIFO_TOUT_INT_ST (BIT(8)) +#define UART_BRK_DET_INT_ST (BIT(7)) +#define UART_CTS_CHG_INT_ST (BIT(6)) +#define UART_DSR_CHG_INT_ST (BIT(5)) +#define UART_RXFIFO_OVF_INT_ST (BIT(4)) +#define UART_FRM_ERR_INT_ST (BIT(3)) +#define UART_PARITY_ERR_INT_ST (BIT(2)) +#define UART_TXFIFO_EMPTY_INT_ST (BIT(1)) +#define UART_RXFIFO_FULL_INT_ST (BIT(0)) + +#define UART_INT_ENA( i ) (REG_UART_BASE( i ) + 0xC) +#define UART_RXFIFO_TOUT_INT_ENA (BIT(8)) +#define UART_BRK_DET_INT_ENA (BIT(7)) +#define UART_CTS_CHG_INT_ENA (BIT(6)) +#define UART_DSR_CHG_INT_ENA (BIT(5)) +#define UART_RXFIFO_OVF_INT_ENA (BIT(4)) +#define UART_FRM_ERR_INT_ENA (BIT(3)) +#define UART_PARITY_ERR_INT_ENA (BIT(2)) +#define UART_TXFIFO_EMPTY_INT_ENA (BIT(1)) +#define UART_RXFIFO_FULL_INT_ENA (BIT(0)) + +#define UART_INT_CLR( i ) (REG_UART_BASE( i ) + 0x10) +#define UART_RXFIFO_TOUT_INT_CLR (BIT(8)) +#define UART_BRK_DET_INT_CLR (BIT(7)) +#define UART_CTS_CHG_INT_CLR (BIT(6)) +#define UART_DSR_CHG_INT_CLR (BIT(5)) +#define UART_RXFIFO_OVF_INT_CLR (BIT(4)) +#define UART_FRM_ERR_INT_CLR (BIT(3)) +#define UART_PARITY_ERR_INT_CLR (BIT(2)) +#define UART_TXFIFO_EMPTY_INT_CLR (BIT(1)) +#define UART_RXFIFO_FULL_INT_CLR (BIT(0)) + +#define UART_CLKDIV( i ) (REG_UART_BASE( i ) + 0x14) +#define UART_CLKDIV_CNT 0x000FFFFF +#define UART_CLKDIV_S 0 + +#define UART_AUTOBAUD( i ) (REG_UART_BASE( i ) + 0x18) +#define UART_GLITCH_FILT 0x000000FF +#define UART_GLITCH_FILT_S 8 +#define UART_AUTOBAUD_EN (BIT(0)) + +#define UART_STATUS( i ) (REG_UART_BASE( i ) + 0x1C) +#define UART_TXD (BIT(31)) +#define UART_RTSN (BIT(30)) +#define UART_DTRN (BIT(29)) +#define UART_TXFIFO_CNT 0x000000FF +#define UART_TXFIFO_CNT_S 16 +#define UART_RXD (BIT(15)) +#define UART_CTSN (BIT(14)) +#define UART_DSRN (BIT(13)) +#define UART_RXFIFO_CNT 0x000000FF +#define UART_RXFIFO_CNT_S 0 + +#define UART_CONF0( i ) (REG_UART_BASE( i ) + 0x20) +#define UART_TXFIFO_RST (BIT(18)) +#define UART_RXFIFO_RST (BIT(17)) +#define UART_IRDA_EN (BIT(16)) +#define UART_TX_FLOW_EN (BIT(15)) +#define UART_LOOPBACK (BIT(14)) +#define UART_IRDA_RX_INV (BIT(13)) +#define UART_IRDA_TX_INV (BIT(12)) +#define UART_IRDA_WCTL (BIT(11)) +#define UART_IRDA_TX_EN (BIT(10)) +#define UART_IRDA_DPLX (BIT(9)) +#define UART_TXD_BRK (BIT(8)) +#define UART_SW_DTR (BIT(7)) +#define UART_SW_RTS (BIT(6)) +#define UART_STOP_BIT_NUM 0x00000003 +#define UART_STOP_BIT_NUM_S 4 +#define UART_BIT_NUM 0x00000003 +#define UART_BIT_NUM_S 2 +#define UART_PARITY_EN (BIT(1)) +#define UART_PARITY (BIT(0)) + +#define UART_CONF1( i ) (REG_UART_BASE( i ) + 0x24) +#define UART_RX_TOUT_EN (BIT(31)) +#define UART_RX_TOUT_THRHD 0x0000007F +#define UART_RX_TOUT_THRHD_S 24 +#define UART_RX_FLOW_EN (BIT(23)) +#define UART_RX_FLOW_THRHD 0x0000007F +#define UART_RX_FLOW_THRHD_S 16 +#define UART_TXFIFO_EMPTY_THRHD 0x0000007F +#define UART_TXFIFO_EMPTY_THRHD_S 8 +#define UART_RXFIFO_FULL_THRHD 0x0000007F +#define UART_RXFIFO_FULL_THRHD_S 0 + +#define UART_LOWPULSE( i ) (REG_UART_BASE( i ) + 0x28) +#define UART_LOWPULSE_MIN_CNT 0x000FFFFF +#define UART_LOWPULSE_MIN_CNT_S 0 + +#define UART_HIGHPULSE( i ) (REG_UART_BASE( i ) + 0x2C) +#define UART_HIGHPULSE_MIN_CNT 0x000FFFFF +#define UART_HIGHPULSE_MIN_CNT_S 0 + +#define UART_PULSE_NUM( i ) (REG_UART_BASE( i ) + 0x30) +#define UART_PULSE_NUM_CNT 0x0003FF +#define UART_PULSE_NUM_CNT_S 0 + +#define UART_DATE( i ) (REG_UART_BASE( i ) + 0x78) +#define UART_ID( i ) (REG_UART_BASE( i ) + 0x7C) +#endif // UART_REGISTER_H_INCLUDED diff --git a/embedded8266/include/string.h b/embedded8266/include/string.h new file mode 100644 index 0000000..bb97dcd --- /dev/null +++ b/embedded8266/include/string.h @@ -0,0 +1 @@ +//Nothing here. diff --git a/embedded8266/include/user_config.h b/embedded8266/include/user_config.h new file mode 100644 index 0000000..ff3f4e7 --- /dev/null +++ b/embedded8266/include/user_config.h @@ -0,0 +1,10 @@ +#ifndef __USER_CONFIG_H__ +#define __USER_CONFIG_H__ + +#define USE_US_TIMER +#define USE_OPTIMIZE_PRINTF +#define ESP_PLATFORM 1 + +#endif + + diff --git a/embedded8266/user/colorchord.c b/embedded8266/user/colorchord.c new file mode 100644 index 0000000..9fd5152 --- /dev/null +++ b/embedded8266/user/colorchord.c @@ -0,0 +1,150 @@ +#include "colorchord.h" + +static uint8_t donefirstrun; +static int8_t sintable[512]; //Actually [sin][cos] pairs. + +//LDD instruction on AVR can read with constant offset. We can set Y to be the place in the buffer, and read with offset. +static uint16_t datspace[bins*4]; //(advances,places,isses,icses) + +// +void HandleProgressiveInt( int8_t sample1, int8_t sample2 ) +{ + int i; + uint16_t startpl = 0; + int16_t ts, tc; + int16_t tmp1; + int8_t s1, c1; + uint16_t ipl, localipl, adv; + + + //startpl maps to 'Y' + // + + + //Estimated 68 minimum instructions... So for two pairs each... just under 5ksps, theoretical. + //Running overall at ~2kHz. + for( i = 0; i < bins; i++ ) //Loop, fixed size = 3 + 2 cycles 5 + { + //12 cycles MIN + adv = datspace[startpl++]; //Read, indirect from RAM (and increment) 2+2 cycles 4 + ipl = datspace[startpl++]; //Read, indirect from RAM (and increment) 2+2 cycles 4 + + //13 cycles MIN + ipl += adv; //Advance, 16bit += 16bit, 1 + 1 cycles 2 + localipl = (ipl>>8)<<1; //Select upper 8 bits 1 cycles 1 + + // need to load Z with 'sintable' and add localipl 2 + s1 = sintable[localipl++]; //Read s1 component out of table. 2+2 cycles 2 + c1 = sintable[localipl++]; //Read c1 component out of table. 2 cycles 2 + + ts = (s1 * sample1); // 8 x 8 multiply signed + copy R1 out. zero MSB ts 2 + tc = (c1 * sample1); // 8 x 8 multiply signed + copy R1 out. zero MSB tc 2 + + + //15 cycles MIN + ipl += adv; //Advance, 16bit += 16bit, 1 + 1 cycles 2 + localipl = (ipl>>8)<<1; //Select upper 8 bits 1 cycles 1 + + // need to load Z with 'sintable' and add localipl 2 + s1 = sintable[localipl++]; //Read s1 component out of table. 2 cycles 2 + c1 = sintable[localipl++]; //Read c1 component out of table. 2 cycles 2 + + ts += (s1 * sample2); // 8 x 8 multiply signed + add R1 out. 3 + tc += (c1 * sample2); // 8 x 8 multiply signed + add R1 out. 3 + + + //Add TS and TC to the datspace stuff. (24 instructions) + tmp1 = datspace[startpl]; //Read out, sin component. 4 + tmp1 -= tmp1>>6; //Subtract from the MSB (with carry) 2 + tmp1 += ts>>6; //Add MSBs with carry 2 + + datspace[startpl++] = tmp1; //Store values back 4 + + tmp1 = datspace[startpl]; //Read out, sin component. 4 + tmp1 -= tmp1>>6; //Subtract from the MSB (with carry) 2 + tmp1 += tc>>6; //Add MSBs with carry 2 + + datspace[startpl++] = tmp1; //Store values back 4 + + datspace[startpl-3] = ipl; //Store values back 4 + } +} + +void SetupConstants() +{ + int i; + static int last_place; + + if( !donefirstrun ) + { + donefirstrun = 1; + for( i = 0; i < 256; i++ ) + { + sintable[i*2+0] = i;//(int8_t)((sin( i / 256.0 * 6.283 ) * 127.0)); + sintable[i*2+1] = i+1;//(int8_t)((cos( i / 256.0 * 6.283 ) * 127.0)); + } + } + + + for( i = 0; i < bins; i++ ) + { + float freq = i;//frequencies[i]; + datspace[i*4] = 65536.0/freq; + } + +} + +/* +void DoDFTProgressiveInteger( float * outbins, float * frequencies, int bins, const float * databuffer, int place_in_data_buffer, int size_of_data_buffer, float q, float speedup ) +{ + int i; + static int last_place; + + if( !donefirstrun ) + { + donefirstrun = 1; + for( i = 0; i < 256; i++ ) + { + sintable[i*2+0] = (int8_t)((sinf( i / 256.0 * 6.283 ) * 127.0)); + sintable[i*2+1] = (int8_t)((cosf( i / 256.0 * 6.283 ) * 127.0)); + } + } + + if( gbins != bins ) + { + gbins = bins; + if( datspace ) free( datspace ); + datspace = malloc( bins * 2 * 4 ); + } + + + for( i = 0; i < bins; i++ ) + { + float freq = frequencies[i]; + datspace[i*4] = 65536.0/freq; + } + + + for( i = last_place; i != ( place_in_data_buffer&0xffffe ); i = (i+2)%size_of_data_buffer ) + { + int8_t ifr1 = (int8_t)( ((databuffer[i+0]) ) * 127 ); + int8_t ifr2 = (int8_t)( ((databuffer[i+1]) ) * 127 ); +// printf( "%d %d\n", i, place_in_data_buffer&0xffffe ); + HandleProgressiveInt( ifr1, ifr2 ); + } + + last_place = place_in_data_buffer&0xfffe; + + //Extract bins. + for( i = 0; i < bins; i++ ) + { + int16_t isps = datspace[i*4+2]; + int16_t ispc = datspace[i*4+3]; + int16_t mux = ( (isps/256) * (isps/256)) + ((ispc/256) * (ispc/256)); +// printf( "%d (%d %d)\n", mux, isps, ispc ); + outbins[i] = sqrt( mux )/100.0; + } +// printf( "\n"); +} + +*/ diff --git a/embedded8266/user/colorchord.h b/embedded8266/user/colorchord.h new file mode 100644 index 0000000..714deb8 --- /dev/null +++ b/embedded8266/user/colorchord.h @@ -0,0 +1,17 @@ +#ifndef _COLORCHORD_H +#define _COLORCHORD_H + +#include "mem.h" +#include "c_types.h" +#include "user_interface.h" +#include "ets_sys.h" +#include "osapi.h" + +#define bins 120 + +void HandleProgressiveInt( int8_t sample1, int8_t sample2 ); +void SetupConstants(); + +#endif + + diff --git a/embedded8266/user/mystuff.c b/embedded8266/user/mystuff.c new file mode 100644 index 0000000..78700b6 --- /dev/null +++ b/embedded8266/user/mystuff.c @@ -0,0 +1,3 @@ +#include "mystuff.h" + +char generic_print_buffer[384]; diff --git a/embedded8266/user/mystuff.h b/embedded8266/user/mystuff.h new file mode 100644 index 0000000..95756a8 --- /dev/null +++ b/embedded8266/user/mystuff.h @@ -0,0 +1,8 @@ +#ifndef _MYSTUFF_H +#define _MYSTUFF_H + +extern char generic_print_buffer[384]; + +#define printf( ... ) os_sprintf( generic_print_buffer, __VA_ARGS__ ); uart0_sendStr( generic_print_buffer ); + +#endif diff --git a/embedded8266/user/user_main.c b/embedded8266/user/user_main.c new file mode 100644 index 0000000..aa71bac --- /dev/null +++ b/embedded8266/user/user_main.c @@ -0,0 +1,143 @@ +#include "mem.h" +#include "c_types.h" +#include "user_interface.h" +#include "ets_sys.h" +#include "driver/uart.h" +#include "osapi.h" +#include "espconn.h" +#include "mystuff.h" +#include "ws2812.h" + +#define PORT 7777 +#define SERVER_TIMEOUT 1000 +#define MAX_CONNS 5 +#define MAX_FRAME 2000 + +#define procTaskPrio 0 +#define procTaskQueueLen 1 + + +static volatile os_timer_t some_timer; +static struct espconn *pUdpServer; + + + +//Note to self. In future consider looking at this: http://pastebin.com/6eLxSrNz + + + + + + + + +//Tasks that happen all the time. + +os_event_t procTaskQueue[procTaskQueueLen]; +static void ICACHE_FLASH_ATTR +procTask(os_event_t *events) +{ + system_os_post(procTaskPrio, 0, 0 ); + if( events->sig == 0 && events->par == 0 ) + { + //Idle Event. + } +} + + +//Timer event. +static void ICACHE_FLASH_ATTR + myTimer(void *arg) +{ + int i; + uart0_sendStr("."); + SetupConstants(); + +#define GPIO_OUTPUT_SET(gpio_no, bit_value) \ + gpio_output_set(bit_value<type = ESPCONN_UDP; + pUdpServer->proto.udp = (esp_udp *)os_zalloc(sizeof(esp_udp)); + pUdpServer->proto.udp->local_port = 7777; + espconn_regist_recvcb(pUdpServer, udpserver_recv); + + wifi_station_dhcpc_start(); + + if( espconn_create( pUdpServer ) ) + { + while(1) { uart0_sendStr( "\r\nFAULT\r\n" ); } + } + + //XXX TODO figure out how to safely re-allow this. + ets_wdt_disable(); + + char outbuffer[] = { 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,0xff,0xff, 0x00,0xff,0x00 }; + WS2812OutBuffer( outbuffer, 1 ); //Initialize the output. + + //Add a process + system_os_task(procTask, procTaskPrio, procTaskQueue, procTaskQueueLen); + + uart0_sendStr("\r\nCustom Server\r\n"); + WS2812OutBuffer( outbuffer, sizeof(outbuffer) ); + + + //Timer example + os_timer_disarm(&some_timer); + os_timer_setfn(&some_timer, (os_timer_func_t *)myTimer, NULL); + os_timer_arm(&some_timer, 1000, 1); + + system_os_post(procTaskPrio, 0, 0 ); +} + + diff --git a/embedded8266/user/ws2812.c b/embedded8266/user/ws2812.c new file mode 100644 index 0000000..6609723 --- /dev/null +++ b/embedded8266/user/ws2812.c @@ -0,0 +1,61 @@ +#include "ws2812.h" +#include "ets_sys.h" +#include "mystuff.h" +#include "osapi.h" + +#define GPIO_OUTPUT_SET(gpio_no, bit_value) \ + gpio_output_set(bit_value<