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.

428 lines
8.9KB

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