As I try to understand improvisation in Blues and Jazz, I work a lot with scales and chords. Today the question popped up, how to distinguish whether a scale or a chord is passed into a function or procedure.
I asked perplexity, my favorite AI, but the suggestions seemed cumbersome. After some experiments I came up with this:
# Method distinguishes, whether a chord or scale is passed
# SR 09.04.2025
# Sources:
# - sr_lang_chord_attributes.txt
# - https://www.rubydoc.info/github/samaaron/sonic-pi/SonicPi/Chord
#
# File: sr_lang_chord_or_scale.txt
# method 1: distinguish chord or scale by class
# returns the string "neither", "chord" or "scale"
define :f_is_chord_or_scale_by_class do |par_notes|
l_result = "neither"
# Methode 1: class of array
if par_notes.to_a.class == SonicPi::Chord then
l_result = "chord"
end
if par_notes.to_a.class == SonicPi::Scale then
l_result = "scale"
end
return l_result
end
# distinguish chord or scale by tonic (Grundton)
# returns the string "neither", "chord" or "scale"
define :f_is_chord_or_scale_by_tonic do |par_notes|
l_result = "neither"
# does the object contain something like tonic?
if par_notes.to_a.instance_variable_defined?(:@tonic)
# what is the type of the instance variable?
# if it is Integer, then it is a chord
if par_notes.to_a.tonic.is_a? Integer
l_result = "chord"
end
if par_notes.to_a.tonic.is_a? Symbol
l_result = "scale"
end
end
return l_result
end
# test
define :p_test do |par_notes|
print "-"*70
print par_notes
print "by class: #{f_is_chord_or_scale_by_class(par_notes)}"
print "by tonic: #{f_is_chord_or_scale_by_tonic(par_notes)}"
print
end
p_test (scale :C3, :blues_minor)
p_test (chord :C3, '7+5-9')
# Testcase "neither"
p_test (ring :C3, :A3, :G3)
# test with random scales or chords
use_random_seed 14
10.times do
if one_in 2 then
p_test (scale :C3, scale_names.choose)
else
p_test (chord :C3, chord_names.choose)
end
end
I hope, it is useful for someone else.