1 2 /** 3 * A MIDI processor for Jack. 4 * It alters the velocity of note messages according to a given curve function. 5 */ 6 7 module velocityCurve; 8 import jack.client; 9 import jack.midiport; 10 import std.stdio; 11 import std.math; 12 import core.stdc.string; 13 14 /// the curve function [0,1]->[0,1] is defined as 15 /// 1-((exp(s*(1-x))-1)/(exp(s)-1)) 16 /// with the constant slope factor s=4 17 double curve(double x) { 18 enum curve_s = 4.0; 19 enum exp_curve_s = /*exp(curve_s)*/ 54.598150033144236; 20 return 1.0 - (fastexp(curve_s * (1.0 - x)) - 1.0) / (exp_curve_s - 1.0); 21 } 22 23 void main() 24 { 25 JackClient client = new JackClient; 26 client.open("velocityCurve", JackOptions.JackNoStartServer, null); 27 scope(exit) client.close(); 28 29 writeln("New jack_client with name: " ~ client.get_name()); 30 31 JackPort midi_in = client.register_port("In", JACK_DEFAULT_MIDI_TYPE, JackPortFlags.JackPortIsInput, 0); 32 JackPort midi_out = client.register_port("Out", JACK_DEFAULT_MIDI_TYPE, JackPortFlags.JackPortIsOutput, 0); 33 34 client.process_callback = delegate int(jack_nframes_t nframes) { 35 JackMidiPortBuffer inbuf = midi_in.get_midi_buffer(nframes); 36 JackMidiPortBuffer outbuf = midi_out.get_midi_buffer(nframes); 37 38 outbuf.clear(); 39 40 foreach (JackMidiEvent event; inbuf.iter_events()) { 41 42 if (event.buffer[0] & 0x80 || event.buffer[0] & 0x90) { 43 double vel = event.buffer[2] / 127.0; 44 double newvel = curve(vel); 45 if (newvel < 0.0) newvel = 0.0; 46 else if (newvel > 1.0) newvel = 1.0; 47 event.buffer[2] = cast(ubyte)lrint(newvel * 127.0); 48 } 49 50 outbuf.write_event(event.time, event.buffer, event.size); 51 } 52 53 return 0; 54 }; 55 56 client.activate(); 57 58 writeln("Press a key to stop."); 59 stdin.readln(); 60 } 61 62 /// fast approximate exp function 63 double fastexp(double x) { 64 union U { 65 double d; 66 struct { 67 version(BigEndian) { int32_t i, j; } 68 version(LittleEndian) { int32_t j, i; } 69 }; 70 } 71 U u; 72 u.d = 0.0; 73 const double exp_a = 1048756.0 / LN2; 74 const double exp_c = 60801.0; 75 u.i = cast(int32_t)lrint(exp_a * x + (1072693248.0 - exp_c)); 76 return u.d; 77 };