class InevitableCacophony::Parser::RhythmLine
Constants
- BAR_LINE
- BEAT_VALUES
Amplitude symbols used by Dwarf Fortress These are in no particular scale; the maximum volume will be whatever's loudest in any particular string.
- TIMING_VALUES
Values for each kind of timing symbol. By default a beat is in the middle of its time-slice (0.0); a value of 1.0 means to play it as late as possible, and -1.0 means play as early as possible.
Technically position of these matters, but we handle that in the parser regexp.
Public Class Methods
parse(rhythm_string)
click to toggle source
# File lib/inevitable_cacophony/parser/rhythm_line.rb, line 74 def self.parse(rhythm_string) new.parse(rhythm_string) end
Public Instance Methods
parse(rhythm_string)
click to toggle source
@param rhythm_string [String] In the notation Dwarf Fortress produces, like | X x ! x | @return [Rhythm]
# File lib/inevitable_cacophony/parser/rhythm_line.rb, line 49 def parse(rhythm_string) # TODO: should I be ignoring bar lines? Is there anything I can do with them? raw_beats = rhythm_string.split(/ |(?=`)|(?<=')/).reject { |beat| beat == BAR_LINE }.map do |beat| timing_symbol = beat.chars.reject { |char| BEAT_VALUES.keys.include?(char) }.join timing = TIMING_VALUES[timing_symbol] || raise("Unknown timing symbol #{timing_symbol}") accent_symbol = beat.delete(timing_symbol) amplitude = BEAT_VALUES[accent_symbol] || raise("Unknown beat symbol #{accent_symbol}") Rhythm::Beat.new(amplitude, 1, timing) end # Ensure all our amplitudes are between 0.0 and 1.0 # TODO: find a way to do this without creating twice as many beats as we need. highest_volume = raw_beats.map(&:amplitude).max scaled_beats = raw_beats.map do |beat| scaled = beat.amplitude.to_f / highest_volume Rhythm::Beat.new(scaled, 1, beat.timing) end Rhythm.new(scaled_beats) end