21 #define CQT_HIGHRANGE_SPLIT_AT_BIN 58
27 #define OSC_BANK_SIZE 10
33 #define TX_PERIODIC_FFT
52 #define TX_CQT_PERIOD 163
90 sprintf(
name,
"AppCQT");
91 if (
ad == NULL ||
am== NULL)
return;
94 sprintf(buffer,
"waveform:%d", i+1);
98 if (
osc[i]!=NULL)
osc[i]->
begin(0.0, 0, WAVEFORM_SINE);
104 if(
fft == NULL ||
fft2 == NULL)
return;
107 memset(&
fftRVal,0,
sizeof(FFTReadRange));
108 memset(&
oscBank,0,
sizeof(FFTReadRange)* OSC_BANK_SIZE);
115 for (uint16_t i=0;i < NOTE_ARRAY_LENGTH;i++){
118 if (i > 0 && i < NOTE_ARRAY_LENGTH-1){
128 memset(&
fftHighRR[i],0,
sizeof(FFTReadRange));
129 memset(&
fftLowRR[i],0,
sizeof(FFTReadRange));
173 #ifdef TX_PERIODIC_FFT
175 if(
sci==NULL)
return;
179 sci->printf(F(
"S 512"));
180 for(
int i = 0; i < 512; i+=1){
193 sci->println(F(
"S FIN"));
202 if (
oscBank[i].
cqtBin <
high_range)
sci->printf(F(
"CQT_L %d,%s,%.0f,%.0f,%.2f,%.3f,%.3f\n"),
oscBank[i].
cqtBin,
note_name[
oscBank[i].
cqtBin],
oscBank[i].
peakFrequency,
note_freq[
oscBank[i].
cqtBin],
oscBank[i].
phase,
oscBank[i].
avgValueFast,
oscBank[i].
avgValueSlow*1000.0,
oscBank[i].
transientValue*100.0);
203 if (
oscBank[i].
cqtBin >=
high_range)
sci->printf(F(
"CQT_H %d,%s,%.0f,%.0f,%.2f,%.3f,%.3f\n"),
oscBank[i].
cqtBin,
note_name[
oscBank[i].
cqtBin],
oscBank[i].
peakFrequency,
note_freq[
oscBank[i].
cqtBin],
oscBank[i].
phase,
oscBank[i].
avgValueFast,
oscBank[i].
avgValueSlow*1000.0,
oscBank[i].
transientValue*100.0);
205 sci->printf(F(
"CQT_EOF\n"));
215 if (
draw == NULL)
return;
218 draw->setFont(Arial_8);
219 draw->setTextColor(ILI9341_DARKGREY);
220 for(uint8_t i=1;i < 18; i++){
221 draw->drawLine(
x,
y + (
h - (log1p((0.1 * i))) *
h),
x+
w,
y + (
h - (log1p((0.1 * i))) *
h),ILI9341_DARKCYAN);
223 draw->setCursor(
x + i * 17,
y+ (
h - (log1p((0.1 * i))) *
h) - 9);
224 if (i < 17)
draw->print((log1p((0.1 * i))));
236 signal = (log1p(amp)) *
h;
237 if (signal>(
h-1)) signal =
h-1;
238 if (signal<0) signal = 0;
241 draw->fillRoundRect(
x+nx,
y+
h - (uint16_t)signal,2,(uint16_t)signal,1,ILI9341_CYAN);
243 signal = (log1p(amp)) *
h;
244 if (signal>(
h-1)) signal =
h-1;
245 if (signal<0) signal = 0;
247 draw->fillRoundRect(
x+nx,
y+
h - (uint16_t)signal,2,(uint16_t)signal,1,ILI9341_MAGENTA);
251 draw->setTextColor(ILI9341_GREENYELLOW);
254 signal = (log1p(amp)) *
h;
255 if (signal<0) signal = 0;
256 if (signal>(
h-1)) signal =
h-1;
258 if ((
y+
h - (uint16_t)signal) <
h && signal > 1)
draw->fillRoundRect(
x+nx,
y+
h - (uint16_t)signal,2,4,1,CL(0xFF,0xA0,(uint8_t)(300*
oscBank[i].
transientValue)));
260 draw->setCursor(
x+nx - 5,
y+
h - (uint16_t)signal - 35);
262 draw->setCursor(
x+nx - 5,
y+
h - (uint16_t)signal - 50);
268 draw->drawRoundRect(
x,
y,
w,
h,4,ILI9341_MAGENTA);
272 draw->setTextColor(ILI9341_DARKCYAN);
275 draw->setTextColor(ILI9341_MAGENTA);
283 if (
fft == NULL ||
fft2 == NULL)
return;
298 if (
fft == NULL ||
fft2 == NULL)
return;
305 if (
fft == NULL ||
fft2 == NULL)
return;
311 void FLASHMEM
onTouch(uint16_t t_x, uint16_t t_y){
313 if (t_x >
x && t_x < (
x +
w) && t_y >
y && t_y < (
y +
h)){
331 float peak_read=-1000;
334 if(
fft==NULL ||
fft2==NULL)
return;
339 for (uint16_t i=0; i < NOTE_ARRAY_LENGTH; i++){
349 if (low_range_switch==
false){
352 }
else if (low_range_switch==
true){
362 if (low_range_switch){
412 float dominantPhase = 0;
413 if (low_range_switch){
415 }
else dominantPhase =
fftHighRR[0].phase;;
422 float64_t phase_aligner;
428 phase_aligner = ((dominantPhase -
oscBank[i].phase)/dominantPhase);
429 phase_aligner = (phase_aligner * (float64_t)
osc[i]->getPhase()) +
pll_p;
430 if(!isnan(phase_aligner)) phase_aligner=0;
433 if (f > 20000) f = 20000;
448 if(strcmp(message,ENABLE)==0){
450 }
else if(strcmp(message,DISABLE)==0){
454 if(sender->
isName(
"SCI")){
455 Serial.print(F(
"M appCQT::MessageHandler SCI param: "));
456 Serial.println(message);
457 if (strcmp(message,CQT_INFO)==0){
461 for (uint16_t i=1;i< NOTE_ARRAY_LENGTH - 1;i++){
463 sci->printf(F(
"M L %d,%f,%f,%d,%d,%d\t\t\t"),
fftLowRR[i].
cqtBin,
fftLowRR[i].
startFrequency,
fftLowRR[i].
stopFrequency,
fftLowRR[i].
startBin,
fftLowRR[i].
stopBin,
fftLowRR[i].
stopBin-
fftLowRR[i].
startBin);
464 sci->printf(F(
"M H %d,%f,%f,%d,%d,%d\n"),
fftHighRR[i].
cqtBin,
fftHighRR[i].
startFrequency,
fftHighRR[i].
stopFrequency,
fftHighRR[i].
startBin,
fftHighRR[i].
stopBin,
fftHighRR[i].
stopBin-
fftHighRR[i].
startBin);
static const char * note_name[]
const float octave_down[]
static const float note_freq[]
SvcSerialCommandInterface * sci
void requestPopUp(bool exclusive=false)
request popup from the AppManager will be activated by the next render loop applications in popup m...
void releasePopUp()
gives up popup
bool isName(const char *name_string)
Compares the name_string to the app class instance name (string)
char name[MAX_NAME_LENGTH]
base class definition / implementation from which all app classes will be derived and override
void FLASHMEM onFocus()
Event handler called when the app gains focus.
void FLASHMEM onFocusLost()
Event handler called when the app loses focus.
erisAudioSynthWaveform * osc[OSC_BANK_SIZE]
void FLASHMEM update()
update loop
void onTouchRelease(uint16_t x, uint16_t y)
Event handler for touch release.
void messageHandler(AppBaseClass *sender, const char *message)
receiver method for inter-app string based communication
uint8_t fft_buffer_select_for_serial_transmit
FFTReadRange fftLowRR[NOTE_ARRAY_LENGTH]
void FLASHMEM onTouch(uint16_t t_x, uint16_t t_y)
Event handler called on touch.
erisAudioAnalyzeFFT1024 * fft
FFTReadRange fftHighRR[NOTE_ARRAY_LENGTH]
elapsedMillis fft_buffer_serial_transmit_elapsed
FFTReadRange oscBank[OSC_BANK_SIZE]
void FASTRUN render()
render loop
elapsedMillis cqt_serial_transmit_elapsed
erisAudioAnalyzeFFT1024 * fft2
void FASTRUN updateOscillatorBank(bool low_range_switch)
Implements the AppCQT class Constant Q Transform Application.
AudioStream * getAudioStreamObjByName(const char *AudioStreamObjName)
int32_t read(const char *key)
returns the int32_t value of the record
bool create(const char *key, int32_t val, uint32_t *owner)
create a record with ownership
bool increment(const char *key)
increments the value of a global record creates a new record if one does not exist and initializes ...
bool requestStartLZ4Message()
request to start a lz4 compressed message starts the message and returns true if available returns f...
void sendLZ4Message()
Calling this function signals the end of a compressed message. The txBuffer contents are lz4 compres...
void enableFFT(bool enable_state)
static void sort_fftrr_by_cqt_bin(FFTReadRange *a, size_t n)
static void sort_fftrr_by_value(FFTReadRange *a, size_t n)
float read(unsigned int binNumber)