Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

586 lines
14KB

  1. #include "AudioStream.h"
  2. #include "arm_math.h"
  3. // When changing multiple audio object settings that must update at
  4. // the same time, these functions allow the audio library interrupt
  5. // to be disabled. For example, you may wish to begin playing a note
  6. // in response to reading an analog sensor. If you have "velocity"
  7. // information, you might start the sample playing and also adjust
  8. // the gain of a mixer channel. Use AudioNoInterrupts() first, then
  9. // make both changes to the 2 separate objects. Then allow the audio
  10. // library to update with AudioInterrupts(). Both changes will happen
  11. // at the same time, because AudioNoInterrupts() prevents any updates
  12. // while you make changes.
  13. #define AudioNoInterrupts() (NVIC_DISABLE_IRQ(IRQ_SOFTWARE))
  14. #define AudioInterrupts() (NVIC_ENABLE_IRQ(IRQ_SOFTWARE))
  15. // waveforms.c
  16. extern "C" {
  17. extern const int16_t AudioWaveformSine[257];
  18. extern const int16_t AudioWaveformTriangle[257];
  19. extern const int16_t AudioWaveformSquare[257];
  20. extern const int16_t AudioWaveformSawtooth[257];
  21. }
  22. // windows.c
  23. extern "C" {
  24. extern const int16_t AudioWindowHanning256[];
  25. extern const int16_t AudioWindowBartlett256[];
  26. extern const int16_t AudioWindowBlackman256[];
  27. extern const int16_t AudioWindowFlattop256[];
  28. extern const int16_t AudioWindowBlackmanHarris256[];
  29. extern const int16_t AudioWindowNuttall256[];
  30. extern const int16_t AudioWindowBlackmanNuttall256[];
  31. extern const int16_t AudioWindowWelch256[];
  32. extern const int16_t AudioWindowHamming256[];
  33. extern const int16_t AudioWindowCosine256[];
  34. extern const int16_t AudioWindowTukey256[];
  35. }
  36. class AudioAnalyzeFFT256 : public AudioStream
  37. {
  38. public:
  39. AudioAnalyzeFFT256(uint8_t navg = 8, const int16_t *win = AudioWindowHanning256)
  40. : AudioStream(1, inputQueueArray), outputflag(false),
  41. prevblock(NULL), count(0), naverage(navg), window(win) { init(); }
  42. bool available() {
  43. if (outputflag == true) {
  44. outputflag = false;
  45. return true;
  46. }
  47. return false;
  48. }
  49. virtual void update(void);
  50. //uint32_t cycles;
  51. int32_t output[128] __attribute__ ((aligned (4)));
  52. private:
  53. void init(void);
  54. const int16_t *window;
  55. audio_block_t *prevblock;
  56. int16_t buffer[512] __attribute__ ((aligned (4)));
  57. uint8_t count;
  58. uint8_t naverage;
  59. bool outputflag;
  60. audio_block_t *inputQueueArray[1];
  61. };
  62. class AudioSynthWaveform : public AudioStream
  63. {
  64. public:
  65. AudioSynthWaveform(const int16_t *waveform)
  66. : AudioStream(0, NULL), wavetable(waveform), magnitude(0), phase(0) { }
  67. void frequency(float freq) {
  68. if (freq > AUDIO_SAMPLE_RATE_EXACT / 2 || freq < 0.0) return;
  69. phase_increment = (freq / AUDIO_SAMPLE_RATE_EXACT) * 4294967296.0f;
  70. }
  71. void amplitude(float n) { // 0 to 1.0
  72. if (n < 0) n = 0;
  73. else if (n > 1.0) n = 1.0;
  74. magnitude = n * 32767.0;
  75. }
  76. virtual void update(void);
  77. private:
  78. const int16_t *wavetable;
  79. uint16_t magnitude;
  80. uint32_t phase;
  81. uint32_t phase_increment;
  82. };
  83. #if 0
  84. class AudioSineWaveMod : public AudioStream
  85. {
  86. public:
  87. AudioSineWaveMod() : AudioStream(1, inputQueueArray) {}
  88. void frequency(float freq);
  89. //void amplitude(q15 n);
  90. virtual void update(void);
  91. private:
  92. uint32_t phase;
  93. uint32_t phase_increment;
  94. uint32_t modulation_factor;
  95. audio_block_t *inputQueueArray[1];
  96. };
  97. #endif
  98. class AudioOutputPWM : public AudioStream
  99. {
  100. public:
  101. AudioOutputPWM(void) : AudioStream(1, inputQueueArray) { begin(); }
  102. virtual void update(void);
  103. void begin(void);
  104. friend void dma_ch3_isr(void);
  105. private:
  106. static audio_block_t *block_1st;
  107. static audio_block_t *block_2nd;
  108. static uint32_t block_offset;
  109. static bool update_responsibility;
  110. static uint8_t interrupt_count;
  111. audio_block_t *inputQueueArray[1];
  112. };
  113. class AudioOutputAnalog : public AudioStream
  114. {
  115. public:
  116. AudioOutputAnalog(void) : AudioStream(1, inputQueueArray) { begin(); }
  117. virtual void update(void);
  118. void begin(void);
  119. void analogReference(int ref);
  120. friend void dma_ch4_isr(void);
  121. private:
  122. static audio_block_t *block_left_1st;
  123. static audio_block_t *block_left_2nd;
  124. static bool update_responsibility;
  125. audio_block_t *inputQueueArray[1];
  126. };
  127. class AudioPrint : public AudioStream
  128. {
  129. public:
  130. AudioPrint(const char *str) : AudioStream(1, inputQueueArray), name(str) {}
  131. virtual void update(void);
  132. private:
  133. const char *name;
  134. audio_block_t *inputQueueArray[1];
  135. };
  136. class AudioInputI2S : public AudioStream
  137. {
  138. public:
  139. AudioInputI2S(void) : AudioStream(0, NULL) { begin(); }
  140. virtual void update(void);
  141. void begin(void);
  142. friend void dma_ch1_isr(void);
  143. protected:
  144. AudioInputI2S(int dummy): AudioStream(0, NULL) {} // to be used only inside AudioInputI2Sslave !!
  145. static bool update_responsibility;
  146. private:
  147. static audio_block_t *block_left;
  148. static audio_block_t *block_right;
  149. static uint16_t block_offset;
  150. };
  151. class AudioOutputI2S : public AudioStream
  152. {
  153. public:
  154. AudioOutputI2S(void) : AudioStream(2, inputQueueArray) { begin(); }
  155. virtual void update(void);
  156. void begin(void);
  157. friend void dma_ch0_isr(void);
  158. friend class AudioInputI2S;
  159. protected:
  160. AudioOutputI2S(int dummy): AudioStream(2, inputQueueArray) {} // to be used only inside AudioOutputI2Sslave !!
  161. static void config_i2s(void);
  162. static audio_block_t *block_left_1st;
  163. static audio_block_t *block_right_1st;
  164. static bool update_responsibility;
  165. private:
  166. static audio_block_t *block_left_2nd;
  167. static audio_block_t *block_right_2nd;
  168. static uint16_t block_left_offset;
  169. static uint16_t block_right_offset;
  170. audio_block_t *inputQueueArray[2];
  171. };
  172. class AudioInputI2Sslave : public AudioInputI2S
  173. {
  174. public:
  175. AudioInputI2Sslave(void) : AudioInputI2S(0) { begin(); }
  176. void begin(void);
  177. friend void dma_ch1_isr(void);
  178. };
  179. class AudioOutputI2Sslave : public AudioOutputI2S
  180. {
  181. public:
  182. AudioOutputI2Sslave(void) : AudioOutputI2S(0) { begin(); } ;
  183. void begin(void);
  184. friend class AudioInputI2Sslave;
  185. friend void dma_ch0_isr(void);
  186. protected:
  187. static void config_i2s(void);
  188. };
  189. class AudioInputAnalog : public AudioStream
  190. {
  191. public:
  192. AudioInputAnalog(unsigned int pin) : AudioStream(0, NULL) { begin(pin); }
  193. virtual void update(void);
  194. void begin(unsigned int pin);
  195. friend void dma_ch2_isr(void);
  196. private:
  197. static audio_block_t *block_left;
  198. static uint16_t block_offset;
  199. uint16_t dc_average;
  200. static bool update_responsibility;
  201. };
  202. #include "SD.h"
  203. class AudioPlaySDcardWAV : public AudioStream
  204. {
  205. public:
  206. AudioPlaySDcardWAV(void) : AudioStream(0, NULL) { begin(); }
  207. void begin(void);
  208. bool play(const char *filename);
  209. void stop(void);
  210. bool start(void);
  211. virtual void update(void);
  212. private:
  213. File wavfile;
  214. bool consume(void);
  215. bool parse_format(void);
  216. uint32_t header[5];
  217. uint32_t data_length; // number of bytes remaining in data section
  218. audio_block_t *block_left;
  219. audio_block_t *block_right;
  220. uint16_t block_offset;
  221. uint8_t buffer[512];
  222. uint16_t buffer_remaining;
  223. uint8_t state;
  224. uint8_t state_play;
  225. uint8_t leftover_bytes;
  226. };
  227. class AudioPlaySDcardRAW : public AudioStream
  228. {
  229. public:
  230. AudioPlaySDcardRAW(void) : AudioStream(0, NULL) { begin(); }
  231. void begin(void);
  232. bool play(const char *filename);
  233. void stop(void);
  234. virtual void update(void);
  235. private:
  236. File rawfile;
  237. audio_block_t *block;
  238. bool playing;
  239. bool paused;
  240. };
  241. class AudioPlayMemory : public AudioStream
  242. {
  243. public:
  244. AudioPlayMemory(void) : AudioStream(0, NULL), playing(0) { }
  245. void play(const unsigned int *data);
  246. void stop(void);
  247. virtual void update(void);
  248. private:
  249. const unsigned int *next;
  250. uint32_t length;
  251. int16_t prior;
  252. volatile uint8_t playing;
  253. };
  254. class AudioMixer4 : public AudioStream
  255. {
  256. public:
  257. AudioMixer4(void) : AudioStream(4, inputQueueArray) {
  258. for (int i=0; i<4; i++) multiplier[i] = 65536;
  259. }
  260. virtual void update(void);
  261. void gain(unsigned int channel, float gain) {
  262. if (channel >= 4) return;
  263. if (gain > 32767.0f) gain = 32767.0f;
  264. else if (gain < 0.0f) gain = 0.0f;
  265. multiplier[channel] = gain * 65536.0f; // TODO: proper roundoff?
  266. }
  267. private:
  268. int32_t multiplier[4];
  269. audio_block_t *inputQueueArray[4];
  270. };
  271. class AudioFilterBiquad : public AudioStream
  272. {
  273. public:
  274. AudioFilterBiquad(int *parameters)
  275. : AudioStream(1, inputQueueArray), definition(parameters) { }
  276. virtual void update(void);
  277. private:
  278. int *definition;
  279. audio_block_t *inputQueueArray[1];
  280. };
  281. class AudioEffectFade : public AudioStream
  282. {
  283. public:
  284. AudioEffectFade(void)
  285. : AudioStream(1, inputQueueArray), position(0xFFFFFFFF) {}
  286. void fadeIn(uint32_t milliseconds) {
  287. uint32_t samples = (uint32_t)(milliseconds * 441u + 5u) / 10u;
  288. //Serial.printf("fadeIn, %u samples\n", samples);
  289. fadeBegin(0xFFFFFFFFu / samples, 1);
  290. }
  291. void fadeOut(uint32_t milliseconds) {
  292. uint32_t samples = (uint32_t)(milliseconds * 441u + 5u) / 10u;
  293. //Serial.printf("fadeOut, %u samples\n", samples);
  294. fadeBegin(0xFFFFFFFFu / samples, 0);
  295. }
  296. virtual void update(void);
  297. private:
  298. void fadeBegin(uint32_t newrate, uint8_t dir);
  299. uint32_t position; // 0 = off, 0xFFFFFFFF = on
  300. uint32_t rate;
  301. uint8_t direction; // 0 = fading out, 1 = fading in
  302. audio_block_t *inputQueueArray[1];
  303. };
  304. class AudioAnalyzeToneDetect : public AudioStream
  305. {
  306. public:
  307. AudioAnalyzeToneDetect(void)
  308. : AudioStream(1, inputQueueArray), thresh(6554), enabled(false) { }
  309. void frequency(float freq, uint16_t cycles=10) {
  310. set_params((int32_t)(cos((double)freq
  311. * (2.0 * 3.14159265358979323846 / AUDIO_SAMPLE_RATE_EXACT))
  312. * (double)2147483647.999), cycles,
  313. (float)AUDIO_SAMPLE_RATE_EXACT / freq * (float)cycles + 0.5f);
  314. }
  315. void set_params(int32_t coef, uint16_t cycles, uint16_t len);
  316. bool available(void) {
  317. __disable_irq();
  318. bool flag = new_output;
  319. if (flag) new_output = false;
  320. __enable_irq();
  321. return flag;
  322. }
  323. float read(void);
  324. void threshold(float level) {
  325. if (level < 0.01f) thresh = 655;
  326. else if (level > 0.99f) thresh = 64881;
  327. else thresh = level * 65536.0f + 0.5f;
  328. }
  329. operator bool(); // true if at or above threshold, false if below
  330. virtual void update(void);
  331. private:
  332. int32_t coefficient; // Goertzel algorithm coefficient
  333. int32_t s1, s2; // Goertzel algorithm state
  334. int32_t out1, out2; // Goertzel algorithm state output
  335. uint16_t length; // number of samples to analyze
  336. uint16_t count; // how many left to analyze
  337. uint16_t ncycles; // number of waveform cycles to seek
  338. uint16_t thresh; // threshold, 655 to 64881 (1% to 99%)
  339. bool enabled;
  340. volatile bool new_output;
  341. audio_block_t *inputQueueArray[1];
  342. };
  343. // TODO: more audio processing objects....
  344. // sine wave with frequency modulation (phase)
  345. // waveforms with bandwidth limited tables for synth
  346. // envelope: attack-decay-sustain-release, maybe other more complex?
  347. // MP3 decoding - it is possible with optimized code?
  348. // other decompression, ADPCM, Vorbis, Speex, etc?
  349. // A base class for all Codecs, DACs and ADCs, so at least the
  350. // most basic functionality is consistent.
  351. #define AUDIO_INPUT_LINEIN 0
  352. #define AUDIO_INPUT_MIC 1
  353. class AudioControl
  354. {
  355. public:
  356. virtual bool enable(void) = 0;
  357. virtual bool disable(void) = 0;
  358. virtual bool volume(float volume) = 0; // volume 0.0 to 100.0
  359. virtual bool inputLevel(float volume) = 0; // volume 0.0 to 100.0
  360. virtual bool inputSelect(int n) = 0;
  361. };
  362. class AudioControlWM8731 : public AudioControl
  363. {
  364. public:
  365. bool enable(void);
  366. bool disable(void) { return false; }
  367. bool volume(float n) { return volumeInteger(n * 0.8 + 47.499); }
  368. bool inputLevel(float n) { return false; }
  369. bool inputSelect(int n) { return false; }
  370. protected:
  371. bool write(unsigned int reg, unsigned int val);
  372. bool volumeInteger(unsigned int n); // range: 0x2F to 0x7F
  373. };
  374. class AudioControlWM8731master : public AudioControlWM8731
  375. {
  376. public:
  377. bool enable(void);
  378. };
  379. class AudioControlSGTL5000 : public AudioControl
  380. {
  381. public:
  382. bool enable(void);
  383. bool disable(void) { return false; }
  384. bool volume(float n) { return volumeInteger(n * 1.29 + 0.499); }
  385. bool inputLevel(float n) {return false;}
  386. bool muteHeadphone(void) { return write(0x0024, ana_ctrl | (1<<4)); }
  387. bool unmuteHeadphone(void) { return write(0x0024, ana_ctrl & ~(1<<4)); }
  388. bool muteLineout(void) { return write(0x0024, ana_ctrl | (1<<8)); }
  389. bool unmuteLineout(void) { return write(0x0024, ana_ctrl & ~(1<<8)); }
  390. bool inputSelect(int n) {
  391. if (n == AUDIO_INPUT_LINEIN) {
  392. return write(0x0024, ana_ctrl | (1<<2));
  393. } else if (n == AUDIO_INPUT_MIC) {
  394. //return write(0x002A, 0x0172) && write(0x0024, ana_ctrl & ~(1<<2));
  395. return write(0x002A, 0x0173) && write(0x0024, ana_ctrl & ~(1<<2)); // +40dB
  396. } else {
  397. return false;
  398. }
  399. }
  400. //bool inputLinein(void) { return write(0x0024, ana_ctrl | (1<<2)); }
  401. //bool inputMic(void) { return write(0x002A, 0x0172) && write(0x0024, ana_ctrl & ~(1<<2)); }
  402. protected:
  403. bool muted;
  404. bool volumeInteger(unsigned int n); // range: 0x00 to 0x80
  405. uint16_t ana_ctrl;
  406. unsigned int read(unsigned int reg);
  407. bool write(unsigned int reg, unsigned int val);
  408. };
  409. /******************************************************************/
  410. /******************************************************************/
  411. // Maximum number of coefficients in a FIR filter
  412. // The audio breaks up with 128 coefficients so a
  413. // maximum of 150 is more than sufficient
  414. #define MAX_COEFFS 150
  415. // Indicates that the code should just pass through the audio
  416. // without any filtering (as opposed to doing nothing at all)
  417. #define FIR_PASSTHRU ((short *) 1)
  418. class AudioFilterFIR :
  419. public AudioStream
  420. {
  421. public:
  422. AudioFilterFIR(void):
  423. AudioStream(2,inputQueueArray) {
  424. }
  425. void begin(short *coeff_p,int f_pin);
  426. virtual void update(void);
  427. void stop(void);
  428. private:
  429. audio_block_t *inputQueueArray[2];
  430. static q15_t l_StateQ15[];
  431. static q15_t r_StateQ15[];
  432. static arm_fir_instance_q15 l_fir_inst;
  433. static arm_fir_instance_q15 r_fir_inst;
  434. static short *coeff_p;
  435. };
  436. /******************************************************************/
  437. /******************************************************************/