usb_midi.c 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. #include <furi.h>
  2. #include <furi_hal.h>
  3. #include "usb/usb_midi_driver.h"
  4. #include "midi/parser.h"
  5. #include "midi/usb_message.h"
  6. #include <math.h>
  7. float note_to_frequency(int note) {
  8. float a = 440;
  9. return (a / 32) * powf(2, ((note - 9) / 12.0));
  10. }
  11. typedef enum {
  12. MidiThreadEventStop = (1 << 0),
  13. MidiThreadEventRx = (1 << 1),
  14. MidiThreadEventAll = MidiThreadEventStop | MidiThreadEventRx,
  15. } MidiThreadEvent;
  16. static void midi_rx_callback(void* context) {
  17. furi_assert(context);
  18. FuriThreadId thread_id = (FuriThreadId)context;
  19. furi_thread_flags_set(thread_id, MidiThreadEventRx);
  20. }
  21. int32_t usb_midi_app(void* p) {
  22. UNUSED(p);
  23. FuriHalUsbInterface* usb_config_prev;
  24. usb_config_prev = furi_hal_usb_get_config();
  25. midi_usb_set_context(furi_thread_get_id(furi_thread_get_current()));
  26. midi_usb_set_rx_callback(midi_rx_callback);
  27. furi_hal_usb_set_config(&midi_usb_interface, NULL);
  28. MidiParser* parser = midi_parser_alloc();
  29. uint32_t events;
  30. uint8_t current_note = 255;
  31. while(1) {
  32. events = furi_thread_flags_wait(MidiThreadEventAll, FuriFlagWaitAny, FuriWaitForever);
  33. if(!(events & FuriFlagError)) {
  34. if(events & MidiThreadEventRx) {
  35. uint8_t buffer[64];
  36. size_t size = midi_usb_rx(buffer, sizeof(buffer));
  37. // loopback
  38. // midi_usb_tx(buffer, size);
  39. size_t start = 0;
  40. while(start < size) {
  41. CodeIndex code_index = code_index_from_data(buffer[start]);
  42. uint8_t data_size = usb_message_data_size(code_index);
  43. if(data_size == 0) break;
  44. start += 1;
  45. for(size_t j = 0; j < data_size; j++) {
  46. if(midi_parser_parse(parser, buffer[start + j])) {
  47. MidiEvent* event = midi_parser_get_message(parser);
  48. if(event->type == NoteOn) {
  49. NoteOnEvent note_on = AsNoteOn(event);
  50. current_note = note_on.note;
  51. if(furi_hal_speaker_is_mine() || furi_hal_speaker_acquire(1000)) {
  52. furi_hal_speaker_start(
  53. note_to_frequency(note_on.note),
  54. note_on.velocity / 127.0f);
  55. }
  56. } else if(event->type == NoteOff) {
  57. NoteOffEvent note_off = AsNoteOff(event);
  58. if(note_off.note == current_note) {
  59. if(furi_hal_speaker_is_mine()) {
  60. furi_hal_speaker_stop();
  61. furi_hal_speaker_release();
  62. }
  63. }
  64. }
  65. }
  66. }
  67. start += data_size;
  68. }
  69. }
  70. }
  71. }
  72. midi_parser_free(parser);
  73. furi_hal_usb_set_config(usb_config_prev, NULL);
  74. return 0;
  75. }