'') seq = B::Sequencer.new bpm = 120 time = 0 tone = 0 octave = 4 length = 4 velocity = 127 scanner.skip /\s*/ until scanner.empty? case when scanner.scan(/T\s*(\d+)/i) bpm = scanner[1].to_i when scanner.scan(/O\s*(\d+)/i) octave = scanner[1].to_i when scanner.scan(/L\s*(\d+)/i) length = scanner[1].to_i when scanner.scan(/V\s*(\d+)/i) velocity = scanner[1].to_i when scanner.scan(/R\s*(\d+)?/i) time += seconds scanner[1]&.to_i || length, bpm when scanner.scan(/@\s*(\d+)/) tone = scanner[1].to_i when scanner.scan(/([<>])/) case scanner[1] when '<' then octave -= 1 when '>' then octave += 1 end when scanner.scan(/([CDEFGAB])\s*([#+-]+)?\s*(\d+)?\s*(\.+)?/i)&.chomp char, offset, len, dots = [1, 2, 3, 4].map {scanner[_1]} freq = frequency(char, offset, octave) or next sec = seconds len&.to_i || length, bpm sec *= 1 + dots.size.times.map {0.5 / (_1 + 1)}.sum if dots osc = B::Oscillator.new TONES[tone], freq: freq env = B::Envelope.new {note_on; note_off (sec - 0.01).clamp(0.01..)} gain = B::Gain.new gain: velocity.clamp(0, 127) / 127.0 * 0.5 seq.add osc >> env >> gain, time, sec time += sec else raise "Unknown input: #{scanner.rest[..10]}" end scanner.skip /\s*/ end seq end private TONES = [:sine, :triangle, :square, :sawtooth] DISTANCES = -> { notes = 'c_d_ef_g_a_b'.each_char.with_index.reject {|c,| c == '_'}.to_a octaves = (0..11).to_a octaves.product(notes) .map.with_object({}) {|(octave, (note, index)), hash| hash[[note, octave]] = octave * 12 + index - 57 } }.call def frequency(note, offset, octave) raise "Bad note: '#{note}'" unless note =~ /[cdefgab]/i distance = DISTANCES[[note.downcase, octave]] distance += (offset || '').each_char.reduce(0) {|value, char| case char when '+', '#' then value + 1 when '-' then value - 1 else value end } 440 * (2 ** (distance.to_f / 12)) end def seconds(length, bpm) 60.0 / bpm / length end end ؆қ..-ίϯύΠϥʔ # Ϛε͕ΫϦοΫ͞ΕͨΒݺΕΔ mousePressed do # ΫϦοΫ͕Θ͔ΔΑ͏ʹؙΛඳը circle mouseX, mouseY, 50 # 2ͭͷ MML ΛίϯύΠϧͯ͠ Sequencer ΦϒδΣΫτΛ2ͭੜ seq1 = MMLCompiler.new.compile '@1 ffffre-rgrf1' seq2 = MMLCompiler.new.compile '@1 c<bb-argrb-ra1' # 2ͭͷ Sequencer ΦϒδΣΫτΛಉ࣌ʹ໐Β͢ B::Sound.new(seq1, 3).play B::Sound.new(seq2, 3).play end https://discord.gg/C847WppZeT IUUQTHJTUHJUIVCDPNYPSEEDEBGFG