List all_symbols

I am playing with :bpm
it appears it’s a known symbol (default 60)

is there a way of listing all known symbols?

(gpt lied… again!)

Sonic Pi uses symbols to represent notes, chords, scales, modes, and other musical concepts. A symbol is a name that starts with a colon, such as :c4 or :major. To get a list of all the symbols that Sonic Pi recognizes, you can use the all_symbols command, like this:

puts all_symbols

undefined local variable or method `all_symbols’ for Runtime:SonicPiLang

Haha, Chat GPT can generate some weird and erroneous stuff sometimes!

Sonic Pi’s language is based on Ruby and in Ruby any set of characters prefixed with a colon is a symbol. The following are all examples of symbols: :foo, :bar_baz, :quux1, :c3, :minor_pentatonic. Just because something is a symbol in Sonic Pi doesn’t mean that it is meaningful as a musical concept :slight_smile:

However, there are some useful functions to list some of the recognised musical symbols:

  • puts scale_names
  • puts chord_names
  • puts sample_groups
  • puts all_sample_names
  • puts synth_names
  • puts fx_names
1 Like

Thanks Sam! Will be playing with these!

Does that mean it’s not possible to get a list of all symbols like :bpm?
(I wasn’t sure if these were defined in the code somewhere specific in the github repo, if it’s not possible to evaluate / return using some RubyWax™), or if this level of detail is concealed from the user.

Perhaps it’s because it’s getting a little late at night for me but I’m unsure where :bpm is ever used as a symbol.

Do you mean the functions use_bpm or current_bpm?

These are fantastic! I just figured out the proper grammar to tick my way through all the different scales (and print them out as well). A proud moment for a newbie! I’m fascinated by the different global and historical divisions of the octave, so I’ll just put these few lines of code on a loop and listen for a few days … this is both fun and enlightening.

1 Like

Do you mean the functions use_bpm or current_bpm?

Perhaps!

I found an example where the bpm is adjustable at runtime, without stopping.

use_bpm get(:bpm)

outside the loop/block the :bpm is initialised

set :bpm, 60

  • If this isn’t initialised, the default is still set
    puts "bpm = #{get(:bpm)}" # 60
  • Also the intellisense picks this symbol up, but I now see that’s just because I’ve used the symbol previously
    set_bpm

So yes I think I may be referring to current_bpm (in a way - or a non-existent symbol!)

Thanks!

Hi @jonny,

could you point me to the example that uses set :bpm and get :bpm?

Note that neither of these will actually change the bpm. For that you need either use_bpm to set the current thread or set_link_bpm! to set the global link-based metronome.

Also, each thread/live_loop can have its own independent bpm value and that the default bpm is set to match the global link-based metronome (which also has GUI controls in the bottom right of the app window).

Hi, & well done! Have you wrapped this up in a method or class?
Am playing with ticks and counters, and curious to see how you’ve implemented, and how you’re iterating… also check out these awesome examples - may need the OP or GPT to explain exactly what’s going on here… would love to know how they came up with this too!

Credit to @amiika
Sonic-Pi/psy/psy_effect_thx.rb at master · amiika/Sonic-Pi (github.com)

Hi @jonny,

it’s very basic (I don’t yet know what a method or class is). the goal for me was simply to listen to all the scales without having to run each scale manually (which is what I did while wrestling with my tick grammar.

i ran puts scale_names and then copied it into a buffer and built around it, each time expecting an error till one time it played - i was giddy. the minute it worked, i detuned all the scales to C256 (philosophical tuning circa 1713) and then added random pan and release functions to make it sound like an unreliable and wonky old piano. Great fun!

live_loop :scales do
  trial = (ring :acem_asiran, :acem_kurdi, :acemli_rast, :aeolian, :ahirbhairav, :augmented, :augmented2, :bartok, :bayati, :bayati_2, :bayati_araban, :bestenigar, :bhairav, :blues_major, :blues_minor, :buselik, :buselik_2, :cargah, :chinese, :chromatic, :diatonic, :diminished, :diminished2, :dorian, :dugah, :dugah_2, :egyptian, :enigmatic, :evcara, :evcara_2, :evcara_3, :evcara_4, :evic, :evic_2, :ferahfeza, :ferahfeza_2, :ferahnak, :gong, :gulizar, :harmonic_major, :harmonic_minor, :hex_aeolian, :hex_dorian, :hex_major6, :hex_major7, :hex_phrygian, :hex_sus, :hicaz, :hicaz_2, :hicaz_humayun, :hicaz_humayun_2, :hicazkar, :hicazkar_2, :hindu, :hirajoshi, :hungarian_minor, :huseyni, :huseyni_2, :huzzam, :huzzam_2, :indian, :ionian, :isfahan, :isfahan_2, :iwato, :jiao, :karcigar, :kumoi, :kurdi, :kurdili_hicazkar, :kurdili_hicazkar_2, :kurdili_hicazkar_3, :kurdili_hicazkar_4, :kurdili_hicazkar_5, :leading_whole, :locrian, :locrian_major, :lydian, :lydian_minor, :mahur, :major, :major_pentatonic, :marva, :melodic_major, :melodic_minor, :melodic_minor_asc, :melodic_minor_desc, :messiaen1, :messiaen2, :messiaen3, :messiaen4, :messiaen5, :messiaen6, :messiaen7, :minor, :minor_pentatonic, :mixolydian, :muhayyer, :neapolitan_major, :neapolitan_minor, :neva, :neva_2, :nihavend, :nihavend_2, :octatonic, :pelog, :phrygian, :prometheus, :purvi, :rast, :ritusen, :romanian_minor, :saba, :scriabin, :sedaraban, :sedaraban_2, :segah, :segah_2, :sehnaz, :sehnaz_2, :sehnaz_3, :sehnaz_4, :sevkefza, :sevkefza_2, :sevkefza_3, :shang, :spanish, :sultani_yegah, :sultani_yegah_2, :super_locrian, :suzidil, :suzidil_2, :suznak, :suznak_2, :tahir, :tahir_2, :todi, :ussak, :uzzal, :uzzal_2, :whole, :whole_tone, :yegah, :yegah_2, :yu, :zhi, :zirguleli_hicaz, :zirguleli_hicaz_2, :zirguleli_suznak, :zirguleli_suznak_2, :zirguleli_suznak_3).tick
  puts trial
  play_pattern (scale :C4, trial)
  sleep 3
end

And the @amiika code you linked to? I’ll be studying that for awhile. I try to stare at the code to understand what it’s doing before running it and I got halfway through that script before my brain exploded. Lots to learn :wink:

Hi! Thanks for sharing! Lots indeed!

  • Everything is an object, or an instance of
  • Classes are the blueprints from which all objects are made
  • We are people, instances of a Person class!
  • Methods are things that can be done with/by/to things (we can think)

Is that the :C4 option you pass to the scale (method used by the play_pattern method)?

:bulb: If you’ve listed all the scale names in the trial ring variable, you can also do

live_loop :scales do
  puts "loop #{tick}, #{scale_names.look}" #look looks at tick but doesn't update it
  play_pattern (scale :C4, scale_names[look]) #play pattern from scale#0,1,2
  sleep 3
end

Venturing into music theory territory, fascinating stuff (hopefully more on this soon!)

Hi @Jonny,

Apologies for the delay. And thanks for that poetic introduction to object-oriented programming :thinking:

I’m still learning words in Ruby / Sonic Pi so I’m doing math in excel till my grammar improves. For that first run I detuned A440Hz by 37cents to flatten the C note from 261.63Hz to 256Hz.

In excel, I went further and created an equal temperament scale with C256Hz as the source and the 12th root of two to create the twelve notes leading to C512Hz.

With these I made a list to play a scale, panned all the notes hard left and then produced a set of ‘best match’ natural harmonics (also in excel) and panned those to the right so I could listen and compare.

As expected, the tonic, the fifth and the octave were the only notes that matched well. All the other notes more or less clashed with their counterparts, some different enough to make beats.

This is more about the physics of sound and teaching math & music to kids than it is about tuning standards. History is filled with attempts to create a proper scale and equal temperament has proven to be the most efficient but whole number ratios are still the strongest and most pleasing so we should never stop looking at alternatives.

For myself, I’ve got my eye (I mean ear) on Hydrogen.

Thanks!!! we’re on similar paths (although I suspect your knowledge and understanding far exceeds mine, re the math of music…

This is amazing (not SP, just re sound and temperament, and the rationale behind the ratios and their gratification)
Hopefully others will enjoy :slightly_smiling_face:

:question: Can I ask, was there significance in the 37cent reduction?
Eg why 37, how was that number/interval (or offset) found?

If you have any sheets (xlsx) or snippets (.rb) or links to projects (github etc) I’d be quite interested in seeing.

:ok_hand:

Hi again, apologies for littering the forums with stuff but wanna quickly ask before I forget

(@robin.newman you may know this)
With sp (or maybe only in sc, eg in synthdef)

~Is there a way~ how can you work with waveforms?

I’m thinking about things like masks, like XOR gates, if any of that nomenclature helps!

pseudo

 #define waves
wave1 =sine 1 
wave2 = sine 1 

#call method on wave using mask wave2 as param

wave3 = wave1.mask wave2
play wave3 #silence, as identical wave masked

Eg simple def example(s) to do things like

  • play note/pitch/ratio of a tone given a waveform type, length in time, number of cycles

This could demoed in a simple live that iterates over indexes or ticks, to make the sounds with the ratios, to play tones and hear the sound of the intervals eg (in loop or defined method called from within live_loop)

#i,j = 0
1.10 times do |I|
 1.10 times do |j|
  play ratio_to_pitch i/j , wave: wave3
 end; end

Tldr is there a good primer for sc?!
Thanks!

Hi @jonny,

Quick answer:

Cents = 1200 x log2 (freq A / freq B)

In my case I wanted to find the difference between middle C (261.6356) and the number 1 (or its octave relation, 256).

More will follow as we’ve touched on a favourite topic of mine but we should start a new thread at some point ;}

1 Like