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.

Audio.h 9.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. #include "AudioStream.h"
  2. // When changing multiple audio object settings that must update at
  3. // the same time, these functions allow the audio library interrupt
  4. // to be disabled. For example, you may wish to begin playing a note
  5. // in response to reading an analog sensor. If you have "velocity"
  6. // information, you might start the sample playing and also adjust
  7. // the gain of a mixer channel. Use AudioNoInterrupts() first, then
  8. // make both changes to the 2 separate objects. Then allow the audio
  9. // library to update with AudioInterrupts(). Both changes will happen
  10. // at the same time, because AudioNoInterrupts() prevents any updates
  11. // while you make changes.
  12. #define AudioNoInterrupts() (NVIC_DISABLE_IRQ(IRQ_SOFTWARE))
  13. #define AudioInterrupts() (NVIC_ENABLE_IRQ(IRQ_SOFTWARE))
  14. // waveforms.c
  15. extern "C" {
  16. extern const int16_t AudioWaveformSine[257];
  17. extern const int16_t AudioWaveformTriangle[257];
  18. extern const int16_t AudioWaveformSquare[257];
  19. extern const int16_t AudioWaveformSawtooth[257];
  20. }
  21. // windows.c
  22. extern "C" {
  23. extern const int16_t AudioWindowHanning256[];
  24. extern const int16_t AudioWindowBartlett256[];
  25. extern const int16_t AudioWindowBlackman256[];
  26. extern const int16_t AudioWindowFlattop256[];
  27. extern const int16_t AudioWindowBlackmanHarris256[];
  28. extern const int16_t AudioWindowNuttall256[];
  29. extern const int16_t AudioWindowBlackmanNuttall256[];
  30. extern const int16_t AudioWindowWelch256[];
  31. extern const int16_t AudioWindowHamming256[];
  32. extern const int16_t AudioWindowCosine256[];
  33. extern const int16_t AudioWindowTukey256[];
  34. }
  35. class AudioAnalyzeFFT256 : public AudioStream
  36. {
  37. public:
  38. AudioAnalyzeFFT256(uint8_t navg = 8, const int16_t *win = AudioWindowHanning256)
  39. : AudioStream(1, inputQueueArray), outputflag(false),
  40. prevblock(NULL), count(0), naverage(navg), window(win) { init(); }
  41. bool available() {
  42. if (outputflag == true) {
  43. outputflag = false;
  44. return true;
  45. }
  46. return false;
  47. }
  48. virtual void update(void);
  49. //uint32_t cycles;
  50. int32_t output[128] __attribute__ ((aligned (4)));
  51. private:
  52. void init(void);
  53. const int16_t *window;
  54. audio_block_t *prevblock;
  55. int16_t buffer[512] __attribute__ ((aligned (4)));
  56. uint8_t count;
  57. uint8_t naverage;
  58. bool outputflag;
  59. audio_block_t *inputQueueArray[1];
  60. };
  61. class AudioSynthWaveform : public AudioStream
  62. {
  63. public:
  64. AudioSynthWaveform(const int16_t *waveform)
  65. : AudioStream(0, NULL), wavetable(waveform), magnitude(0), phase(0) { }
  66. void frequency(float freq) {
  67. if (freq > AUDIO_SAMPLE_RATE_EXACT / 2 || freq < 0.0) return;
  68. phase_increment = (freq / AUDIO_SAMPLE_RATE_EXACT) * 4294967296.0f;
  69. }
  70. void amplitude(float n) { // 0 to 1.0
  71. if (n < 0) n = 0;
  72. else if (n > 1.0) n = 1.0;
  73. magnitude = n * 32767.0;
  74. }
  75. virtual void update(void);
  76. private:
  77. const int16_t *wavetable;
  78. uint16_t magnitude;
  79. uint32_t phase;
  80. uint32_t phase_increment;
  81. };
  82. #if 0
  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. #endif
  97. class AudioOutputPWM : public AudioStream
  98. {
  99. public:
  100. AudioOutputPWM(void) : AudioStream(1, inputQueueArray) { begin(); }
  101. virtual void update(void);
  102. void begin(void);
  103. friend void dma_ch3_isr(void);
  104. private:
  105. static audio_block_t *block_1st;
  106. static audio_block_t *block_2nd;
  107. static uint32_t block_offset;
  108. static bool update_responsibility;
  109. static uint8_t interrupt_count;
  110. audio_block_t *inputQueueArray[1];
  111. };
  112. class AudioOutputAnalog : public AudioStream
  113. {
  114. public:
  115. AudioOutputAnalog(void) : AudioStream(1, inputQueueArray) { begin(); }
  116. virtual void update(void);
  117. void begin(void);
  118. void analogReference(int ref);
  119. friend void dma_ch4_isr(void);
  120. private:
  121. static audio_block_t *block_left_1st;
  122. static audio_block_t *block_left_2nd;
  123. static bool update_responsibility;
  124. audio_block_t *inputQueueArray[1];
  125. };
  126. class AudioPrint : public AudioStream
  127. {
  128. public:
  129. AudioPrint(const char *str) : AudioStream(1, inputQueueArray), name(str) {}
  130. virtual void update(void);
  131. private:
  132. const char *name;
  133. audio_block_t *inputQueueArray[1];
  134. };
  135. class AudioInputI2S : public AudioStream
  136. {
  137. public:
  138. AudioInputI2S(void) : AudioStream(0, NULL) { begin(); }
  139. virtual void update(void);
  140. void begin(void);
  141. friend void dma_ch1_isr(void);
  142. private:
  143. static audio_block_t *block_left;
  144. static audio_block_t *block_right;
  145. static uint16_t block_offset;
  146. static bool update_responsibility; // TODO: implement and test this.
  147. };
  148. class AudioOutputI2S : public AudioStream
  149. {
  150. public:
  151. AudioOutputI2S(void) : AudioStream(2, inputQueueArray) { begin(); }
  152. virtual void update(void);
  153. void begin(void);
  154. friend void dma_ch0_isr(void);
  155. friend class AudioInputI2S;
  156. private:
  157. static void config_i2s(void);
  158. static audio_block_t *block_left_1st;
  159. static audio_block_t *block_right_1st;
  160. static audio_block_t *block_left_2nd;
  161. static audio_block_t *block_right_2nd;
  162. static uint16_t block_left_offset;
  163. static uint16_t block_right_offset;
  164. static bool update_responsibility;
  165. audio_block_t *inputQueueArray[2];
  166. };
  167. class AudioInputAnalog : public AudioStream
  168. {
  169. public:
  170. AudioInputAnalog(unsigned int pin) : AudioStream(0, NULL) { begin(pin); }
  171. virtual void update(void);
  172. void begin(unsigned int pin);
  173. friend void dma_ch2_isr(void);
  174. private:
  175. static audio_block_t *block_left;
  176. static uint16_t block_offset;
  177. uint16_t dc_average;
  178. //static bool update_responsibility; // TODO: implement and test this.
  179. };
  180. #include "SD.h"
  181. class AudioPlaySDcardWAV : public AudioStream
  182. {
  183. public:
  184. AudioPlaySDcardWAV(void) : AudioStream(0, NULL) { begin(); }
  185. void begin(void);
  186. bool play(const char *filename);
  187. void stop(void);
  188. bool start(void);
  189. virtual void update(void);
  190. private:
  191. File wavfile;
  192. bool consume(void);
  193. bool parse_format(void);
  194. uint32_t header[5];
  195. uint32_t data_length; // number of bytes remaining in data section
  196. audio_block_t *block_left;
  197. audio_block_t *block_right;
  198. uint16_t block_offset;
  199. uint8_t buffer[512];
  200. uint16_t buffer_remaining;
  201. uint8_t state;
  202. uint8_t state_play;
  203. uint8_t leftover_bytes;
  204. };
  205. class AudioPlaySDcardRAW : public AudioStream
  206. {
  207. public:
  208. AudioPlaySDcardRAW(void) : AudioStream(0, NULL) { begin(); }
  209. void begin(void);
  210. bool play(const char *filename);
  211. void stop(void);
  212. virtual void update(void);
  213. private:
  214. File rawfile;
  215. audio_block_t *block;
  216. bool playing;
  217. bool paused;
  218. };
  219. class AudioPlayMemory : public AudioStream
  220. {
  221. public:
  222. AudioPlayMemory(void) : AudioStream(0, NULL), playing(0) { }
  223. void play(const unsigned int *data);
  224. void stop(void);
  225. virtual void update(void);
  226. private:
  227. const unsigned int *next;
  228. uint32_t length;
  229. int16_t prior;
  230. volatile uint8_t playing;
  231. };
  232. class AudioMixer4 : public AudioStream
  233. {
  234. public:
  235. AudioMixer4(void) : AudioStream(4, inputQueueArray) {
  236. for (int i=0; i<4; i++) multiplier[i] = 65536;
  237. }
  238. virtual void update(void);
  239. void gain(unsigned int channel, float gain) {
  240. if (channel >= 4) return;
  241. if (gain > 32767.0f) gain = 32767.0f;
  242. else if (gain < 0.0f) gain = 0.0f;
  243. multiplier[channel] = gain * 65536.0f; // TODO: proper roundoff?
  244. }
  245. private:
  246. int32_t multiplier[4];
  247. audio_block_t *inputQueueArray[4];
  248. };
  249. class AudioFilterBiquad : public AudioStream
  250. {
  251. public:
  252. AudioFilterBiquad(int *parameters)
  253. : AudioStream(1, inputQueueArray), definition(parameters) { }
  254. virtual void update(void);
  255. private:
  256. int *definition;
  257. audio_block_t *inputQueueArray[1];
  258. };
  259. // TODO: more audio processing objects....
  260. // N-channel mixer, adjustable gain on each channel
  261. // sine wave with frequency modulation (phase)
  262. // non-sine oscillators, ramp, triangle, square/pulse, etc
  263. // envelope: attack-decay-sustain-release, maybe other more complex?
  264. // filters, low pass, high pass, bandpass, notch
  265. // frequency analysis - FFT, single frequency (eg, filter for DTMF)
  266. // MP3 decoding - it is possible with optimized code?
  267. // other decompression, ADPCM, Vorbis, Speex, etc?
  268. // A base class for all Codecs, DACs and ADCs, so at least the
  269. // most basic functionality is consistent.
  270. #define AUDIO_INPUT_LINEIN 0
  271. #define AUDIO_INPUT_MIC 1
  272. class AudioControl
  273. {
  274. public:
  275. virtual bool enable(void) = 0;
  276. virtual bool disable(void) = 0;
  277. virtual bool volume(float volume) = 0; // volume 0.0 to 100.0
  278. virtual bool inputLevel(float volume) = 0; // volume 0.0 to 100.0
  279. virtual bool inputSelect(int n) = 0;
  280. };
  281. class AudioControlWM8731 : public AudioControl
  282. {
  283. public:
  284. bool enable(void);
  285. bool volume(float n) { return volumeInteger(n * 0.8 + 47.499); }
  286. bool inputLevel(float n) { return false; }
  287. bool inputSelect(int n) { return false; }
  288. protected:
  289. bool write(unsigned int reg, unsigned int val);
  290. bool volumeInteger(unsigned int n); // range: 0x2F to 0x7F
  291. };
  292. class AudioControlSGTL5000 : public AudioControl
  293. {
  294. public:
  295. bool enable(void);
  296. bool disable(void) { return false; }
  297. bool volume(float n) { return volumeInteger(n * 1.29 + 0.499); }
  298. bool inputLevel(float n) {return false;}
  299. bool muteHeadphone(void) { return write(0x0024, ana_ctrl | (1<<4)); }
  300. bool unmuteHeadphone(void) { return write(0x0024, ana_ctrl & ~(1<<4)); }
  301. bool muteLineout(void) { return write(0x0024, ana_ctrl | (1<<8)); }
  302. bool unmuteLineout(void) { return write(0x0024, ana_ctrl & ~(1<<8)); }
  303. bool inputSelect(int n) {
  304. if (n == AUDIO_INPUT_LINEIN) {
  305. return write(0x0024, ana_ctrl | (1<<2));
  306. } else if (n == AUDIO_INPUT_MIC) {
  307. //return write(0x002A, 0x0172) && write(0x0024, ana_ctrl & ~(1<<2));
  308. return write(0x002A, 0x0173) && write(0x0024, ana_ctrl & ~(1<<2)); // +40dB
  309. } else {
  310. return false;
  311. }
  312. }
  313. //bool inputLinein(void) { return write(0x0024, ana_ctrl | (1<<2)); }
  314. //bool inputMic(void) { return write(0x002A, 0x0172) && write(0x0024, ana_ctrl & ~(1<<2)); }
  315. protected:
  316. bool muted;
  317. bool volumeInteger(unsigned int n); // range: 0x00 to 0x80
  318. uint16_t ana_ctrl;
  319. unsigned int read(unsigned int reg);
  320. bool write(unsigned int reg, unsigned int val);
  321. };