You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

399 lines
8.2KB

  1. #include "AudioStream.h"
  2. extern "C" {
  3. extern const int16_t AudioWindowHanning256[];
  4. extern const int16_t AudioWindowBartlett256[];
  5. extern const int16_t AudioWindowBlackman256[];
  6. extern const int16_t AudioWindowFlattop256[];
  7. extern const int16_t AudioWindowBlackmanHarris256[];
  8. extern const int16_t AudioWindowNuttall256[];
  9. extern const int16_t AudioWindowBlackmanNuttall256[];
  10. extern const int16_t AudioWindowWelch256[];
  11. extern const int16_t AudioWindowHamming256[];
  12. extern const int16_t AudioWindowCosine256[];
  13. extern const int16_t AudioWindowTukey256[];
  14. }
  15. class AudioAnalyzeFFT256 : public AudioStream
  16. {
  17. public:
  18. AudioAnalyzeFFT256(uint8_t navg = 8, const int16_t *win = AudioWindowHanning256)
  19. : AudioStream(1, inputQueueArray), outputflag(false),
  20. prevblock(NULL), count(0), naverage(navg), window(win) { init(); }
  21. bool available() {
  22. if (outputflag == true) {
  23. outputflag = false;
  24. return true;
  25. }
  26. return false;
  27. }
  28. virtual void update(void);
  29. //uint32_t cycles;
  30. int32_t output[128] __attribute__ ((aligned (4)));
  31. private:
  32. void init(void);
  33. const int16_t *window;
  34. audio_block_t *prevblock;
  35. int16_t buffer[512] __attribute__ ((aligned (4)));
  36. uint8_t count;
  37. uint8_t naverage;
  38. bool outputflag;
  39. audio_block_t *inputQueueArray[1];
  40. };
  41. class AudioSineWave : public AudioStream
  42. {
  43. public:
  44. AudioSineWave() : AudioStream(0, NULL) { magnitude = 0; }
  45. void frequency(float freq);
  46. //void amplitude(double n) { amplitude((float)n); }
  47. void amplitude(float n) { // 0 to 1.0
  48. if (n < 0) n = 0;
  49. else if (n > 1.0) n = 1.0;
  50. magnitude = n * 32767.0;
  51. Serial.print("magnitude(f) = ");
  52. Serial.println(magnitude);
  53. }
  54. /*
  55. void amplitude(int n) { // 0 to 32767
  56. if (n < 0) n = 0;
  57. else if (n > 32767) n = 32767;
  58. magnitude = n;
  59. Serial.print("magnitude(i) = ");
  60. Serial.println(magnitude);
  61. }
  62. void amplitude(unsigned int n) { // 0 to 32767
  63. if (n > 32767) n = 32767;
  64. magnitude = n;
  65. Serial.print("magnitude(u) = ");
  66. Serial.println(magnitude);
  67. }
  68. */
  69. virtual void update(void);
  70. private:
  71. uint16_t magnitude;
  72. uint32_t phase;
  73. uint32_t phase_increment;
  74. };
  75. class AudioSineWaveMod : public AudioStream
  76. {
  77. public:
  78. AudioSineWaveMod() : AudioStream(1, inputQueueArray) {}
  79. void frequency(float freq);
  80. //void amplitude(q15 n);
  81. virtual void update(void);
  82. private:
  83. uint32_t phase;
  84. uint32_t phase_increment;
  85. uint32_t modulation_factor;
  86. audio_block_t *inputQueueArray[1];
  87. };
  88. class AudioOutputPWM : public AudioStream
  89. {
  90. public:
  91. AudioOutputPWM(void) : AudioStream(1, inputQueueArray) { begin(); }
  92. virtual void update(void);
  93. void begin(void);
  94. friend void dma_ch3_isr(void);
  95. private:
  96. static audio_block_t *block_1st;
  97. static audio_block_t *block_2nd;
  98. static uint32_t block_offset;
  99. static bool update_responsibility;
  100. static uint8_t interrupt_count;
  101. audio_block_t *inputQueueArray[1];
  102. };
  103. class AudioPrint : public AudioStream
  104. {
  105. public:
  106. AudioPrint(const char *str) : AudioStream(1, inputQueueArray), name(str) {}
  107. virtual void update(void);
  108. private:
  109. const char *name;
  110. audio_block_t *inputQueueArray[1];
  111. };
  112. class AudioInputI2S : public AudioStream
  113. {
  114. public:
  115. AudioInputI2S(void) : AudioStream(0, NULL) { begin(); }
  116. virtual void update(void);
  117. void begin(void);
  118. friend void dma_ch1_isr(void);
  119. private:
  120. static audio_block_t *block_left;
  121. static audio_block_t *block_right;
  122. static uint16_t block_offset;
  123. static bool update_responsibility; // TODO: implement and test this.
  124. };
  125. class AudioOutputI2S : public AudioStream
  126. {
  127. public:
  128. AudioOutputI2S(void) : AudioStream(2, inputQueueArray) { begin(); }
  129. virtual void update(void);
  130. void begin(void);
  131. friend void dma_ch0_isr(void);
  132. friend class AudioInputI2S;
  133. private:
  134. static void config_i2s(void);
  135. static audio_block_t *block_left_1st;
  136. static audio_block_t *block_right_1st;
  137. static audio_block_t *block_left_2nd;
  138. static audio_block_t *block_right_2nd;
  139. static uint16_t block_left_offset;
  140. static uint16_t block_right_offset;
  141. static bool update_responsibility;
  142. audio_block_t *inputQueueArray[2];
  143. };
  144. class AudioInputAnalog : public AudioStream
  145. {
  146. public:
  147. AudioInputAnalog(unsigned int pin) : AudioStream(0, NULL) { begin(pin); }
  148. virtual void update(void);
  149. void begin(unsigned int pin);
  150. friend void dma_ch2_isr(void);
  151. private:
  152. static audio_block_t *block_left;
  153. static uint16_t block_offset;
  154. uint16_t dc_average;
  155. //static bool update_responsibility; // TODO: implement and test this.
  156. };
  157. #include "SD.h"
  158. class AudioPlaySDcardWAV : public AudioStream
  159. {
  160. public:
  161. AudioPlaySDcardWAV(void) : AudioStream(0, NULL) { begin(); }
  162. void begin(void);
  163. bool play(const char *filename);
  164. void stop(void);
  165. bool start(void);
  166. virtual void update(void);
  167. private:
  168. File wavfile;
  169. bool consume(void);
  170. bool parse_format(void);
  171. uint32_t header[5];
  172. uint32_t data_length;
  173. audio_block_t *block_left;
  174. audio_block_t *block_right;
  175. uint16_t block_offset;
  176. uint8_t buffer[512];
  177. uint16_t buffer_remaining;
  178. uint8_t state;
  179. uint8_t state_play;
  180. uint8_t leftover_bytes;
  181. };
  182. class AudioPlaySDcardRAW : public AudioStream
  183. {
  184. public:
  185. AudioPlaySDcardRAW(void) : AudioStream(0, NULL) { begin(); }
  186. void begin(void);
  187. bool play(const char *filename);
  188. void stop(void);
  189. virtual void update(void);
  190. private:
  191. File rawfile;
  192. audio_block_t *block;
  193. bool playing;
  194. bool paused;
  195. };
  196. class AudioMixer4 : public AudioStream
  197. {
  198. public:
  199. AudioMixer4(void) : AudioStream(4, inputQueueArray) {
  200. //for (int i=0; i<4; i++) gain(i, 1.0f);
  201. for (int i=0; i<4; i++) multiplier[i] = 65536;
  202. }
  203. virtual void update(void);
  204. /*
  205. void gain(unsigned int channel, float gain) {
  206. if (channel >= 4) return;
  207. if (gain > 32767.0f) gain = 32767.0f;
  208. else if (gain < 0.0f) gain = 0.0f;
  209. multiplier[channel] = gain * 65536.0f; // TODO: proper roundoff?
  210. }
  211. */
  212. private:
  213. int32_t multiplier[4];
  214. audio_block_t *inputQueueArray[4];
  215. };
  216. // TODO: more audio processing objects....
  217. // N-channel mixer, adjustable gain on each channel
  218. // sine wave with frequency modulation (phase)
  219. // non-sine oscillators, ramp, triangle, square/pulse, etc
  220. // envelope: attack-decay-sustain-release, maybe other more complex?
  221. // filters, low pass, high pass, bandpass, notch
  222. // frequency analysis - FFT, single frequency (eg, filter for DTMF)
  223. // MP3 decoding - it is possible with optimized code?
  224. // other decompression, ADPCM, Vorbis, Speex, etc?
  225. // A base class for all Codecs, DACs and ADCs, so at least the
  226. // most basic functionality is consistent.
  227. #define AUDIO_INPUT_LINEIN 0
  228. #define AUDIO_INPUT_MIC 1
  229. class AudioControl
  230. {
  231. public:
  232. virtual bool enable(void) = 0;
  233. virtual bool disable(void) = 0;
  234. virtual bool volume(float volume) = 0; // volume 0.0 to 100.0
  235. virtual bool inputLevel(float volume) = 0; // volume 0.0 to 100.0
  236. virtual bool inputSelect(int n) = 0;
  237. };
  238. class AudioControlWM8731 : public AudioControl
  239. {
  240. public:
  241. bool enable(void);
  242. bool volume(float n) { return volumeInteger(n * 0.8 + 47.499); }
  243. bool inputLevel(float n) { return false; }
  244. bool inputSelect(int n) { return false; }
  245. protected:
  246. bool write(unsigned int reg, unsigned int val);
  247. bool volumeInteger(unsigned int n); // range: 0x2F to 0x7F
  248. };
  249. class AudioControlSGTL5000 : public AudioControl
  250. {
  251. public:
  252. bool enable(void);
  253. bool disable(void) { return false; }
  254. bool volume(float n) { return volumeInteger(n * 1.29 + 0.499); }
  255. bool inputLevel(float n) {return false;}
  256. bool muteHeadphone(void) { return write(0x0024, ana_ctrl | (1<<4)); }
  257. bool unmuteHeadphone(void) { return write(0x0024, ana_ctrl & ~(1<<4)); }
  258. bool muteLineout(void) { return write(0x0024, ana_ctrl | (1<<8)); }
  259. bool unmuteLineout(void) { return write(0x0024, ana_ctrl & ~(1<<8)); }
  260. bool inputSelect(int n) {
  261. if (n == AUDIO_INPUT_LINEIN) {
  262. return write(0x0024, ana_ctrl | (1<<2));
  263. } else if (n == AUDIO_INPUT_MIC) {
  264. //return write(0x002A, 0x0172) && write(0x0024, ana_ctrl & ~(1<<2));
  265. return write(0x002A, 0x0173) && write(0x0024, ana_ctrl & ~(1<<2)); // +40dB
  266. } else {
  267. return false;
  268. }
  269. }
  270. //bool inputLinein(void) { return write(0x0024, ana_ctrl | (1<<2)); }
  271. //bool inputMic(void) { return write(0x002A, 0x0172) && write(0x0024, ana_ctrl & ~(1<<2)); }
  272. protected:
  273. bool muted;
  274. bool volumeInteger(unsigned int n); // range: 0x00 to 0x80
  275. uint16_t ana_ctrl;
  276. unsigned int read(unsigned int reg);
  277. bool write(unsigned int reg, unsigned int val);
  278. };