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.

407 line
8.5KB

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