146 lines
4.4KB

  1. #include <LiquidCrystal.h>
  2. #include <Audio.h>
  3. #include <Wire.h>
  4. #include <SPI.h>
  5. #include <SD.h>
  6. #include <SerialFlash.h>
  7. // GUItool: begin automatically generated code
  8. AudioInputI2S i2s1; //xy=139,91
  9. AudioMixer4 mixer1; //xy=312,134
  10. AudioOutputI2S i2s2; //xy=392,32
  11. AudioAnalyzeFFT1024 fft1024; //xy=467,147
  12. AudioConnection patchCord1(i2s1, 0, mixer1, 0);
  13. AudioConnection patchCord2(i2s1, 0, i2s2, 0);
  14. AudioConnection patchCord3(i2s1, 1, mixer1, 1);
  15. AudioConnection patchCord4(i2s1, 1, i2s2, 1);
  16. AudioConnection patchCord5(mixer1, fft1024);
  17. AudioControlSGTL5000 audioShield; //xy=366,225
  18. // GUItool: end automatically generated code
  19. const int myInput = AUDIO_INPUT_LINEIN;
  20. //const int myInput = AUDIO_INPUT_MIC;
  21. // The scale sets how much sound is needed in each frequency range to
  22. // show all 8 bars. Higher numbers are more sensitive.
  23. float scale = 60.0;
  24. // An array to hold the 16 frequency bands
  25. float level[16];
  26. // This array holds the on-screen levels. When the signal drops quickly,
  27. // these are used to lower the on-screen level 1 bar per update, which
  28. // looks more pleasing to corresponds to human sound perception.
  29. int shown[16];
  30. // Use the LiquidCrystal library to display the spectrum
  31. //
  32. LiquidCrystal lcd(0, 1, 2, 3, 4, 5);
  33. byte bar1[8] = {0,0,0,0,0,0,0,255};
  34. byte bar2[8] = {0,0,0,0,0,0,255,255}; // 8 bar graph
  35. byte bar3[8] = {0,0,0,0,0,255,255,255}; // custom
  36. byte bar4[8] = {0,0,0,0,255,255,255,255}; // characters
  37. byte bar5[8] = {0,0,0,255,255,255,255,255};
  38. byte bar6[8] = {0,0,255,255,255,255,255,255};
  39. byte bar7[8] = {0,255,255,255,255,255,255,255};
  40. byte bar8[8] = {255,255,255,255,255,255,255,255};
  41. void setup() {
  42. // Audio requires memory to work.
  43. AudioMemory(12);
  44. // Enable the audio shield and set the output volume.
  45. audioShield.enable();
  46. audioShield.inputSelect(myInput);
  47. audioShield.volume(0.5);
  48. // turn on the LCD and define the custom characters
  49. lcd.begin(16, 2);
  50. lcd.print("Audio Spectrum");
  51. lcd.createChar(0, bar1);
  52. lcd.createChar(1, bar2);
  53. lcd.createChar(2, bar3);
  54. lcd.createChar(3, bar4);
  55. lcd.createChar(4, bar5);
  56. lcd.createChar(5, bar6);
  57. lcd.createChar(6, bar7);
  58. lcd.createChar(7, bar8);
  59. // configure the mixer to equally add left & right
  60. mixer1.gain(0, 0.5);
  61. mixer1.gain(1, 0.5);
  62. // pin 21 will select rapid vs animated display
  63. pinMode(21, INPUT_PULLUP);
  64. }
  65. void loop() {
  66. if (fft1024.available()) {
  67. // read the 512 FFT frequencies into 16 levels
  68. // music is heard in octaves, but the FFT data
  69. // is linear, so for the higher octaves, read
  70. // many FFT bins together.
  71. level[0] = fft1024.read(0);
  72. level[1] = fft1024.read(1);
  73. level[2] = fft1024.read(2, 3);
  74. level[3] = fft1024.read(4, 6);
  75. level[4] = fft1024.read(7, 10);
  76. level[5] = fft1024.read(11, 15);
  77. level[6] = fft1024.read(16, 22);
  78. level[7] = fft1024.read(23, 32);
  79. level[8] = fft1024.read(33, 46);
  80. level[9] = fft1024.read(47, 66);
  81. level[10] = fft1024.read(67, 93);
  82. level[11] = fft1024.read(94, 131);
  83. level[12] = fft1024.read(132, 184);
  84. level[13] = fft1024.read(185, 257);
  85. level[14] = fft1024.read(258, 359);
  86. level[15] = fft1024.read(360, 511);
  87. // See this conversation to change this to more or less than 16 log-scaled bands?
  88. // https://forum.pjrc.com/threads/32677-Is-there-a-logarithmic-function-for-FFT-bin-selection-for-any-given-of-bands
  89. // if you have the volume pot soldered to your audio shield
  90. // uncomment this line to make it adjust the full scale signal
  91. //scale = 8.0 + analogRead(A1) / 5.0;
  92. // begin drawing at the first character on the 2nd row
  93. lcd.setCursor(0, 1);
  94. for (int i=0; i<16; i++) {
  95. Serial.print(level[i]);
  96. // TODO: conversion from FFT data to display bars should be
  97. // exponentially scaled. But how keep it a simple example?
  98. int val = level[i] * scale;
  99. if (val > 8) val = 8;
  100. if (val >= shown[i]) {
  101. shown[i] = val;
  102. } else {
  103. if (shown[i] > 0) shown[i] = shown[i] - 1;
  104. val = shown[i];
  105. }
  106. //Serial.print(shown[i]);
  107. Serial.print(" ");
  108. // print each custom digit
  109. if (shown[i] == 0) {
  110. lcd.write(' ');
  111. } else {
  112. lcd.write(shown[i] - 1);
  113. }
  114. }
  115. Serial.print(" cpu:");
  116. Serial.println(AudioProcessorUsageMax());
  117. }
  118. }