Skip to content

Instantly share code, notes, and snippets.

@ahx
Created September 1, 2008 16:54
Show Gist options
  • Save ahx/8322 to your computer and use it in GitHub Desktop.
Save ahx/8322 to your computer and use it in GitHub Desktop.
A very simple onscreen midi-keyboard using Shoes and Midator.
#
# A simple onscreen midi-keyboard using Shoes and Midiator.
# No key-up Event.
#
# Set Keyboard layout here:
KEYBOARD_LAYOUT = :de # only :de and :us are supported, by now. See MidiKeymap#map_keys!
#
# You will need a midi input for this.
# On OSX you could use http://notahat.com/midi_patchbay
# and http://notahat.com/simplesynth or Garage Band
#
# Authors: Andreas Haller(http://github.com/ahaller)
# Copyright (c) 2008 Andreas Haller
# This code released under the terms of the MIT license.
#
# enjoy.
Shoes.setup do
gem 'midiator >= 0.2.0'
end
require 'midiator'
# Methods for drawing the piano keys
module ClaviatureDrawing
module Highlightable
def highlight
self.style :stroke => app.fuchsia
end
def unhighlight
self.style :stroke => app.black
end
end
def draw_keys
stroke black
strokewidth 4
key_pattern = [:w,:b,:w,:b,:w,:w,:b,:w,:b,:w,:b,:w]
keys = []
20.times do |i|
key_type = key_pattern[i % key_pattern.length]
case key_type
when :w
k = draw_white_key
translate 64, 0
when :b
# FIXME Fix z-index of black keys. The black keys should be in front of white keys.
k = draw_black_key
end
k.extend Highlightable
keys << k
end
keys
end
def draw_white_key
nofill
rect 0, 0, 60, 130, 4
end
def draw_black_key
fill black
rect -20, 0, 40, 80, 4
end
end
# Responsible for mapping Keystrings to Midi-tones.
class Keymap
attr_accessor :octave
def initialize(options = {})
options = {
:layout => :de,
:octave => 2
}.merge!(options)
@octave = options[:octave]
set_layout!(options[:layout])
end
def midi_tone_of(keystring)
# TODO Oktave richtig mit einberechnen!..
(@octave+1) * 12 + @tones[keystring]
end
# Method to find out, which key has been pressed, the most left key is 0 ...
def index_of(keystring)
@tones[keystring]
end
private
def set_layout!(lang)
@keys = {
:de => %w(a w s e d f t g z h u j k o l p ö ä + # ),
:us => %w(a w s e d f t g y h u j k o l p ; ' ] \\ )
}[lang]
map_keys!
end
def map_keys!
@tones = {}
@keys.each_with_index do |k, i|
@tones[k] = i
end
end
end
# The Shoes App
Shoes.app(:title => "Midi Keyboard", :width => 766, :height => 136, :resizable => false) do
self.extend ClaviatureDrawing
def play(note, time)
# Midiator sleeps for 'time' after each note, so we start a new threat (is this ok?)
Thread.new { @midi.play(note, time) } # note, duration, channel, velocity
end
def highlight(shape, time)
shape.highlight
timer time do
shape.unhighlight
end
end
background yellow
# setup midi driver
@midi = MIDIator::Interface.new
@midi.autodetect_driver
# setup keymap
@keymap = Keymap.new(:layout => KEYBOARD_LAYOUT)
# draw keys
@key_shapes = draw_keys
keypress do |key|
case key
when "1"
@keymap.octave -= 1
when "2"
@keymap.octave += 1
else
t = 1
play(@keymap.midi_tone_of(key), t)
highlight(@key_shapes[@keymap.index_of(key)], t)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment