1:- module(mididcg, [ midi//3
    2                   , noteon//3
    3                   , noteoff//2
    4                   , note//4
    5                   , prog//2
    6                   , prog//3
    7                   , prog//4
    8                   , pan//2
    9                   , volume//2
   10						 , tempo//1
   11						 , keysig//2
   12						 , timesig//1
   13                   , instr//2
   14                   ]).   15
   16:- use_module(library(clpfd)).   17:- use_module(library(dcg_pair)).   18:- use_module(library(dcg_core), [get//1, set//1]).   19:- use_module(library(genmidi), [gm/4]).   20
   21midi(Msg,Arg1,Arg2) --> get(T) <\> [msg(T,M,Arg1,Arg2)], {M #= Msg}.
   22midi(Msg,Arg1)      --> get(T) <\> [msg(T,M,Arg1)], {M #= Msg}.
   23meta(Msg,Bytes)     --> get(T) <\> [meta(T,M,N,Bytes)], {M #= Msg, length(Bytes,N)}.
   24text(Type,Text)     --> get(T) <\> [text(T,M,Text)], {text_type_code(M, Type)}.
   25
   26text_type_code(0x01, text).
   27text_type_code(0x02, copyright).
   28text_type_code(0x03, track_name).
   29text_type_code(0x04, instrument).
   30text_type_code(0x05, lyric).
   31text_type_code(0x06, marker).
   32text_type_code(0x07, cue).
   33
   34tempo(T)             --> meta(0x51, [B2, B1, B0]), {divmod(T,256,Z,B0), divmod(Z,256,B2,B1)}.
   35keysig(Sharps,major) --> meta(0x59, [Sharps, 0]).
   36keysig(Sharps,minor) --> meta(0x59, [Sharps, 1]).
   37timesig(Num/Denom)   --> meta(0x58, [Num, DenomPower, 24, 8]), { Denom #= 2^DenomPower }.
   38
   39holding_time(P) --> \< get(T), call_dcg(P), \< set(T).
   40
   41noteon(Ch,NN,V) --> midi(144+Ch,NN,V).
   42noteoff(Ch,NN) --> midi(128+Ch,NN,0).
   43
   44note(Ch,Vel,Dur,NN) --> 
   45   {N1 #= NN, V1 #= Vel},
   46   noteon(Ch,N1,V1), \< adv(Dur),
   47   noteoff(Ch,N1).
   48
   49prog(Ch,Prog) -->
   50	midi(192+Ch,Prog).
   51	
   52prog(Ch,Prog,Bank) -->
   53   { MSB #= Bank // 128, 
   54     LSB #= Bank mod 128
   55   },
   56	midi(176+Ch,0,MSB),
   57	midi(176+Ch,32,LSB),
   58	prog(Ch,Prog).
   59
   60prog(Ch,Prog,MSB,LSB) -->
   61	midi(176+Ch,0,MSB),
   62	midi(176+Ch,32,LSB),
   63	prog(Ch,Prog).
   64
   65instr(Ch,Instr) -->
   66   {gm(Instr,Prog,MSB,LSB)},
   67   prog(Ch,Prog,MSB,LSB).
   68
   69pan(Ch,Pan) --> midi(176+Ch,10,Pan).
   70
   71volume(Ch,Vol) --> midi(176+Ch,7,Vol).
   72
   73adv(Dur,T1,T2) :- T2 #= T1 + Dur