|
1 WITH |
|
2 -- Configuration parameters: |
|
3 duration AS (SELECT 16 AS value), -- in seconds |
|
4 bpm AS (SELECT 120 AS value), -- beats per minute |
|
5 |
|
6 -- Numbered beats, the outline: |
|
7 beat AS ( |
|
8 WITH RECURSIVE beat0 AS ( |
|
9 SELECT 0 AS value |
|
10 UNION ALL |
|
11 SELECT beat0.value + 1 FROM beat0, duration, bpm |
|
12 WHERE beat0.value < (duration.value * bpm.value / 60 - 1) |
|
13 ) |
|
14 SELECT * FROM beat0 |
|
15 ), |
|
16 |
|
17 -- Set instruments for particular channels: |
|
18 raw AS ( |
|
19 SELECT 0 AS time, 'c0 0e' AS raw UNION ALL -- channel 1 = Tubular Bells |
|
20 SELECT 0 AS time, 'c1 58' AS raw -- channel 2 = Fantasia |
|
21 ), |
|
22 |
|
23 -- Parts (quite random sounds): |
|
24 |
|
25 drums_1 AS ( |
|
26 SELECT |
|
27 9 AS channel, |
|
28 beat.value AS beat, NULL AS custom_time, |
|
29 250 * 1000 AS duration, |
|
30 CASE WHEN beat.value % 4 IN (0,1,2) THEN 35 ELSE 40 END AS note_pitch, |
|
31 80 AS note_velocity |
|
32 FROM beat, bpm |
|
33 ), |
|
34 |
|
35 bells_1 AS ( |
|
36 SELECT |
|
37 0 AS channel, |
|
38 beat.value AS beat, NULL AS custom_time, |
|
39 500 * 1000 AS duration, |
|
40 CASE WHEN beat.value / 4 % 2 = 0 THEN 68 ELSE 55 END AS note_pitch, |
|
41 90 AS note_velocity |
|
42 FROM beat, bpm |
|
43 WHERE beat.value % 4 IN (1) |
|
44 ), |
|
45 |
|
46 fantasia_1 AS ( |
|
47 SELECT |
|
48 1 AS channel, |
|
49 beat.value AS beat, NULL AS custom_time, |
|
50 500 * 1000 AS duration, |
|
51 60 + beat.value % 4 AS note_pitch, |
|
52 90 AS note_velocity |
|
53 FROM beat, bpm |
|
54 WHERE beat.value % 4 IN (2,3,0) |
|
55 ), |
|
56 |
|
57 -- Put all parts together: |
|
58 notes AS ( |
|
59 SELECT |
|
60 part.*, |
|
61 CASE |
|
62 WHEN custom_time IS NULL THEN beat * 1000 * 1000 * 60 / bpm.value |
|
63 ELSE CAST(custom_time AS integer) |
|
64 END AS time |
|
65 FROM ( |
|
66 SELECT * FROM drums_1 UNION ALL |
|
67 SELECT * FROM bells_1 UNION ALL |
|
68 SELECT * FROM fantasia_1 |
|
69 ) AS part, bpm |
|
70 ) |
|
71 |
|
72 -- We need to emit two MIDI events: one for key press and one for key release. |
|
73 -- So we add the release events (note_on = false) derived from the time and duration values. |
|
74 SELECT 'note' AS event, time, channel, 1 AS note_on, note_pitch, note_velocity, '' AS raw FROM notes UNION ALL |
|
75 SELECT 'note' AS event, time+duration AS time, channel, 0 AS note_on, note_pitch, note_velocity, '' AS raw FROM notes UNION ALL |
|
76 SELECT 'sysex' AS event, time, 0 AS channel, 0 AS note_on, 0 AS note_pitch, 0 AS note_velocity, raw FROM raw |
|
77 ORDER BY time ASC, event DESC; |