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:
require 'dl/import' class LiveMIDI ON = 0x90 OFF = 0x80 PC = 0xC0 def initialize open end def note_on(channel, note, velocity = 64) message(ON | channel, note, velocity) end def note_off(channel, note, velocity = 64) message(OFF | channel, note, velocity) end def program_change(channel, preset) message(PC | channel, preset) end end if (RUBY_PLATFORM.include?('mswin') || RUBY_PLATFORM.include?('w32')) class LiveMIDI #Windows code module C extend DL::Importable dlload 'winmm' extern "int midiOutOpen(HMIDIOUT*, int, int, int, int)" extern "int midiOutClose(int)" extern "int midiOutShortMsg(int, int)" end def open @device = DL.malloc(DL.sizeof('I')) C.midiOutOpen(@device, -1, 0, 0, 0) end def close C.midiOutClose(@device.ptr.to_i) end def message(one, two = 0, three=0) message = one + (two << 8) + (three << 16) C.midiOutShortMsg(@device.ptr.to_i, message) end end elsif RUBY_PLATFORM.include?('darwin') class LiveMIDI #Mac code here someday end elsif RUBY_PLATFORM.include?('linux') class LiveMIDI #Linux code here someday end else raise "Couldn't find a LiveMIDI implementation for your platform" end def play_note(channel, note, velocity, sleep_time, midi) midi.note_on(channel, note, velocity) sleep(sleep_time) midi.note_off(channel, note) end def play_chord(channel, notes, velocity, sleep_time, midi) notes.each do |note| midi.note_on(channel, note, velocity) end sleep(sleep_time) notes.each { |note| midi.note_off(channel, note)} end midi = LiveMIDI.new #Middle C chords, Middle C is 60 and each number up or down is a half-step I = [60,64,67] ii = [62,65,69] iii = [64, 67,71] IV = [65, 69, 72] V = [67, 71, 74] vi = [69, 73, 76] midi.program_change(1,32) #to use for the melody if I can figure it out play_note(1,64,100,1,midi) play_note(1,64,100,0.25,midi) play_note(1,64,100,0.25,midi) play_note(1,64,100,0.25,midi) midi.program_change(0, 3) # set channel 0 to piano sleep(1) midi.note_on(1,64,100) 4.times do || play_chord(0, [55,64],100,0.25,midi) play_note(0,48,100,0.25,midi) end midi.note_off(1,64,100) 4.times do || play_chord(0, [57,65],100,0.25,midi) play_note(0,50,100,0.25,midi) end 4.times do || play_chord(0, [60,69],100,0.25,midi) play_note(0,53,100,0.25,midi) end 4.times do || play_chord(0, [64,67],100,0.25,midi) play_note(0,48,100,0.25,midi) end 4.times do || play_chord(0, [64,69,72],100,0.25,midi) play_note(0,57,100,0.25,midi) end 4.times do || play_chord(0, [62,71],100,0.25,midi) play_note(0,55,100,0.25,midi) end 4.times do || play_chord(0, [64,67,72],100,0.25,midi) play_note(0,48,100,0.25,midi) end play_chord(0,[48,52,55,60],100,1,midi)Download it and run it on Windows to hear it play!
Tune from Whitaker Blackall