PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
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.

253 lines
6.5KB

  1. /* Audio Library for Teensy 3.X
  2. * Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com
  3. *
  4. * Development of this audio library was funded by PJRC.COM, LLC by sales of
  5. * Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop
  6. * open source software by purchasing Teensy or other PJRC products.
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining a copy
  9. * of this software and associated documentation files (the "Software"), to deal
  10. * in the Software without restriction, including without limitation the rights
  11. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. * copies of the Software, and to permit persons to whom the Software is
  13. * furnished to do so, subject to the following conditions:
  14. *
  15. * The above copyright notice, development funding notice, and this permission
  16. * notice shall be included in all copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24. * THE SOFTWARE.
  25. */
  26. #include <Arduino.h>
  27. #include "play_memory.h"
  28. #include "utility/dspinst.h"
  29. void AudioPlayMemory::play(const unsigned int *data)
  30. {
  31. uint32_t format;
  32. playing = 0;
  33. prior = 0;
  34. format = *data++;
  35. next = data;
  36. beginning = data;
  37. length = format & 0xFFFFFF;
  38. playing = format >> 24;
  39. }
  40. void AudioPlayMemory::stop(void)
  41. {
  42. playing = 0;
  43. }
  44. extern "C" {
  45. extern const int16_t ulaw_decode_table[256];
  46. };
  47. void AudioPlayMemory::update(void)
  48. {
  49. audio_block_t *block;
  50. const unsigned int *in;
  51. int16_t *out;
  52. uint32_t tmp32, consumed;
  53. int16_t s0, s1, s2, s3, s4;
  54. int i;
  55. if (!playing) return;
  56. block = allocate();
  57. if (block == NULL) return;
  58. //Serial.write('.');
  59. out = block->data;
  60. in = next;
  61. s0 = prior;
  62. switch (playing) {
  63. case 0x01: // u-law encoded, 44100 Hz
  64. for (i=0; i < AUDIO_BLOCK_SAMPLES; i += 4) {
  65. tmp32 = *in++;
  66. *out++ = ulaw_decode_table[(tmp32 >> 0) & 255];
  67. *out++ = ulaw_decode_table[(tmp32 >> 8) & 255];
  68. *out++ = ulaw_decode_table[(tmp32 >> 16) & 255];
  69. *out++ = ulaw_decode_table[(tmp32 >> 24) & 255];
  70. }
  71. consumed = AUDIO_BLOCK_SAMPLES;
  72. break;
  73. case 0x81: // 16 bit PCM, 44100 Hz
  74. for (i=0; i < AUDIO_BLOCK_SAMPLES; i += 2) {
  75. tmp32 = *in++;
  76. *out++ = (int16_t)(tmp32 & 65535);
  77. *out++ = (int16_t)(tmp32 >> 16);
  78. }
  79. consumed = AUDIO_BLOCK_SAMPLES;
  80. break;
  81. case 0x02: // u-law encoded, 22050 Hz
  82. for (i=0; i < AUDIO_BLOCK_SAMPLES; i += 8) {
  83. tmp32 = *in++;
  84. s1 = ulaw_decode_table[(tmp32 >> 0) & 255];
  85. s2 = ulaw_decode_table[(tmp32 >> 8) & 255];
  86. s3 = ulaw_decode_table[(tmp32 >> 16) & 255];
  87. s4 = ulaw_decode_table[(tmp32 >> 24) & 255];
  88. *out++ = (s0 + s1) >> 1;
  89. *out++ = s1;
  90. *out++ = (s1 + s2) >> 1;
  91. *out++ = s2;
  92. *out++ = (s2 + s3) >> 1;
  93. *out++ = s3;
  94. *out++ = (s3 + s4) >> 1;
  95. *out++ = s4;
  96. s0 = s4;
  97. }
  98. consumed = AUDIO_BLOCK_SAMPLES/2;
  99. break;
  100. case 0x82: // 16 bits PCM, 22050 Hz
  101. for (i=0; i < AUDIO_BLOCK_SAMPLES; i += 4) {
  102. tmp32 = *in++;
  103. s1 = (int16_t)(tmp32 & 65535);
  104. s2 = (int16_t)(tmp32 >> 16);
  105. *out++ = (s0 + s1) >> 1;
  106. *out++ = s1;
  107. *out++ = (s1 + s2) >> 1;
  108. *out++ = s2;
  109. s0 = s2;
  110. }
  111. consumed = AUDIO_BLOCK_SAMPLES/2;
  112. break;
  113. case 0x03: // u-law encoded, 11025 Hz
  114. for (i=0; i < AUDIO_BLOCK_SAMPLES; i += 16) {
  115. tmp32 = *in++;
  116. s1 = ulaw_decode_table[(tmp32 >> 0) & 255];
  117. s2 = ulaw_decode_table[(tmp32 >> 8) & 255];
  118. s3 = ulaw_decode_table[(tmp32 >> 16) & 255];
  119. s4 = ulaw_decode_table[(tmp32 >> 24) & 255];
  120. *out++ = (s0 * 3 + s1) >> 2;
  121. *out++ = (s0 + s1) >> 1;
  122. *out++ = (s0 + s1 * 3) >> 2;
  123. *out++ = s1;
  124. *out++ = (s1 * 3 + s2) >> 2;
  125. *out++ = (s1 + s2) >> 1;
  126. *out++ = (s1 + s2 * 3) >> 2;
  127. *out++ = s2;
  128. *out++ = (s2 * 3 + s3) >> 2;
  129. *out++ = (s2 + s3) >> 1;
  130. *out++ = (s2 + s3 * 3) >> 2;
  131. *out++ = s3;
  132. *out++ = (s3 * 3 + s4) >> 2;
  133. *out++ = (s3 + s4) >> 1;
  134. *out++ = (s3 + s4 * 3) >> 2;
  135. *out++ = s4;
  136. s0 = s4;
  137. }
  138. consumed = AUDIO_BLOCK_SAMPLES/4;
  139. break;
  140. case 0x83: // 16 bit PCM, 11025 Hz
  141. for (i=0; i < AUDIO_BLOCK_SAMPLES; i += 8) {
  142. tmp32 = *in++;
  143. s1 = (int16_t)(tmp32 & 65535);
  144. s2 = (int16_t)(tmp32 >> 16);
  145. *out++ = (s0 * 3 + s1) >> 2;
  146. *out++ = (s0 + s1) >> 1;
  147. *out++ = (s0 + s1 * 3) >> 2;
  148. *out++ = s1;
  149. *out++ = (s1 * 3 + s2) >> 2;
  150. *out++ = (s1 + s2) >> 1;
  151. *out++ = (s1 + s2 * 3) >> 2;
  152. *out++ = s2;
  153. s0 = s2;
  154. }
  155. consumed = AUDIO_BLOCK_SAMPLES/4;
  156. break;
  157. default:
  158. release(block);
  159. playing = 0;
  160. return;
  161. }
  162. prior = s0;
  163. next = in;
  164. if (length > consumed) {
  165. length -= consumed;
  166. } else {
  167. playing = 0;
  168. }
  169. transmit(block);
  170. release(block);
  171. }
  172. #define B2M_88200 (uint32_t)((double)4294967296000.0 / AUDIO_SAMPLE_RATE_EXACT / 2.0)
  173. #define B2M_44100 (uint32_t)((double)4294967296000.0 / AUDIO_SAMPLE_RATE_EXACT) // 97352592
  174. #define B2M_22050 (uint32_t)((double)4294967296000.0 / AUDIO_SAMPLE_RATE_EXACT * 2.0)
  175. #define B2M_11025 (uint32_t)((double)4294967296000.0 / AUDIO_SAMPLE_RATE_EXACT * 4.0)
  176. uint32_t AudioPlayMemory::positionMillis(void)
  177. {
  178. uint8_t p;
  179. const uint8_t *n, *b;
  180. uint32_t b2m;
  181. __disable_irq();
  182. p = playing;
  183. n = (const uint8_t *)next;
  184. b = (const uint8_t *)beginning;
  185. __enable_irq();
  186. switch (p) {
  187. case 0x81: // 16 bit PCM, 44100 Hz
  188. b2m = B2M_88200; break;
  189. case 0x01: // u-law encoded, 44100 Hz
  190. case 0x82: // 16 bits PCM, 22050 Hz
  191. b2m = B2M_44100; break;
  192. case 0x02: // u-law encoded, 22050 Hz
  193. case 0x83: // 16 bit PCM, 11025 Hz
  194. b2m = B2M_22050; break;
  195. case 0x03: // u-law encoded, 11025 Hz
  196. b2m = B2M_11025; break;
  197. default:
  198. return 0;
  199. }
  200. if (p == 0) return 0;
  201. return ((uint64_t)(n - b) * b2m) >> 32;
  202. }
  203. uint32_t AudioPlayMemory::lengthMillis(void)
  204. {
  205. uint8_t p;
  206. const uint32_t *b;
  207. uint32_t b2m;
  208. __disable_irq();
  209. p = playing;
  210. b = (const uint32_t *)beginning;
  211. __enable_irq();
  212. switch (p) {
  213. case 0x81: // 16 bit PCM, 44100 Hz
  214. case 0x01: // u-law encoded, 44100 Hz
  215. b2m = B2M_44100; break;
  216. case 0x82: // 16 bits PCM, 22050 Hz
  217. case 0x02: // u-law encoded, 22050 Hz
  218. b2m = B2M_22050; break;
  219. case 0x83: // 16 bit PCM, 11025 Hz
  220. case 0x03: // u-law encoded, 11025 Hz
  221. b2m = B2M_11025; break;
  222. default:
  223. return 0;
  224. }
  225. return ((uint64_t)(*(b - 1) & 0xFFFFFF) * b2m) >> 32;
  226. }