Tag Archives: MIDI

A video game music composer has put up a pretty cool tutorial for people interested in making tunes.  It starts from absolute basics and builds up a simple piece.  If only I had the budget to get that kind of music into my flash games!  Once I get to where I can earn anything significant out of them, .

He did the tutorial with Garage Band. Since, I don't have an iPad,  that piece of software isn't an option for me.  I have been working through some ruby tutorials, though, and so I figured I'd give it a shot in MIDI.  It turns out that it's not that much of a pain to access C libraries from within Ruby. It breaks platform independence, but hey, this is just a fun project, so why not?

It took me a little while to get used to MIDI's notation. A note value of 60 is middle C. 59 is half a step lower, 61 is a half step up, and so on. That means that to go up an octave, it's necessary to increase the note value by 12 instead of 8. After adjusting to this, it wasn't too tough to get the chords Whitaker used in his blog post. Well, hopefully they're right! I also started listening to the sound files further down the post, but didn't get that far in deciphering the melody. Here's the ruby code to generate what I've gotten so far:

 

1require 'dl/import'
2 
3class LiveMIDI
4   ON = 0x90
5   OFF = 0x80
6   PC = 0xC0
7    
8   def initialize
9      open
10   end
11    
12   def note_on(channel, note, velocity = 64)
13      message(ON | channel, note, velocity)
14   end
15    
16   def note_off(channel, note, velocity = 64)
17      message(OFF | channel, note, velocity)
18   end
19    
20   def program_change(channel, preset)
21      message(PC | channel, preset)
22   end
23end
24 
25if (RUBY_PLATFORM.include?('mswin') || RUBY_PLATFORM.include?('w32'))
26   class LiveMIDI
27      #Windows code
28      module C
29         extend DL::Importable
30         dlload 'winmm'
31          
32         extern "int midiOutOpen(HMIDIOUT*, int, int, int, int)"
33         extern "int midiOutClose(int)"
34         extern "int midiOutShortMsg(int, int)"
35      end
36       
37      def open
38         @device = DL.malloc(DL.sizeof('I'))
39         C.midiOutOpen(@device, -1, 0, 0, 0)
40      end
41       
42      def close
43         C.midiOutClose(@device.ptr.to_i)
44      end
45       
46      def message(one, two = 0, three=0)
47         message = one + (two << 8) + (three << 16)
48         C.midiOutShortMsg(@device.ptr.to_i, message)
49      end
50       
51   end
52elsif RUBY_PLATFORM.include?('darwin')
53   class LiveMIDI
54      #Mac code here someday
55   end
56elsif RUBY_PLATFORM.include?('linux')
57   class LiveMIDI
58      #Linux code here someday
59   end
60else
61   raise "Couldn't find a LiveMIDI implementation for your platform"
62end
63 
64def play_note(channel, note, velocity, sleep_time, midi)
65   midi.note_on(channel, note, velocity)
66   sleep(sleep_time)
67   midi.note_off(channel, note)
68end
69 
70def play_chord(channel, notes, velocity, sleep_time, midi)
71   notes.each do |note|
72      midi.note_on(channel, note, velocity)
73   end
74   sleep(sleep_time)
75   notes.each { |note| midi.note_off(channel, note)}
76end
77 
78midi = LiveMIDI.new
79#Middle C chords, Middle C is 60 and each number up or down is a half-step
80I = [60,64,67]
81ii = [62,65,69]
82iii = [64, 67,71]
83IV = [65, 69, 72]
84V = [67, 71, 74]
85vi = [69, 73, 76]
86 
87midi.program_change(1,32) #to use for the melody if I can figure it out
88play_note(1,64,100,1,midi)
89play_note(1,64,100,0.25,midi)
90play_note(1,64,100,0.25,midi)
91play_note(1,64,100,0.25,midi)
92 
93 
94midi.program_change(0, 3) # set channel 0 to piano
95 
96sleep(1)
97 
98midi.note_on(1,64,100)
994.times do ||
100   play_chord(0, [55,64],100,0.25,midi)
101   play_note(0,48,100,0.25,midi)
102end
103midi.note_off(1,64,100)
104 
1054.times do ||
106   play_chord(0, [57,65],100,0.25,midi)
107   play_note(0,50,100,0.25,midi)
108end
109 
1104.times do ||
111   play_chord(0, [60,69],100,0.25,midi)
112   play_note(0,53,100,0.25,midi)
113end
114 
1154.times do ||
116   play_chord(0, [64,67],100,0.25,midi)
117   play_note(0,48,100,0.25,midi)
118end
119 
1204.times do ||
121   play_chord(0, [64,69,72],100,0.25,midi)
122   play_note(0,57,100,0.25,midi)
123end
124 
1254.times do ||
126   play_chord(0, [62,71],100,0.25,midi)
127   play_note(0,55,100,0.25,midi)
128end
129 
1304.times do ||
131   play_chord(0, [64,67,72],100,0.25,midi)
132   play_note(0,48,100,0.25,midi)
133end
134play_chord(0,[48,52,55,60],100,1,midi)

Download it and run it on Windows to hear it play!

Tune from Whitaker Blackall