audio.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561
  1. /* Copyright 2016-2020 Jack Humbert
  2. * Copyright 2020 JohSchneider
  3. * This program is free software: you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation, either version 2 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include "audio.h"
  17. #include "eeconfig.h"
  18. #include "timer.h"
  19. #include "wait.h"
  20. /* audio system:
  21. *
  22. * audio.[ch] takes care of all overall state, tracking the actively playing
  23. * notes/tones; the notes a SONG consists of;
  24. * ...
  25. * = everything audio-related that is platform agnostic
  26. *
  27. * driver_[avr|chibios]_[dac|pwm] take care of the lower hardware dependent parts,
  28. * specific to each platform and the used subsystem/driver to drive
  29. * the output pins/channels with the calculated frequencies for each
  30. * active tone
  31. * as part of this, the driver has to trigger regular state updates by
  32. * calling 'audio_update_state' through some sort of timer - be it a
  33. * dedicated one or piggybacking on for example the timer used to
  34. * generate a pwm signal/clock.
  35. *
  36. *
  37. * A Note on terminology:
  38. * tone, pitch and frequency are used somewhat interchangeably, in a strict Wikipedia-sense:
  39. * "(Musical) tone, a sound characterized by its duration, pitch (=frequency),
  40. * intensity (=volume), and timbre"
  41. * - intensity/volume is currently not handled at all, although the 'dac_additive' driver could do so
  42. * - timbre is handled globally (TODO: only used with the pwm drivers at the moment)
  43. *
  44. * in musical_note.h a 'note' is the combination of a pitch and a duration
  45. * these are used to create SONG arrays; during playback their frequencies
  46. * are handled as single successive tones, while the durations are
  47. * kept track of in 'audio_update_state'
  48. *
  49. * 'voice' as it is used here, equates to a sort of instrument with its own
  50. * characteristics sound and effects
  51. * the audio system as-is deals only with (possibly multiple) tones of one
  52. * instrument/voice at a time (think: chords). since the number of tones that
  53. * can be reproduced depends on the hardware/driver in use: pwm can only
  54. * reproduce one tone per output/speaker; DACs can reproduce/mix multiple
  55. * when doing additive synthesis.
  56. *
  57. * 'duration' can either be in the beats-per-minute related unit found in
  58. * musical_notes.h, OR in ms; keyboards create SONGs with the former, while
  59. * the internal state of the audio system does its calculations with the later - ms
  60. */
  61. #ifndef AUDIO_TONE_STACKSIZE
  62. # define AUDIO_TONE_STACKSIZE 8
  63. #endif
  64. uint8_t active_tones = 0; // number of tones pushed onto the stack by audio_play_tone - might be more than the hardware is able to reproduce at any single time
  65. musical_tone_t tones[AUDIO_TONE_STACKSIZE]; // stack of currently active tones
  66. bool playing_melody = false; // playing a SONG?
  67. bool playing_note = false; // or (possibly multiple simultaneous) tones
  68. bool state_changed = false; // global flag, which is set if anything changes with the active_tones
  69. // melody/SONG related state variables
  70. float (*notes_pointer)[][2]; // SONG, an array of MUSICAL_NOTEs
  71. uint16_t notes_count; // length of the notes_pointer array
  72. bool notes_repeat; // PLAY_SONG or PLAY_LOOP?
  73. uint16_t melody_current_note_duration = 0; // duration of the currently playing note from the active melody, in ms
  74. uint8_t note_tempo = TEMPO_DEFAULT; // beats-per-minute
  75. uint16_t current_note = 0; // index into the array at notes_pointer
  76. bool note_resting = false; // if a short pause was introduced between two notes with the same frequency while playing a melody
  77. uint16_t last_timestamp = 0;
  78. #ifdef AUDIO_ENABLE_TONE_MULTIPLEXING
  79. # ifndef AUDIO_MAX_SIMULTANEOUS_TONES
  80. # define AUDIO_MAX_SIMULTANEOUS_TONES 3
  81. # endif
  82. uint16_t tone_multiplexing_rate = AUDIO_TONE_MULTIPLEXING_RATE_DEFAULT;
  83. uint8_t tone_multiplexing_index_shift = 0; // offset used on active-tone array access
  84. #endif
  85. // provided and used by voices.c
  86. extern uint8_t note_timbre;
  87. extern bool glissando;
  88. extern bool vibrato;
  89. extern uint16_t voices_timer;
  90. #ifndef STARTUP_SONG
  91. # define STARTUP_SONG SONG(STARTUP_SOUND)
  92. #endif
  93. #ifndef AUDIO_ON_SONG
  94. # define AUDIO_ON_SONG SONG(AUDIO_ON_SOUND)
  95. #endif
  96. #ifndef AUDIO_OFF_SONG
  97. # define AUDIO_OFF_SONG SONG(AUDIO_OFF_SOUND)
  98. #endif
  99. float startup_song[][2] = STARTUP_SONG;
  100. float audio_on_song[][2] = AUDIO_ON_SONG;
  101. float audio_off_song[][2] = AUDIO_OFF_SONG;
  102. static bool audio_initialized = false;
  103. static bool audio_driver_stopped = true;
  104. audio_config_t audio_config;
  105. void audio_init() {
  106. if (audio_initialized) {
  107. return;
  108. }
  109. // Check EEPROM
  110. #ifdef EEPROM_ENABLE
  111. if (!eeconfig_is_enabled()) {
  112. eeconfig_init();
  113. }
  114. audio_config.raw = eeconfig_read_audio();
  115. #else // EEPROM settings
  116. audio_config.enable = true;
  117. # ifdef AUDIO_CLICKY_ON
  118. audio_config.clicky_enable = true;
  119. # endif
  120. #endif // EEPROM settings
  121. for (uint8_t i = 0; i < AUDIO_TONE_STACKSIZE; i++) {
  122. tones[i] = (musical_tone_t){.time_started = 0, .pitch = -1.0f, .duration = 0};
  123. }
  124. if (!audio_initialized) {
  125. audio_driver_initialize();
  126. audio_initialized = true;
  127. }
  128. stop_all_notes();
  129. #ifndef AUDIO_INIT_DELAY
  130. audio_startup();
  131. #endif
  132. }
  133. void audio_startup(void) {
  134. if (audio_config.enable) {
  135. PLAY_SONG(startup_song);
  136. }
  137. last_timestamp = timer_read();
  138. }
  139. void audio_toggle(void) {
  140. if (audio_config.enable) {
  141. stop_all_notes();
  142. }
  143. audio_config.enable ^= 1;
  144. eeconfig_update_audio(audio_config.raw);
  145. if (audio_config.enable) {
  146. audio_on_user();
  147. } else {
  148. audio_off_user();
  149. }
  150. }
  151. void audio_on(void) {
  152. audio_config.enable = 1;
  153. eeconfig_update_audio(audio_config.raw);
  154. audio_on_user();
  155. PLAY_SONG(audio_on_song);
  156. }
  157. void audio_off(void) {
  158. PLAY_SONG(audio_off_song);
  159. audio_off_user();
  160. wait_ms(100);
  161. audio_stop_all();
  162. audio_config.enable = 0;
  163. eeconfig_update_audio(audio_config.raw);
  164. }
  165. bool audio_is_on(void) {
  166. return (audio_config.enable != 0);
  167. }
  168. void audio_stop_all() {
  169. if (audio_driver_stopped) {
  170. return;
  171. }
  172. active_tones = 0;
  173. audio_driver_stop();
  174. playing_melody = false;
  175. playing_note = false;
  176. melody_current_note_duration = 0;
  177. for (uint8_t i = 0; i < AUDIO_TONE_STACKSIZE; i++) {
  178. tones[i] = (musical_tone_t){.time_started = 0, .pitch = -1.0f, .duration = 0};
  179. }
  180. audio_driver_stopped = true;
  181. }
  182. void audio_stop_tone(float pitch) {
  183. if (pitch < 0.0f) {
  184. pitch = -1 * pitch;
  185. }
  186. if (playing_note) {
  187. if (!audio_initialized) {
  188. audio_init();
  189. }
  190. bool found = false;
  191. for (int i = AUDIO_TONE_STACKSIZE - 1; i >= 0; i--) {
  192. found = (tones[i].pitch == pitch);
  193. if (found) {
  194. tones[i] = (musical_tone_t){.time_started = 0, .pitch = -1.0f, .duration = 0};
  195. for (int j = i; (j < AUDIO_TONE_STACKSIZE - 1); j++) {
  196. tones[j] = tones[j + 1];
  197. tones[j + 1] = (musical_tone_t){.time_started = 0, .pitch = -1.0f, .duration = 0};
  198. }
  199. break;
  200. }
  201. }
  202. if (!found) {
  203. return;
  204. }
  205. state_changed = true;
  206. active_tones--;
  207. if (active_tones < 0) active_tones = 0;
  208. #ifdef AUDIO_ENABLE_TONE_MULTIPLEXING
  209. if (tone_multiplexing_index_shift >= active_tones) {
  210. tone_multiplexing_index_shift = 0;
  211. }
  212. #endif
  213. if (active_tones == 0) {
  214. audio_driver_stop();
  215. audio_driver_stopped = true;
  216. playing_note = false;
  217. }
  218. }
  219. }
  220. void audio_play_note(float pitch, uint16_t duration) {
  221. if (!audio_config.enable) {
  222. return;
  223. }
  224. if (!audio_initialized) {
  225. audio_init();
  226. }
  227. if (pitch < 0.0f) {
  228. pitch = -1 * pitch;
  229. }
  230. // round-robin: shifting out old tones, keeping only unique ones
  231. // if the new frequency is already amongst the active tones, shift it to the top of the stack
  232. bool found = false;
  233. for (int i = active_tones - 1; i >= 0; i--) {
  234. found = (tones[i].pitch == pitch);
  235. if (found) {
  236. for (int j = i; (j < active_tones - 1); j++) {
  237. tones[j] = tones[j + 1];
  238. tones[j + 1] = (musical_tone_t){.time_started = timer_read(), .pitch = pitch, .duration = duration};
  239. }
  240. return; // since this frequency played already, the hardware was already started
  241. }
  242. }
  243. // frequency/tone is actually new, so we put it on the top of the stack
  244. active_tones++;
  245. if (active_tones > AUDIO_TONE_STACKSIZE) {
  246. active_tones = AUDIO_TONE_STACKSIZE;
  247. // shift out the oldest tone to make room
  248. for (int i = 0; i < active_tones - 1; i++) {
  249. tones[i] = tones[i + 1];
  250. }
  251. }
  252. state_changed = true;
  253. playing_note = true;
  254. tones[active_tones - 1] = (musical_tone_t){.time_started = timer_read(), .pitch = pitch, .duration = duration};
  255. // TODO: needs to be handled per note/tone -> use its timestamp instead?
  256. voices_timer = timer_read(); // reset to zero, for the effects added by voices.c
  257. if (audio_driver_stopped) {
  258. audio_driver_start();
  259. audio_driver_stopped = false;
  260. }
  261. }
  262. void audio_play_tone(float pitch) {
  263. audio_play_note(pitch, 0xffff);
  264. }
  265. void audio_play_melody(float (*np)[][2], uint16_t n_count, bool n_repeat) {
  266. if (!audio_config.enable) {
  267. audio_stop_all();
  268. return;
  269. }
  270. if (!audio_initialized) {
  271. audio_init();
  272. }
  273. // Cancel note if a note is playing
  274. if (playing_note) audio_stop_all();
  275. playing_melody = true;
  276. note_resting = false;
  277. notes_pointer = np;
  278. notes_count = n_count;
  279. notes_repeat = n_repeat;
  280. current_note = 0; // note in the melody-array/list at note_pointer
  281. // start first note manually, which also starts the audio_driver
  282. // all following/remaining notes are played by 'audio_update_state'
  283. audio_play_note((*notes_pointer)[current_note][0], audio_duration_to_ms((*notes_pointer)[current_note][1]));
  284. last_timestamp = timer_read();
  285. melody_current_note_duration = audio_duration_to_ms((*notes_pointer)[current_note][1]);
  286. }
  287. float click[2][2];
  288. void audio_play_click(uint16_t delay, float pitch, uint16_t duration) {
  289. uint16_t duration_tone = audio_ms_to_duration(duration);
  290. uint16_t duration_delay = audio_ms_to_duration(delay);
  291. if (delay <= 0.0f) {
  292. click[0][0] = pitch;
  293. click[0][1] = duration_tone;
  294. click[1][0] = 0.0f;
  295. click[1][1] = 0.0f;
  296. audio_play_melody(&click, 1, false);
  297. } else {
  298. // first note is a rest/pause
  299. click[0][0] = 0.0f;
  300. click[0][1] = duration_delay;
  301. // second note is the actual click
  302. click[1][0] = pitch;
  303. click[1][1] = duration_tone;
  304. audio_play_melody(&click, 2, false);
  305. }
  306. }
  307. bool audio_is_playing_note(void) {
  308. return playing_note;
  309. }
  310. bool audio_is_playing_melody(void) {
  311. return playing_melody;
  312. }
  313. uint8_t audio_get_number_of_active_tones(void) {
  314. return active_tones;
  315. }
  316. float audio_get_frequency(uint8_t tone_index) {
  317. if (tone_index >= active_tones) {
  318. return 0.0f;
  319. }
  320. return tones[active_tones - tone_index - 1].pitch;
  321. }
  322. float audio_get_processed_frequency(uint8_t tone_index) {
  323. if (tone_index >= active_tones) {
  324. return 0.0f;
  325. }
  326. int8_t index = active_tones - tone_index - 1;
  327. // new tones are stacked on top (= appended at the end), so the most recent/current is MAX-1
  328. #ifdef AUDIO_ENABLE_TONE_MULTIPLEXING
  329. index = index - tone_multiplexing_index_shift;
  330. if (index < 0) // wrap around
  331. index += active_tones;
  332. #endif
  333. if (tones[index].pitch <= 0.0f) {
  334. return 0.0f;
  335. }
  336. return voice_envelope(tones[index].pitch);
  337. }
  338. bool audio_update_state(void) {
  339. if (!playing_note && !playing_melody) {
  340. return false;
  341. }
  342. bool goto_next_note = false;
  343. uint16_t current_time = timer_read();
  344. if (playing_melody) {
  345. goto_next_note = timer_elapsed(last_timestamp) >= melody_current_note_duration;
  346. if (goto_next_note) {
  347. uint16_t delta = timer_elapsed(last_timestamp) - melody_current_note_duration;
  348. last_timestamp = current_time;
  349. uint16_t previous_note = current_note;
  350. current_note++;
  351. voices_timer = timer_read(); // reset to zero, for the effects added by voices.c
  352. if (current_note >= notes_count) {
  353. if (notes_repeat) {
  354. current_note = 0;
  355. } else {
  356. audio_stop_all();
  357. return false;
  358. }
  359. }
  360. if (!note_resting && (*notes_pointer)[previous_note][0] == (*notes_pointer)[current_note][0]) {
  361. note_resting = true;
  362. // special handling for successive notes of the same frequency:
  363. // insert a short pause to separate them audibly
  364. audio_play_note(0.0f, audio_duration_to_ms(2));
  365. current_note = previous_note;
  366. melody_current_note_duration = audio_duration_to_ms(2);
  367. } else {
  368. note_resting = false;
  369. // TODO: handle glissando here (or remember previous and current tone)
  370. /* there would need to be a freq(here we are) -> freq(next note)
  371. * and do slide/glissando in between problem here is to know which
  372. * frequency on the stack relates to what other? e.g. a melody starts
  373. * tones in a sequence, and stops expiring one, so the most recently
  374. * stopped is the starting point for a glissando to the most recently started?
  375. * how to detect and preserve this relation?
  376. * and what about user input, chords, ...?
  377. */
  378. // '- delta': Skip forward in the next note's length if we've over shot
  379. // the last, so the overall length of the song is the same
  380. uint16_t duration = audio_duration_to_ms((*notes_pointer)[current_note][1]);
  381. // Skip forward past any completely missed notes
  382. while (delta > duration && current_note < notes_count - 1) {
  383. delta -= duration;
  384. current_note++;
  385. duration = audio_duration_to_ms((*notes_pointer)[current_note][1]);
  386. }
  387. if (delta < duration) {
  388. duration -= delta;
  389. } else {
  390. // Only way to get here is if it is the last note and
  391. // we have completely missed it. Play it for 1ms...
  392. duration = 1;
  393. }
  394. audio_play_note((*notes_pointer)[current_note][0], duration);
  395. melody_current_note_duration = duration;
  396. }
  397. }
  398. }
  399. if (playing_note) {
  400. #ifdef AUDIO_ENABLE_TONE_MULTIPLEXING
  401. tone_multiplexing_index_shift = (int)(current_time / tone_multiplexing_rate) % MIN(AUDIO_MAX_SIMULTANEOUS_TONES, active_tones);
  402. goto_next_note = true;
  403. #endif
  404. if (vibrato || glissando) {
  405. // force update on each cycle, since vibrato shifts the frequency slightly
  406. goto_next_note = true;
  407. }
  408. // housekeeping: stop notes that have no playtime left
  409. for (int i = 0; i < active_tones; i++) {
  410. if ((tones[i].duration != 0xffff) // indefinitely playing notes, started by 'audio_play_tone'
  411. && (tones[i].duration != 0) // 'uninitialized'
  412. ) {
  413. if (timer_elapsed(tones[i].time_started) >= tones[i].duration) {
  414. audio_stop_tone(tones[i].pitch); // also sets 'state_changed=true'
  415. }
  416. }
  417. }
  418. }
  419. // state-changes have a higher priority, always triggering the hardware to update
  420. if (state_changed) {
  421. state_changed = false;
  422. return true;
  423. }
  424. return goto_next_note;
  425. }
  426. // Tone-multiplexing functions
  427. #ifdef AUDIO_ENABLE_TONE_MULTIPLEXING
  428. void audio_set_tone_multiplexing_rate(uint16_t rate) {
  429. tone_multiplexing_rate = rate;
  430. }
  431. void audio_enable_tone_multiplexing(void) {
  432. tone_multiplexing_rate = AUDIO_TONE_MULTIPLEXING_RATE_DEFAULT;
  433. }
  434. void audio_disable_tone_multiplexing(void) {
  435. tone_multiplexing_rate = 0;
  436. }
  437. void audio_increase_tone_multiplexing_rate(uint16_t change) {
  438. if ((0xffff - change) > tone_multiplexing_rate) {
  439. tone_multiplexing_rate += change;
  440. }
  441. }
  442. void audio_decrease_tone_multiplexing_rate(uint16_t change) {
  443. if (change <= tone_multiplexing_rate) {
  444. tone_multiplexing_rate -= change;
  445. }
  446. }
  447. #endif
  448. // Tempo functions
  449. void audio_set_tempo(uint8_t tempo) {
  450. if (tempo < 10) note_tempo = 10;
  451. // else if (tempo > 250)
  452. // note_tempo = 250;
  453. else
  454. note_tempo = tempo;
  455. }
  456. void audio_increase_tempo(uint8_t tempo_change) {
  457. if (tempo_change > 255 - note_tempo)
  458. note_tempo = 255;
  459. else
  460. note_tempo += tempo_change;
  461. }
  462. void audio_decrease_tempo(uint8_t tempo_change) {
  463. if (tempo_change >= note_tempo - 10)
  464. note_tempo = 10;
  465. else
  466. note_tempo -= tempo_change;
  467. }
  468. // TODO in the int-math version are some bugs; songs sometimes abruptly end - maybe an issue with the timer/system-tick wrapping around?
  469. uint16_t audio_duration_to_ms(uint16_t duration_bpm) {
  470. #if defined(__AVR__)
  471. // doing int-math saves us some bytes in the overall firmware size, but the intermediate result is less accurate before being cast to/returned as uint
  472. return ((uint32_t)duration_bpm * 60 * 1000) / (64 * note_tempo);
  473. // NOTE: beware of uint16_t overflows when note_tempo is low and/or the duration is long
  474. #else
  475. return ((float)duration_bpm * 60) / (64 * note_tempo) * 1000;
  476. #endif
  477. }
  478. uint16_t audio_ms_to_duration(uint16_t duration_ms) {
  479. #if defined(__AVR__)
  480. return ((uint32_t)duration_ms * 64 * note_tempo) / 60 / 1000;
  481. #else
  482. return ((float)duration_ms * 64 * note_tempo) / 60 / 1000;
  483. #endif
  484. }