No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

main.c 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. /*
  2. Copyright (C) 2002 Anthony Van Groningen
  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. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  14. */
  15. #include <stdlib.h>
  16. #include <stdio.h>
  17. #include <errno.h>
  18. #include <unistd.h>
  19. #include <math.h>
  20. #include <getopt.h>
  21. #include <string.h>
  22. #include <jack/jack.h>
  23. #include <asoundlib.h>
  24. #include "synth.h"
  25. struct Synth synth;
  26. typedef jack_default_audio_sample_t sample_t;
  27. #define CLIENT_NAME "Vampi Synth"
  28. jack_client_t *client;
  29. jack_port_t *output_ports[2];
  30. unsigned long sr;
  31. int verbose = 0;
  32. int process (jack_nframes_t nframes, void *arg) {
  33. sample_t *buffers[2];
  34. buffers[0] = (sample_t *) jack_port_get_buffer (output_ports[0], nframes);
  35. buffers[1] = (sample_t *) jack_port_get_buffer (output_ports[1], nframes);
  36. for(int i = 0; i < nframes; i++) {
  37. float out[2] = {0, 0};
  38. synth_render_sample(&synth, out);
  39. buffers[0][i] = out[0];
  40. buffers[1][i] = out[1];
  41. }
  42. return 0;
  43. }
  44. static char *midi_note_names[12] = {
  45. "C", "C#", "D", "D#", "E", "F",
  46. "F#", "G", "G#", "A", "A#", "B",
  47. };
  48. const char *midi_note_name(int note) {
  49. return midi_note_names[note % 12];
  50. }
  51. const char *midi_cc_name(int cc) {
  52. switch(cc) {
  53. case MIDI_CTL_ALL_NOTES_OFF: return "All notes off";
  54. case MIDI_CTL_ALL_SOUNDS_OFF: return "All sounds off";
  55. case MIDI_CTL_DATA_DECREMENT: return "Data Decrement";
  56. case MIDI_CTL_DATA_INCREMENT: return "Data Increment";
  57. case MIDI_CTL_E1_REVERB_DEPTH: return "E1 Reverb Depth";
  58. case MIDI_CTL_E2_TREMOLO_DEPTH: return "E2 Tremolo Depth";
  59. case MIDI_CTL_E3_CHORUS_DEPTH: return "E3 Chorus Depth";
  60. case MIDI_CTL_E4_DETUNE_DEPTH: return "E4 Detune Depth";
  61. case MIDI_CTL_E5_PHASER_DEPTH: return "E5 Phaser Depth";
  62. case MIDI_CTL_GENERAL_PURPOSE5: return "General purpose 5";
  63. case MIDI_CTL_GENERAL_PURPOSE6: return "General purpose 6";
  64. case MIDI_CTL_GENERAL_PURPOSE7: return "General purpose 7";
  65. case MIDI_CTL_GENERAL_PURPOSE8: return "General purpose 8";
  66. case MIDI_CTL_HOLD2: return "Hold2";
  67. case MIDI_CTL_LEGATO_FOOTSWITCH: return "Legato foot switch";
  68. case MIDI_CTL_LOCAL_CONTROL_SWITCH: return "Local control switch";
  69. case MIDI_CTL_LSB_BALANCE: return "Balance";
  70. case MIDI_CTL_LSB_BANK: return "Bank selection";
  71. case MIDI_CTL_LSB_BREATH: return "Breath";
  72. case MIDI_CTL_LSB_DATA_ENTRY: return "Data entry";
  73. case MIDI_CTL_LSB_EFFECT1: return "Effect1";
  74. case MIDI_CTL_LSB_EFFECT2: return "Effect2";
  75. case MIDI_CTL_LSB_EXPRESSION: return "Expression";
  76. case MIDI_CTL_LSB_FOOT: return "Foot";
  77. case MIDI_CTL_LSB_GENERAL_PURPOSE1: return "General purpose 1";
  78. case MIDI_CTL_LSB_GENERAL_PURPOSE2: return "General purpose 2";
  79. case MIDI_CTL_LSB_GENERAL_PURPOSE3: return "General purpose 3";
  80. case MIDI_CTL_LSB_GENERAL_PURPOSE4: return "General purpose 4";
  81. case MIDI_CTL_LSB_MAIN_VOLUME: return "Main volume";
  82. case MIDI_CTL_LSB_MODWHEEL: return "Modulation";
  83. case MIDI_CTL_LSB_PAN: return "Panpot";
  84. case MIDI_CTL_LSB_PORTAMENTO_TIME: return "Portamento time";
  85. case MIDI_CTL_MONO1: return "Mono1";
  86. case MIDI_CTL_MONO2: return "Mono2";
  87. case MIDI_CTL_MSB_BALANCE: return "Balance";
  88. case MIDI_CTL_MSB_BANK: return "Bank selection";
  89. case MIDI_CTL_MSB_BREATH: return "Breath";
  90. case MIDI_CTL_MSB_DATA_ENTRY: return "Data entry";
  91. case MIDI_CTL_MSB_EFFECT1: return "Effect1";
  92. case MIDI_CTL_MSB_EFFECT2: return "Effect2";
  93. case MIDI_CTL_MSB_EXPRESSION: return "Expression";
  94. case MIDI_CTL_MSB_FOOT: return "Foot";
  95. case MIDI_CTL_MSB_GENERAL_PURPOSE1: return "General purpose 1";
  96. case MIDI_CTL_MSB_GENERAL_PURPOSE2: return "General purpose 2";
  97. case MIDI_CTL_MSB_GENERAL_PURPOSE3: return "General purpose 3";
  98. case MIDI_CTL_MSB_GENERAL_PURPOSE4: return "General purpose 4";
  99. case MIDI_CTL_MSB_MAIN_VOLUME: return "Main volume";
  100. case MIDI_CTL_MSB_MODWHEEL: return "Modulation";
  101. case MIDI_CTL_MSB_PAN: return "Panpot";
  102. case MIDI_CTL_MSB_PORTAMENTO_TIME: return "Portamento time";
  103. case MIDI_CTL_NONREG_PARM_NUM_LSB: return "Non-registered parameter number";
  104. case MIDI_CTL_NONREG_PARM_NUM_MSB: return "Non-registered parameter number";
  105. case MIDI_CTL_OMNI_OFF: return "Omni off";
  106. case MIDI_CTL_OMNI_ON: return "Omni on";
  107. case MIDI_CTL_PORTAMENTO: return "Portamento";
  108. case MIDI_CTL_PORTAMENTO_CONTROL: return "Portamento control";
  109. case MIDI_CTL_REGIST_PARM_NUM_LSB: return "Registered parameter number";
  110. case MIDI_CTL_REGIST_PARM_NUM_MSB: return "Registered parameter number";
  111. case MIDI_CTL_RESET_CONTROLLERS: return "Reset Controllers";
  112. case MIDI_CTL_SC10: return "SC10";
  113. case MIDI_CTL_SC1_SOUND_VARIATION: return "SC1 Sound Variation";
  114. case MIDI_CTL_SC2_TIMBRE: return "SC2 Timbre";
  115. case MIDI_CTL_SC3_RELEASE_TIME: return "SC3 Release Time";
  116. case MIDI_CTL_SC4_ATTACK_TIME: return "SC4 Attack Time";
  117. case MIDI_CTL_SC5_BRIGHTNESS: return "SC5 Brightness";
  118. case MIDI_CTL_SC6: return "SC6";
  119. case MIDI_CTL_SC7: return "SC7";
  120. case MIDI_CTL_SC8: return "SC8";
  121. case MIDI_CTL_SC9: return "SC9";
  122. case MIDI_CTL_SOFT_PEDAL: return "Soft pedal";
  123. case MIDI_CTL_SOSTENUTO: return "Sostenuto";
  124. case MIDI_CTL_SUSTAIN: return "Sustain pedal";
  125. }
  126. return "Unknown";
  127. }
  128. void midi_action(snd_seq_t *seq_handle) {
  129. snd_seq_event_t *ev;
  130. do {
  131. snd_seq_event_input(seq_handle, &ev);
  132. switch (ev->type) {
  133. case SND_SEQ_EVENT_NOTEON:
  134. if(verbose)
  135. printf("Note on %s (%d) %d\n", midi_note_name(ev->data.note.note), ev->data.note.note, ev->data.note.velocity);
  136. synth_note_on(&synth, ev->data.note.note, ev->data.note.velocity);
  137. break;
  138. case SND_SEQ_EVENT_NOTEOFF:
  139. if(verbose)
  140. printf("Note off %s (%d) %d\n", midi_note_name(ev->data.note.note), ev->data.note.note, ev->data.note.velocity);
  141. synth_note_off(&synth, ev->data.note.note, ev->data.note.velocity);
  142. break;
  143. case SND_SEQ_EVENT_PITCHBEND:
  144. synth_pitch_bend(&synth, ev->data.control.value);
  145. break;
  146. case SND_SEQ_EVENT_CONTROLLER:
  147. if(verbose)
  148. printf("CC 0x%02x (%s) %d\n", ev->data.control.param, midi_cc_name(ev->data.control.param), ev->data.control.value);
  149. if(ev->data.control.param == 0x01) {
  150. if(verbose)
  151. printf("LFO Depth %d\n", ev->data.control.value);
  152. synth_set_lfo_depth(&synth, ev->data.control.value);
  153. } else if(ev->data.control.param == 7) {
  154. if(verbose)
  155. printf("Volume %d\n", ev->data.control.value);
  156. synth_set_volume(&synth, ev->data.control.value);
  157. } else if(ev->data.control.param == 91) {
  158. if(verbose)
  159. printf("Unison spread %d\n", ev->data.control.value);
  160. synth_set_unison_spread(&synth, ev->data.control.value);
  161. } else if(ev->data.control.param == 93) {
  162. if(verbose)
  163. printf("Stereo spread %d\n", ev->data.control.value);
  164. synth_set_stereo_spread(&synth, ev->data.control.value);
  165. } else if(ev->data.control.param == 74) {
  166. if(verbose)
  167. printf("Cutoff %d\n", ev->data.control.value);
  168. synth_set_cutoff_freq(&synth, ev->data.control.value);
  169. } else if(ev->data.control.param == 71) {
  170. if(verbose)
  171. printf("Resonance %d\n", ev->data.control.value);
  172. synth_set_resonance(&synth, ev->data.control.value);
  173. }
  174. break;
  175. }
  176. snd_seq_free_event(ev);
  177. } while (snd_seq_event_input_pending(seq_handle, 0) > 0);
  178. }
  179. int main(int argc, char **argv) {
  180. int option_index;
  181. int opt;
  182. char *client_name = CLIENT_NAME;
  183. char *input_seq_addr = 0;
  184. jack_status_t status;
  185. const char *options = "n:p:hv";
  186. struct option long_options[] = {
  187. {"name", 1, 0, 'n'},
  188. {"port", 1, 0, 'p'},
  189. {"help", 0, 0, 'h'},
  190. {"verbose", 0, 0, 'v'},
  191. {0, 0, 0, 0}
  192. };
  193. while ((opt = getopt_long (argc, argv, options, long_options, &option_index)) != EOF) {
  194. switch (opt) {
  195. case 'n':
  196. client_name = (char *) malloc (strlen (optarg) * sizeof (char));
  197. strcpy (client_name, optarg);
  198. break;
  199. case 'p':
  200. input_seq_addr = optarg;
  201. break;
  202. case 'v':
  203. verbose = 1;
  204. break;
  205. default:
  206. fprintf (stderr, "Unknown option %c\n", opt);
  207. case 'h':
  208. fprintf(stderr, "usage: %s [options]\n"
  209. "\t-p, --port <port name> Input port for sequencer events (MIDI keyboard)\n"
  210. "\t-n, --name <name>. Jack client name. Default: " CLIENT_NAME " ]\n"
  211. "\t-v Verbose\n"
  212. "\t-h Help\n",
  213. argv[0]
  214. );
  215. return -1;
  216. }
  217. }
  218. /* Initial Jack setup, get sample rate */
  219. if ((client = jack_client_open (client_name, JackNoStartServer, &status)) == 0) {
  220. fprintf (stderr, "jack server not running?\n");
  221. return 1;
  222. }
  223. jack_set_process_callback(client, process, 0);
  224. output_ports[0] = jack_port_register(client, "Synth Out L", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
  225. output_ports[1] = jack_port_register(client, "Synth Out R", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
  226. sr = jack_get_sample_rate(client);
  227. synth_init(&synth);
  228. if(optind < argc) {
  229. synth_load_patch(&synth, argv[optind]);
  230. }
  231. if (jack_activate(client)) {
  232. fprintf (stderr, "cannot activate client");
  233. exit (1);
  234. }
  235. const char **ports;
  236. ports = jack_get_ports (client, NULL, NULL, JackPortIsPhysical|JackPortIsInput);
  237. if (ports == NULL) {
  238. fprintf(stderr, "no physical capture ports\n");
  239. exit (1);
  240. }
  241. if (jack_connect (client, jack_port_name (output_ports[0]), ports[0])) {
  242. fprintf (stderr, "cannot connect input ports\n");
  243. }
  244. if (jack_connect (client, jack_port_name (output_ports[1]), ports[1])) {
  245. fprintf (stderr, "cannot connect input ports\n");
  246. }
  247. snd_seq_t *seq_handle;
  248. int npfd;
  249. struct pollfd *pfd;
  250. int portid;
  251. if (snd_seq_open(&seq_handle, "default", SND_SEQ_OPEN_INPUT, 0) < 0) {
  252. fprintf(stderr, "Error opening ALSA sequencer.\n");
  253. exit(1);
  254. }
  255. snd_seq_set_client_name(seq_handle, client_name);
  256. if ((portid = snd_seq_create_simple_port(seq_handle, "Cornhole",
  257. SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE,
  258. SND_SEQ_PORT_TYPE_APPLICATION)) < 0) {
  259. fprintf(stderr, "Error creating sequencer port.\n");
  260. exit(1);
  261. }
  262. snd_seq_addr_t seq_input_port;
  263. if(input_seq_addr) {
  264. if(snd_seq_parse_address(seq_handle, &seq_input_port, input_seq_addr) == 0) {
  265. snd_seq_connect_from(seq_handle, portid, seq_input_port.client, seq_input_port.port);
  266. } else {
  267. fprintf(stderr, "Could not parse port: %s\n", input_seq_addr);
  268. exit(1);
  269. }
  270. }
  271. npfd = snd_seq_poll_descriptors_count(seq_handle, POLLIN);
  272. pfd = (struct pollfd *)alloca(npfd * sizeof(struct pollfd));
  273. snd_seq_poll_descriptors(seq_handle, pfd, npfd, POLLIN);
  274. while (1) {
  275. if (poll(pfd, npfd, 100000) > 0) {
  276. midi_action(seq_handle);
  277. }
  278. }
  279. }