|
1 <stránka |
|
2 xmlns="https://trac.frantovo.cz/xml-web-generator/wiki/xmlns/strana" |
|
3 xmlns:m="https://trac.frantovo.cz/xml-web-generator/wiki/xmlns/makro"> |
|
4 |
|
5 <nadpis>Generating and sending MIDI messages</nadpis> |
|
6 <perex>generate some sounds and send them to the JACK daemon</perex> |
|
7 <m:pořadí-příkladu>04500</m:pořadí-příkladu> |
|
8 |
|
9 <text xmlns="http://www.w3.org/1999/xhtml"> |
|
10 |
|
11 <p> |
|
12 A powerful audio system called <a href="https://jackaudio.org/">JACK</a> allows us to |
|
13 build pipelines consisting of audio interfaces, players, recorders, filters and effects… |
|
14 and route sound streams (both PCM and MIDI) through them. |
|
15 MIDI messages can come from keyboards or other hardware MIDI controllers or from MIDI players and other software. |
|
16 </p> |
|
17 |
|
18 <p> |
|
19 While <code>relpipe-in-jack</code> can be used for <m:a href="examples-jack-midi-monitoring">monitoring MIDI messages</m:a> (<i>recording</i>), |
|
20 the <code>relpipe-out-jack</code> (since <m:a href="release-v0.17">v0.17</m:a>) is designed for sending messages to JACK (<i>playback</i>). |
|
21 So instead of playing <em>Standard MIDI Files</em> (.smf, .mid) |
|
22 we can read relational data and send them as MIDI messages to JACK daemon that forwards them to a hardware or software synthesizer |
|
23 or other program (called <i>client</i> in JACK terminology). |
|
24 </p> |
|
25 |
|
26 <p> |
|
27 The <code>relpipe-out-jack</code> reads relational data in the same format as <code>relpipe-in-jack</code>. |
|
28 So we can capture some MIDI data and play it later. |
|
29 But this is bit boring and any music sequencer would do a better job. |
|
30 We can have more fun with programmatically generating the „music“ (or rather just sounds in beginnings). |
|
31 Thanks to the nature of <m:name/>, the relation containing such „music“ can come from many various sources. |
|
32 In this example we will use the SQL language. |
|
33 </p> |
|
34 |
|
35 |
|
36 <h2>Connect and say hello to MT-32 (SysEx)</h2> |
|
37 |
|
38 <p> |
|
39 Before doing anything audible, we will start with saying hello to our sound module. |
|
40 We need a relation with two attributes. The first one is <code>event</code> and says what should be done. |
|
41 The second one <code>raw</code> contains the raw MIDI data. It is a SysEx message specific to Roland MT-32, |
|
42 but it can be any MIDI event: |
|
43 </p> |
|
44 |
|
45 <m:pre jazyk="bash"><![CDATA[relpipe-in-cli \ |
|
46 --relation "midi" \ |
|
47 --attribute "event" string \ |
|
48 --attribute "raw" string \ |
|
49 --record "sysex" "f0 41 10 16 12 20 00 00 52 65 6c 70 69 70 65 21 6e f7" \ |
|
50 | relpipe-out-jack --connect-to j2a_bridge:playback]]></m:pre> |
|
51 |
|
52 <p> |
|
53 If we omit the <code>--connect-to j2a_bridge:playback</code> part, the <code>relpipe-out-jack</code> command |
|
54 will wait util we connect it somewhere e.g. using QjackCtl. |
|
55 We can control this behavior by explicitly specifying <code>--required-connections N</code> (default <code>N</code> is 1) |
|
56 and say e.g. „Wait until you have 3 connections and then start sending“. |
|
57 But because we specified the destination port, the <code>relpipe-out-jack</code> command immediately |
|
58 connects to it and sends data there. |
|
59 </p> |
|
60 |
|
61 <p> |
|
62 The <code>j2a_bridge:playback</code> port was created by the <code>j2amidi_bridge</code> |
|
63 that bridges JACK-MIDI and ALSA-MIDI. |
|
64 In QjackCtl or other tool, we can connect the ALSA end of this bridge to a physical interface (sound module, synthesizer). |
|
65 If we have no audio hardware, we omit this part and stay in the JACK world – we can connect our MIDI ports to various |
|
66 applications like Yoshimi, QMidiArp, Qtractor etc. |
|
67 </p> |
|
68 |
|
69 <p> |
|
70 See more details on MT-32 and MIDI SysEx in: <m:a href="examples-jack-midi-monitoring">Monitoring MIDI messages using JACK</m:a>. |
|
71 </p> |
|
72 |
|
73 <h2>Set the MIDI instruments for particular channels</h2> |
|
74 |
|
75 <p> |
|
76 Instruments (like particular pianos, guitars, drums, special effects etc.) can be set on our synthesizer for particular channels. |
|
77 However for reproducible results and more comfort, it is better to configure the instruments through MIDI commands (<i>Patch change</i>). |
|
78 Currently we misuse the <code>sysex</code> event for this and send this configuration as raw MIDI commands |
|
79 (the <code>c0 0e</code> and <code>c1 58</code> below). |
|
80 In later versions of <code>relpipe-out-jack</code>, there might be better support for instrument configuration. |
|
81 </p> |
|
82 |
|
83 <p> |
|
84 The list of standard instruments is available at MIDI.org: <a href="https://www.midi.org/specifications/item/gm-level-1-sound-set">General MIDI: GM 1 Sound Set</a>. |
|
85 </p> |
|
86 |
|
87 <h2>Play some SQL tones</h2> |
|
88 |
|
89 <p> |
|
90 Specifying the notes as raw MIDI messages is possible but uncomfortable. |
|
91 So we will put <code>note</code> in the <code>event</code> attribute |
|
92 and specify also <code>time</code>, <code>channel</code>, <code>note_on</code>, <code>note_pitch</code> and <code>note_velocity</code> attributes. |
|
93 The <code>relpipe-out-jack</code> will compose the raw MIDI event from these values. |
|
94 </p> |
|
95 |
|
96 <p> |
|
97 We are not going to create any tables or insert any records. |
|
98 Everything in this example is done in-memory by a single SELECT statement executed on an empty database. |
|
99 But of course, we can persist our creations in database tables and later play the music by SELECTing from them. |
|
100 </p> |
|
101 |
|
102 <m:pre jazyk="sql" odkaz="ano" src="examples/jack-midi-1.sql"/> |
|
103 |
|
104 <p> |
|
105 The SQL engine (SQLite by default) called from <code>relpipe-in-sql</code> converts our script into a relation. |
|
106 Then the <code>relpipe-out-jack</code> translates this relation to actual MIDI events and sends them to JACK system. |
|
107 </p> |
|
108 |
|
109 <m:pre jazyk="bash"><![CDATA[relpipe-in-sql \ |
|
110 --relation "midi" "$(cat examples/jack-midi-1.sql)" \ |
|
111 --type-cast 'note_on' boolean \ |
|
112 | relpipe-out-jack \ |
|
113 --connect-to j2a_bridge:playback \ |
|
114 --connect-to relpipe-in-jack:midi-in]]></m:pre> |
|
115 |
|
116 <p> |
|
117 We connect it to two ports, so we can hear the sounds and at the same time, we can monitor the MIDI events |
|
118 (through <code>relpipe-in-jack</code> and usually <code>relpipe-out-csv</code>). |
|
119 We can also use <code>relpipe-out-tabular</code> instead of <code>relpipe-out-jack</code> and check generated data without sending them to JACK. |
|
120 For visual check, we can connect to the JACK port of a MIDI program like Qtractor and record there our creation (like recording from a MIDI keyboard). |
|
121 We can also do some real-time post-processing e.g. using QMidiArp (arpeggiator). |
|
122 </p> |
|
123 |
|
124 <p> |
|
125 If we have some hardware, it should look and sound like this: |
|
126 </p> |
|
127 |
|
128 <video src="https://blog.frantovo.cz/s/1601/jack-midi-1.webm" poster="img/sc-88-video-1.jpeg" controls="controls" width="820px">Maybe you often ask: What would MT-32 do?</video> |
|
129 |
|
130 <p> |
|
131 In this video, the Roland MT-32 and SC-88 Pro are daisy-chained and most sounds come from the SC-88. |
|
132 </p> |
|
133 |
|
134 <p> |
|
135 n.b. the MIDI channel 1 (index 0) is usually silent on MT-32 (default configuration). |
|
136 </p> |
|
137 |
|
138 |
|
139 |
|
140 <h2>Supported event types and attributes</h2> |
|
141 |
|
142 <p> |
|
143 The <code>relpipe-out-jack</code> supports following event types: |
|
144 </p> |
|
145 |
|
146 <ul> |
|
147 <li> |
|
148 <code>note</code>: press or release (depending on <code>note_on</code>) of particular key on keyboard |
|
149 </li> |
|
150 <li> |
|
151 <code>control</code>: change value of a controller (knob, slider, switch etc.) |
|
152 </li> |
|
153 <li> |
|
154 <code>sysex</code>: SystemExclusive command specific for particular device or manufacturer (e.g. show some text on the display) |
|
155 </li> |
|
156 <li> |
|
157 <code>connect</code>: link two JACK ports using a virtual cable |
|
158 </li> |
|
159 <li> |
|
160 <code>disconnect</code>: put that cable away |
|
161 </li> |
|
162 </ul> |
|
163 |
|
164 <p> |
|
165 Because the events of various types are usually interleaved, we pass them as records of one relation. |
|
166 Each type uses a different set of attributes: |
|
167 </p> |
|
168 |
|
169 <table> |
|
170 <thead> |
|
171 <tr> |
|
172 <td><code>event</code></td> |
|
173 <td><code>note</code></td> |
|
174 <td><code>control</code></td> |
|
175 <td><code>sysex</code></td> |
|
176 <td><code>connect</code></td> |
|
177 <td><code>disconnect</code></td> |
|
178 </tr> |
|
179 </thead> |
|
180 <tbody> |
|
181 <tr> |
|
182 <td><code>time</code></td> |
|
183 <td>✔</td> |
|
184 <td>✔</td> |
|
185 <td>✔</td> |
|
186 <td></td> |
|
187 <td></td> |
|
188 </tr> |
|
189 <tr> |
|
190 <td><code>channel</code></td> |
|
191 <td>✔</td> |
|
192 <td>✔</td> |
|
193 <td>✔</td> |
|
194 <td></td> |
|
195 <td></td> |
|
196 </tr> |
|
197 <tr> |
|
198 <td><code>note_on</code></td> |
|
199 <td>✔</td> |
|
200 <td></td> |
|
201 <td></td> |
|
202 <td></td> |
|
203 <td></td> |
|
204 </tr> |
|
205 <tr> |
|
206 <td><code>note_pitch</code></td> |
|
207 <td>✔</td> |
|
208 <td></td> |
|
209 <td></td> |
|
210 <td></td> |
|
211 <td></td> |
|
212 </tr> |
|
213 <tr> |
|
214 <td><code>note_velocity</code></td> |
|
215 <td>✔</td> |
|
216 <td></td> |
|
217 <td></td> |
|
218 <td></td> |
|
219 <td></td> |
|
220 </tr> |
|
221 <tr> |
|
222 <td><code>controller_id</code></td> |
|
223 <td></td> |
|
224 <td>✔</td> |
|
225 <td></td> |
|
226 <td></td> |
|
227 <td></td> |
|
228 </tr> |
|
229 <tr> |
|
230 <td><code>controller_value</code></td> |
|
231 <td></td> |
|
232 <td>✔</td> |
|
233 <td></td> |
|
234 <td></td> |
|
235 <td></td> |
|
236 </tr> |
|
237 <tr> |
|
238 <td><code>raw</code></td> |
|
239 <td></td> |
|
240 <td></td> |
|
241 <td>✔</td> |
|
242 <td></td> |
|
243 <td></td> |
|
244 </tr> |
|
245 <tr> |
|
246 <td><code>source_port</code></td> |
|
247 <td></td> |
|
248 <td></td> |
|
249 <td></td> |
|
250 <td>✔</td> |
|
251 <td>✔</td> |
|
252 </tr> |
|
253 <tr> |
|
254 <td><code>destination_port</code></td> |
|
255 <td></td> |
|
256 <td></td> |
|
257 <td></td> |
|
258 <td>✔</td> |
|
259 <td>✔</td> |
|
260 </tr> |
|
261 </tbody> |
|
262 </table> |
|
263 |
|
264 |
|
265 <p> |
|
266 Note: this design pattern is one of possible ways how to implement the <em>inheritance</em> (an object-oriented concept) in the relational world. |
|
267 The relation contains one attribute that determines the <i>type</i> (or <i>class</i>) |
|
268 and then union of all attributes of all that types. |
|
269 Each type uses just its relevant attributes and the rest is empty. |
|
270 </p> |
|
271 |
|
272 <p> |
|
273 The meaning of the attributes is following: |
|
274 </p> |
|
275 |
|
276 <table> |
|
277 <thead> |
|
278 <tr> |
|
279 <td>attribute</td> |
|
280 <td>type</td> |
|
281 <td>description</td> |
|
282 </tr> |
|
283 </thead> |
|
284 <tbody> |
|
285 <tr> |
|
286 <td> |
|
287 <code>event</code> |
|
288 </td> |
|
289 <td> |
|
290 <code>string</code> |
|
291 </td> |
|
292 <td>type of the record</td> |
|
293 </tr> |
|
294 <tr> |
|
295 <td> |
|
296 <code>time</code> |
|
297 </td> |
|
298 <td> |
|
299 <code>integer</code> |
|
300 </td> |
|
301 <td>time in microseconds since start of the playback</td> |
|
302 </tr> |
|
303 <tr> |
|
304 <td> |
|
305 <code>channel</code> |
|
306 </td> |
|
307 <td> |
|
308 <code>integer</code> |
|
309 </td> |
|
310 <td>number of the MIDI channel; starts from 0</td> |
|
311 </tr> |
|
312 <tr> |
|
313 <td> |
|
314 <code>note_on</code> |
|
315 </td> |
|
316 <td> |
|
317 <code>boolean</code> |
|
318 </td> |
|
319 <td>whether the key was pressed (<code>true</code>) or released (<code>false</code>)</td> |
|
320 </tr> |
|
321 <tr> |
|
322 <td> |
|
323 <code>note_pitch</code> |
|
324 </td> |
|
325 <td> |
|
326 <code>integer</code> |
|
327 </td> |
|
328 <td>pitch or tone; starts from 0; e.g. C4 is 60</td> |
|
329 </tr> |
|
330 <tr> |
|
331 <td> |
|
332 <code>note_velocity</code> |
|
333 </td> |
|
334 <td> |
|
335 <code>integer</code> |
|
336 </td> |
|
337 <td>force with which a note is played; 0-127</td> |
|
338 </tr> |
|
339 <tr> |
|
340 <td> |
|
341 <code>controller_id</code> |
|
342 </td> |
|
343 <td> |
|
344 <code>integer</code> |
|
345 </td> |
|
346 <td>number of the controller; starts from 0</td> |
|
347 </tr> |
|
348 <tr> |
|
349 <td> |
|
350 <code>controller_value</code> |
|
351 </td> |
|
352 <td> |
|
353 <code>integer</code> |
|
354 </td> |
|
355 <td>value of the controller; 0-127</td> |
|
356 </tr> |
|
357 <tr> |
|
358 <td> |
|
359 <code>raw</code> |
|
360 </td> |
|
361 <td> |
|
362 <code>string</code> |
|
363 </td> |
|
364 <td>raw MIDI bytes written in hexadecimal format; e.g. <code>91 3c 41</code></td> |
|
365 </tr> |
|
366 <tr> |
|
367 <td> |
|
368 <code>source_port</code> |
|
369 </td> |
|
370 <td> |
|
371 <code>string</code> |
|
372 </td> |
|
373 <td>name of the JACK output port; e.g. <code>system:capture_1</code></td> |
|
374 </tr> |
|
375 <tr> |
|
376 <td> |
|
377 <code>destination_port</code> |
|
378 </td> |
|
379 <td> |
|
380 <code>string</code> |
|
381 </td> |
|
382 <td>name of the JACK input port; e.g. <code>system:playback_1</code></td> |
|
383 </tr> |
|
384 </tbody> |
|
385 </table> |
|
386 |
|
387 <p> |
|
388 Besides the <code>event</code> we need to specify only attributes we use. |
|
389 So if we e.g. only send SysEx messages, we need only <code>event</code> and <code>raw</code> attributes. |
|
390 If the <code>time</code> is missing, the event is processed as soon as possible (in the next real-time cycle). |
|
391 The <code>time</code> attribute is used for precise timing |
|
392 – so the process is not driven by the time when the event arrives on STDIN of the <code>relpipe-out-jack</code>. |
|
393 </p> |
|
394 |
|
395 |
|
396 </text> |
|
397 |
|
398 </stránka> |