/* fht_codec.pde guest openmusiclabs.com 9.5.12 example sketch for running an fht on data collected with the codecshield. this will send out 128 bins of data over the serial port at 115.2kb. there is a pure data patch for visualizing the data. note: be sure to download the latest AudioCodec library if yours is older than 8.16.12. there were modifications made that allow for code outside of the interrupt. */ //#define SAMPLE_RATE 44 // 44.1Khz //#define ADCS 0 // no ADCs are being used #define LOG_OUT 1 // use the log output function #define LIN_OUT8 1 #define FHT_N 256 // set to 256 point fht #define FREQ 17 // include necessary libraries #include "FHT.h" //#include //#include //#include // create data variables for audio transfer //int left_in = 0x0000; //int left_out = 0x0000; //int right_in = 0x0000; //int right_out = 0x0000; unsigned int count = 0; volatile byte flag = 1; int fht_input2[FHT_N]; int fht_output[FHT_N]; char fht_phase[FHT_N/2]; char fht_phase2[FHT_N/2]; int phase = 0; int last_number = 0; int freq = 0; PROGMEM prog_uint8_t arctan[] = { #include }; PROGMEM prog_int16_t sinewave[] = { #include }; void setup() { Serial.begin(115200); // use serial port Serial.println("start"); // AudioCodec_init(); } void loop() { while(1) { // reduces clock jitter // while(flag); // wait for samples to be collected unsigned long t = millis(); fht_window(); // window the data fht_reorder(); // reorder for fht input fht_run(); // process fht // fht_mag_log(); // take output of fht // fht_mag_lin8(); // Serial.print('S'); // send out a start byte // Serial.print('o'); // int i = 0; // Serial.println("start"); // while (i < FHT_N/2) { // Serial.println(fht_lin_out8[i], DEC); // send out data bytes // i++; // } for (int i = 1; i < FHT_N/2; i++) { int j = fht_input[i] >> 1; int k = fht_input[FHT_N - i] >> 1; int l = j - k; // imaginary k = j + k; // real if (abs(l) <= 0x3ff) l <<= 5; // scale values by 32 else k >>= 5; if (k == 0) { // check edge cases if (l == 0) fht_phase[i] = 0x80; // indeterminate marker else if (l > 0) fht_phase[i] = 63; // pi/2 scaled else fht_phase[i] = -63; // -pi/2 scaled } else if (k > 0) { if (l >= 0) { j = l/k; if (j > 1023) fht_phase[i] = 63; // pi/2 scaled else fht_phase[i] = pgm_read_byte_near(arctan + j); } else { // invert all values for negatives j = -l/k; if (j > 1023) fht_phase[i] = -63; // pi/2 scaled else fht_phase[i] = -pgm_read_byte_near(arctan + j); } } else { // k is negative if (l >= 0) { j = -l/k; if (j > 1023) fht_phase[i] = 63; // pi/2 scaled else fht_phase[i] = 126 - pgm_read_byte_near(arctan + j); } else { // invert all values for negatives j = l/k; if (j > 1023) fht_phase[i] = -63; // pi/2 scaled else fht_phase[i] = pgm_read_byte_near(arctan + j) - 126; } } } // Serial.print(phase, DEC); // Serial.print("\t"); // Serial.print(fht_input[4], DEC); // Serial.print("\t"); // Serial.print(fht_input[252], DEC); // Serial.print("\t"); // int c = fht_input[252] >> 1; // int d = fht_input[4] >> 1; // Serial.print(d-c, DEC); // Serial.print("\t"); // Serial.print(d+c, DEC); // Serial.print("\t"); // int mag = (d-c)/((d+c) >> 5); // Serial.print(mag, DEC); // Serial.print("\t"); // Serial.print(fht_phase[4], DEC); for (int i = 0; i < FHT_N; i++) { fht_input[i] = fht_input2[i]; } // Serial.println(fht_phase[4], DEC); fht_window(); // window the data fht_reorder(); // reorder for fht input fht_run(); // process fht // fht_mag_log(); // take output of fht // int i = 0; // Serial.println("start"); // while (i < FHT_N/2) { // Serial.println(fht_log_out[i], DEC); // send out data bytes // i++; // } // Serial.print('t'); // send second packet indicator // i = 0; // while (i < FHT_N) { // Serial.println(fht_input[i]); // send out data bytes // i++; // } for (int i = 1; i < FHT_N/2; i++) { int j = fht_input[i] >> 1; int k = fht_input[FHT_N - i] >> 1; int l = j - k; // imaginary k = j + k; // real if (abs(l) <= 0x3ff) l <<= 5; // scale values by 32 else k >>= 5; if (k == 0) { // check edge cases if (l == 0) fht_phase2[i] = 0x80; // indeterminate marker else if (l > 0) fht_phase2[i] = 63; // pi/2 scaled else fht_phase2[i] = -63; // -pi/2 scaled } else if (k > 0) { if (l >= 0) { j = l/k; if (j > 1023) fht_phase2[i] = 63; // pi/2 scaled else fht_phase2[i] = pgm_read_byte_near(arctan + j); } else { // invert all values for negatives j = -l/k; if (j > 1023) fht_phase2[i] = -63; // pi/2 scaled else fht_phase2[i] = -pgm_read_byte_near(arctan + j); } } else { // k is negative if (l >= 0) { j = -l/k; if (j > 1023) fht_phase2[i] = 63; // pi/2 scaled else fht_phase2[i] = 126 - pgm_read_byte_near(arctan + j); } else { // invert all values for negatives j = l/k; if (j > 1023) fht_phase2[i] = -63; // pi/2 scaled else fht_phase2[i] = pgm_read_byte_near(arctan + j) - 126; } } } // Serial.print("\t"); // Serial.print(fht_phase[4], DEC); // Serial.print("\t"); // Serial.print(fht_phase2[4], DEC); // Serial.print("\t"); for (int i = 1; i < FHT_N/2; i++) { char m = fht_phase2[i]; char n = fht_phase[i]; if (m == -0x80); // dont add null cases else if (n == -0x80) fht_phase2[i] = n; else { int p = m - n; if (p > 126) p -= 252; // deal with wrap around else if (p < -126) p += 252; fht_phase2[i] = p; } } // int s = (fht_phase2[4] + last_number) >> 1; // last_number = fht_phase2[4]; Serial.println(millis() - t, DEC); phase++; phase &= 0x03ff; freq += random(1023); // at this point fht_phase2 is full of the phase differences // flag = 1; // tell the codec that processing is done for (int i = 0; i < FHT_N; i++) { freq += FREQ; freq &= 0x03ff; fht_input[i] = pgm_read_word_near(sinewave + freq); fht_input2[i] = pgm_read_word_near(sinewave + ((freq + phase) & 0x03ff)); } delay(100); } }