Last active
November 15, 2016 23:36
-
-
Save Arkham/ca83bbaf054b86747557f6bbae147ece to your computer and use it in GitHub Desktop.
Nokia Ringtone Player for Sonic PI
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use_bpm 140 | |
song = "4a1 4#a1 8g1 8#a1 8c2 8f1 8a1 4#a1 8g1 8#a1 8d2 4#d2 8d2 | |
8c2 4#a1 8g1 8#a1 8c2 8f1 8a1 4#a1 8g1 8#a1 8d2 4#d2 8d2 8c2 4#a1 8g1 8#a1 8c2 | |
8f1 8a1 4#a1 8g1 8#a1 8d2 4#d2 8d2 8c2 4#a1 8g1 8#a1 8a1 8f1 8f1 2g1" | |
class NokringParser | |
DURATION_REGEX = /(?<duration>1|2|4|8|16|32)?(?<dotted>\.)?/ | |
NOTE_REGEX = /^#{DURATION_REGEX}(?<sharp>\#)?(?<note>[cdefgab])(?<octave>[1234])?$/ | |
PAUSE_REGEX = /^#{DURATION_REGEX}\-$/x | |
attr_reader :default_duration, :default_octave | |
def initialize(default_duration: 4, default_octave: 2) | |
@default_duration = default_duration | |
@default_octave = default_octave | |
end | |
def parse(expr) | |
if match = expr.match(NOTE_REGEX) | |
octave = match[:octave] || default_octave | |
octave = octave.to_i + 2 | |
note = match[:note] | |
note += 's' if match[:sharp] | |
[:note, "#{note}#{octave}".to_sym, parse_duration(match)] | |
elsif match = expr.match(PAUSE_REGEX) | |
[:pause, parse_duration(match)] | |
else | |
[:error, expr] | |
end | |
end | |
private | |
def parse_duration(match) | |
duration = match[:duration] || default_duration | |
duration = 4.0 / duration.to_i | |
duration *= 1.5 if match[:dotted] | |
duration | |
end | |
end | |
def play_tokens(tokens) | |
tokens.each do |result| | |
case result.first | |
when :note | |
_, note, duration = result | |
play note, release: duration * 1.1 | |
sleep duration | |
when :pause | |
_, duration = result | |
sleep duration | |
else | |
_, error = result | |
puts "Error, couldn't parse expression: #{error}" | |
end | |
end | |
end | |
parser = NokringParser.new | |
live_loop :nokia do | |
play_tokens song.split(" ").map{|e| parser.parse(e)} | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment