jack.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /*
  2. Author: Harry van Haaren
  3. E-mail: harryhaaren@gmail.com
  4. Copyright (C) 2010 Harry van Haaren
  5. Copyright (C) 2015 Tobias Platen
  6. PrintSynth is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. PrintJackMidi is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with PrintJackMidi. If not, see <http://www.gnu.org/licenses/>. */
  16. #include "jack.hpp"
  17. #include <unistd.h>
  18. #include "midi.h"
  19. using namespace std;
  20. Jack::Jack() {
  21. std::cout << "Jack()" << std::flush;
  22. if ((client = jack_client_open("SampleMidiSynth", JackNullOption, NULL)) ==
  23. 0) {
  24. std::cout << "jack server not running?" << std::endl;
  25. }
  26. synth.init(jack_get_sample_rate(client), jack_get_buffer_size(client));
  27. bufferSize = jack_get_buffer_size(client);
  28. inputPort = jack_port_register(client, "midi_in", JACK_DEFAULT_MIDI_TYPE,
  29. JackPortIsInput, 0);
  30. outputPort = jack_port_register(client, "audio_out", JACK_DEFAULT_AUDIO_TYPE,
  31. JackPortIsOutput, 0);
  32. inputBuffer = jack_ringbuffer_create(4096);
  33. outputBuffer = jack_ringbuffer_create(4096 * sizeof(float));
  34. jack_set_process_callback(client, staticProcess, static_cast<void *>(this));
  35. std::cout << "\t\t\tDone!" << std::endl;
  36. }
  37. Jack::~Jack() { std::cout << "~Jack()" << std::endl; }
  38. void Jack::activate() {
  39. std::cout << "activate()" << std::flush;
  40. if (jack_activate(client) != 0) {
  41. std::cout << "cannot activate client" << std::endl;
  42. return;
  43. }
  44. std::cout << "\t\tDone!" << std::endl;
  45. jack_connect(client, "a2j:MIDIMATE II [20] (capture): MIDIMATE II MIDI 1",
  46. "SampleMidiSynth:midi_in");
  47. jack_connect(client, "SampleMidiSynth:audio_out", "system:playback_1");
  48. jack_connect(client, "SampleMidiSynth:audio_out", "system:playback_2");
  49. std::thread *thr = new std::thread(Jack::staticWorkerThread, this);
  50. (void) thr;
  51. }
  52. int Jack::staticProcess(jack_nframes_t nframes, void *arg) {
  53. return static_cast<Jack *>(arg)->process(nframes);
  54. }
  55. int Jack::process(jack_nframes_t nframes) {
  56. jack_midi_event_t in_event;
  57. //jack_nframes_t event_index = 0;
  58. //jack_position_t position;
  59. //jack_transport_state_t transport;
  60. // get the port data
  61. void *inputPortBuf = jack_port_get_buffer(inputPort, nframes);
  62. //void *outputPortBuf = jack_port_get_buffer(outputPort, nframes);
  63. jack_nframes_t event_count = jack_midi_get_event_count(inputPortBuf);
  64. if (event_count > 0) {
  65. for (uint i = 0; i < event_count; i++) {
  66. jack_midi_event_get(&in_event, inputPortBuf, i);
  67. unsigned char event[4];
  68. event[0] = 0;
  69. event[1] = in_event.buffer[0];
  70. event[2] = in_event.buffer[1];
  71. event[3] = in_event.buffer[2];
  72. if (jack_ringbuffer_write_space(inputBuffer) > 4) {
  73. jack_ringbuffer_write(inputBuffer, (char *)event, 4);
  74. }
  75. }
  76. }
  77. jack_default_audio_sample_t *out =
  78. (jack_default_audio_sample_t *)jack_port_get_buffer(outputPort, nframes);
  79. if (jack_ringbuffer_read_space(outputBuffer) > nframes * sizeof(float) * 2) {
  80. jack_ringbuffer_read(outputBuffer, (char *)out, nframes * sizeof(float));
  81. }
  82. return 0;
  83. }
  84. void Jack::staticWorkerThread(Jack *self) {
  85. fprintf(stderr, "worker thread - non realtime\n");
  86. while (1) {
  87. if (jack_ringbuffer_read_space(self->inputBuffer) >= 4) {
  88. unsigned char event[4];
  89. jack_ringbuffer_read(self->inputBuffer, (char *)event, 4);
  90. int sb = event[1];
  91. int arg1 = event[2];
  92. int arg2 = event[3];
  93. if (MIDI_STATUS(sb) == MIDI_NOTEOFF ||
  94. (MIDI_STATUS(sb) == MIDI_NOTEON && arg2 == 0))
  95. self->synth.noteOff(arg1);
  96. else if (MIDI_STATUS(sb) == MIDI_NOTEON)
  97. self->synth.noteOn(arg1, arg2);
  98. else if (MIDI_STATUS(sb) == MIDI_CONTROLLER)
  99. self->synth.controllerEvent(arg1, arg2);
  100. else if (MIDI_STATUS(sb) == MIDI_PITCHBEND)
  101. self->synth.pitchBend(arg1, arg2);
  102. }
  103. if (jack_ringbuffer_write_space(self->outputBuffer) >=
  104. self->bufferSize * sizeof(float)) {
  105. float buffer[self->bufferSize];
  106. self->synth.fill(buffer, self->bufferSize);
  107. jack_ringbuffer_write(self->outputBuffer, (char *)buffer,
  108. self->bufferSize * sizeof(float));
  109. }
  110. usleep(1000);
  111. }
  112. }