Class: Musa::Scales::Scale
- Inherits:
-
Object
- Object
- Musa::Scales::Scale
- Extended by:
- Forwardable
- Defined in:
- lib/musa-dsl/music/scales.rb
Instance Attribute Summary collapse
-
#kind ⇒ Object
readonly
Returns the value of attribute kind.
-
#root_pitch ⇒ Object
readonly
Returns the value of attribute root_pitch.
Instance Method Summary collapse
- #==(other) ⇒ Object
- #[](grade_or_symbol) ⇒ Object
- #absolut ⇒ Object
- #chord_of(*grades_or_symbols) ⇒ Object
- #chromatic ⇒ Object
- #grade_of(grade_or_string_or_symbol) ⇒ Object
-
#initialize(kind, root_pitch:) ⇒ Scale
constructor
A new instance of Scale.
- #inspect ⇒ Object (also: #to_s)
- #note_of_pitch(pitch, allow_chromatic: nil, allow_nearest: nil) ⇒ Object
- #octave(octave) ⇒ Object
- #offset_of_interval(interval_name) ⇒ Object
- #parse_grade(neuma_grade) ⇒ Object
- #root ⇒ Object
Constructor Details
#initialize(kind, root_pitch:) ⇒ Scale
Returns a new instance of Scale.
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 |
# File 'lib/musa-dsl/music/scales.rb', line 266 def initialize(kind, root_pitch:) @notes_by_grade = {} @notes_by_pitch = {} @kind = kind @root_pitch = root_pitch @kind.class.grades_functions.each do |name| define_singleton_method name do self[name] end end end |
Instance Attribute Details
#kind ⇒ Object (readonly)
Returns the value of attribute kind.
284 285 286 |
# File 'lib/musa-dsl/music/scales.rb', line 284 def kind @kind end |
#root_pitch ⇒ Object (readonly)
Returns the value of attribute root_pitch.
284 285 286 |
# File 'lib/musa-dsl/music/scales.rb', line 284 def root_pitch @root_pitch end |
Instance Method Details
#==(other) ⇒ Object
413 414 415 416 417 |
# File 'lib/musa-dsl/music/scales.rb', line 413 def ==(other) self.class == other.class && @kind == other.kind && @root_pitch == other.root_pitch end |
#[](grade_or_symbol) ⇒ Object
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 |
# File 'lib/musa-dsl/music/scales.rb', line 304 def [](grade_or_symbol) raise ArgumentError, "grade_or_symbol '#{grade_or_symbol}' should be a Integer, String or Symbol" unless grade_or_symbol.is_a?(Symbol) || grade_or_symbol.is_a?(String) || grade_or_symbol.is_a?(Integer) wide_grade, sharps = grade_of(grade_or_symbol) unless @notes_by_grade.key?(wide_grade) octave = wide_grade / @kind.class.grades grade = wide_grade % @kind.class.grades pitch = @root_pitch + octave * @kind.tuning.notes_in_octave + @kind.class.pitches[grade][:pitch] note = NoteInScale.new self, grade, octave, pitch @notes_by_grade[wide_grade] = @notes_by_pitch[pitch] = note end @notes_by_grade[wide_grade].sharp(sharps) end |
#absolut ⇒ Object
294 295 296 |
# File 'lib/musa-dsl/music/scales.rb', line 294 def absolut @kind[0] end |
#chord_of(*grades_or_symbols) ⇒ Object
409 410 411 |
# File 'lib/musa-dsl/music/scales.rb', line 409 def chord_of(*grades_or_symbols) Chord.new(notes: grades_or_symbols.collect { |g| self[g] }) end |
#chromatic ⇒ Object
290 291 292 |
# File 'lib/musa-dsl/music/scales.rb', line 290 def chromatic @kind.tuning.chromatic[@root_pitch] end |
#grade_of(grade_or_string_or_symbol) ⇒ Object
328 329 330 331 332 333 334 335 336 337 338 339 |
# File 'lib/musa-dsl/music/scales.rb', line 328 def grade_of(grade_or_string_or_symbol) name, wide_grade, accidentals = parse_grade(grade_or_string_or_symbol) grade = @kind.class.grade_of_function name if name octave = wide_grade / @kind.class.grades if wide_grade grade = wide_grade % @kind.class.grades if wide_grade octave ||= 0 return octave * @kind.class.grades + grade, accidentals end |
#inspect ⇒ Object Also known as: to_s
419 420 421 |
# File 'lib/musa-dsl/music/scales.rb', line 419 def inspect "<Scale: kind = #{@kind} root_pitch = #{@root_pitch}>" end |
#note_of_pitch(pitch, allow_chromatic: nil, allow_nearest: nil) ⇒ Object
369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 |
# File 'lib/musa-dsl/music/scales.rb', line 369 def note_of_pitch(pitch, allow_chromatic: nil, allow_nearest: nil) allow_chromatic ||= false allow_nearest ||= false note = @notes_by_pitch[pitch] unless note pitch_offset = pitch - @root_pitch pitch_offset_in_octave = pitch_offset % @kind.tuning.scale_system.notes_in_octave pitch_offset_octave = pitch_offset / @kind.tuning.scale_system.notes_in_octave grade = @kind.class.pitches.find_index { |pitch_definition| pitch_definition[:pitch] == pitch_offset_in_octave } if grade wide_grade = pitch_offset_octave * @kind.class.grades + grade note = self[wide_grade] elsif allow_nearest sharps = 0 until note note = note_of_pitch(pitch - (sharps += 1) * @kind.tuning.scale_system.part_of_tone_size) note ||= note_of_pitch(pitch + sharps * @kind.tuning.scale_system.part_of_tone_size) end elsif allow_chromatic nearest = note_of_pitch(pitch, allow_nearest: true) note = chromatic.note_of_pitch(pitch).with_background(scale: self, grade: nearest.grade, octave: nearest.octave, sharps: (pitch - nearest.pitch) / @kind.tuning.scale_system.part_of_tone_size) end end note end |
#octave(octave) ⇒ Object
298 299 300 301 302 |
# File 'lib/musa-dsl/music/scales.rb', line 298 def octave(octave) raise ArgumentError, "#{octave} is not integer" unless octave == octave.to_i @kind[@root_pitch + octave * @kind.class.grades] end |
#offset_of_interval(interval_name) ⇒ Object
405 406 407 |
# File 'lib/musa-dsl/music/scales.rb', line 405 def offset_of_interval(interval_name) @kind.tuning.offset_of_interval(interval_name) end |
#parse_grade(neuma_grade) ⇒ Object
341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 |
# File 'lib/musa-dsl/music/scales.rb', line 341 def parse_grade(neuma_grade) name = wide_grade = nil accidentals = 0 case neuma_grade when Symbol, String match = /\A(?<name>[^[#|_]]*)(?<accidental_sharps>#*)(?<accidental_flats>_*)\Z/.match neuma_grade.to_s if match if match[:name] == match[:name].to_i.to_s wide_grade = match[:name].to_i else name = match[:name].to_sym unless match[:name].empty? end accidentals = match[:accidental_sharps].length - match[:accidental_flats].length else name = neuma_grade.to_sym unless (neuma_grade.nil? || neuma_grade.empty?) end when Numeric wide_grade = neuma_grade.to_i else raise ArgumentError, "Cannot eval #{neuma_grade} as name or grade position." end return name, wide_grade, accidentals end |
#root ⇒ Object
286 287 288 |
# File 'lib/musa-dsl/music/scales.rb', line 286 def root self[0] end |