From d922c5bd0be20d4c1d573b27ea7e09d9bfa1cba6 Mon Sep 17 00:00:00 2001 From: Erik Mackdanz Date: Mon, 23 Oct 2017 00:19:06 +0000 Subject: [PATCH] Handle program change messages --- README | 9 +++++++-- src/lex.l | 28 ++++++++++++++++++++++------ src/realtime.c | 4 ++++ syntax/quincer.el | 2 +- 4 files changed, 34 insertions(+), 9 deletions(-) diff --git a/README b/README index 9ed689a..d4dac15 100644 --- a/README +++ b/README @@ -89,9 +89,13 @@ k 90 80 j a4 80 b f# 70 l d 60 + M a5 100 m a5 60 +# Send program change (program 3) to rhykeys instrument +P pc 3 + # Reso on the synth r cc 74 0 R cc 74 127 @@ -99,6 +103,7 @@ R cc 74 127 0.....'.....'.....'.....|.....'.....'.....'..... $ $- f g | basskick k | rim +P | rhykeys M m m | rhykeys j--------- l---b----- | suskeys r R | reso @@ -144,8 +149,8 @@ k 90 80 This takes the form: pattern - [cc] - [cc] + [cc|pc] + [cc|pc] ... Note that 'bpm' is declared for each pattern, which allows mid-song diff --git a/src/lex.l b/src/lex.l index a96feb7..e9f8ac0 100644 --- a/src/lex.l +++ b/src/lex.l @@ -35,7 +35,8 @@ enum EventType { NoneYet = -1, NoteOn, - Cc + ControlChange, + ProgramChange }; struct eventdef { @@ -241,7 +242,7 @@ %s incfilename %s comment %s patname patbpm patswing -%s eventdefchar eventdefcharortickdef eventtypeorval eventval1 eventval2 +%s eventdefchar eventdefcharortickdef eventtypeorval eventval1 eventval1progchange eventval2 %s tickdefchar %s pv pvvoicename %s runspec @@ -251,7 +252,7 @@ ID [a-z][a-z0-9]{0,15} CHANNEL 1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16 EVENTDEFCHAR [[:print:]]{-}[S0\.\'|\- ] -EVENTTYPE note|cc +EVENTTYPE note|cc|pc EVENTDEFSHORT [0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-7] RUNSPEC once|loop @@ -415,10 +416,14 @@ NAMEDPITCHRELATIVE [a-gA-G][b#]? struct eventdef* def = eventdefs + current_eventdef; if(!strcmp("note",yytext)) { def->type = last_event_type = NoteOn; + BEGIN(eventval1); } else if(!strcmp("cc",yytext)) { - def->type = last_event_type = Cc; + def->type = last_event_type = ControlChange; + BEGIN(eventval1); + } else if(!strcmp("pc",yytext)) { + def->type = last_event_type = ProgramChange; + BEGIN(eventval1progchange); } - BEGIN(eventval1); } {NAMEDPITCHABSOLUTE} { @@ -469,6 +474,12 @@ NAMEDPITCHRELATIVE [a-gA-G][b#]? BEGIN(eventval2); } +{EVENTDEFSHORT} { + struct eventdef* def = eventdefs + current_eventdef; + def->data[0] = (char)atoi(yytext); + BEGIN(eventdefcharortickdef); + } + {EVENTDEFSHORT} { struct eventdef* def = eventdefs + current_eventdef; def->data[1] = (char)atoi(yytext); @@ -571,11 +582,16 @@ NAMEDPITCHRELATIVE [a-gA-G][b#]? evtnew->data[1] = def->data[0]; evtnew->data[2] = def->data[1]; break; - case Cc: + case ControlChange: evtnew->data[0] = 0xB0; // control change evtnew->data[1] = def->data[0]; evtnew->data[2] = def->data[1]; break; + case ProgramChange: + evtnew->data[0] = 0xC0; // program change + evtnew->data[1] = def->data[0] - 1; // program 1 should get 0 + evtnew->data[2] = 0; + break; case NoneYet: break; } diff --git a/src/realtime.c b/src/realtime.c index 531370b..64bcf24 100644 --- a/src/realtime.c +++ b/src/realtime.c @@ -253,6 +253,10 @@ static void accumulate_pattern_events(qn_context_t* ctx, qn_port_t* port, outev->szdata = 3; outev->data[0] |= pv->voice->channel; break; + case 0xc0: // program change + outev->szdata = 2; + outev->data[0] |= pv->voice->channel; + break; } increment_nout: diff --git a/syntax/quincer.el b/syntax/quincer.el index 6a32e48..d72c27f 100644 --- a/syntax/quincer.el +++ b/syntax/quincer.el @@ -6,7 +6,7 @@ '("run" "once" "loop" "voice" "pattern" - "cc" "note" + "cc" "pc" "note" "include" "clock") ;; some keywords '( -- 2.11.4.GIT