Simple Idea: Sweep through Overtone/Harmonic Series

Pretty obvious, still fun. A sweep through the harmonic/overtone series.

i=1.0
partials=32
dura=0.06
pdamp=0.8
use_synth :sine
use_synth_defaults attack: 0.05, sustain: 1
fund=60

with_fx :reverb, room: 8, damp: 0 do
  partials.times do
    freq=hz_to_midi fund*i
    play freq, amp: 1/(i*pdamp), release: (partials-i+1)*dura
    i+=1
    sleep dura
  end
end

Though exceedingly simple, perhaps, I feel that this kind of thing can help learners “appropriate sound”. Sure, there are plenty of YouTube videos about the overtone series. With a bit of code, it makes it easier for learners to try things on their own, tweaking a parameter here and there. For instance, it can be switched to an “undertone sweep” by changing freq=hz_to_midi fund*i to freq=hz_to_midi fund/i. Again, really simple. And kinda fun.

Of course, it’s also a neat way to learn some simple coding ideas.

For context…
Was exploring the overtone series because of George Russell’s “Lydian Chromatic Concept of Tonal Organization” (LCCTO). While discovering that it’s more of a pseudoscientific theory than I had thought, I got to think about that 11th overtone and the relationship between the overtone series and tuning systems.

Reminded me of the bit of training I had in acoustics and psychoacoustics in the late 80s and early 90s. At the time, Csound tended to be what instructors used to create example files. We also used some pretty sophisticated (and then-expensive) equipment like Brüel & Kjær instruments (that was probably long before Hainbach started collecting them). Decades later, I’m still not that good with Csound… and I don’t have Hainbach’s budget or patience for this kind of thing. So, simple Sonic Pi scripts will have to do.

And the result is pretty neat, to my ear.

One thing I’ll probably do with this is use samples from those experiments in other contexts, say with granular synthesis tools on my iPad.

Something I wish I knew how to do is to “autosample” in Sonic Pi. Basically, write samples directly from the script. I’m sure it’s doable and probably fairly easy. Perhaps even easier on the command-line. Then, it’d be easier (and more precise) than trimming the audio recordings.

This whole period of isolation is as good a time as any to play with this geeky stuff.

4 Likes

Nice. I think you mean room: 0.8 not room: 8 above. 8 is out of permissible range.

If you want a sample, just use the record button, run the code, save the .wav, then do
any clean up in the DAW of your choice. Or am I missing something? I usually am.

Eli…

Either that, or :gverb instead of :reverb, room: 8 would be valid for :gverb.

1 Like

Hi @enkerli,

very, very nice! Overtones, especially in a row, do have a very distinct magic.

As to your “autosample”: I don’t know exactly what you are aiming at, but my different experiments to create a live looper for Sonic Pi (e. g. here and here - very old and ugly code!) somehow seem to go into this direction. I meant to record external (e. g. another musician) and internal sound (meaning: route SP sound back into SP); this is then immediatelly available as a sample within SP.

In addition to that I couldn’t resist to start turning your code into a little ‘overtone sequencer’ as I had already a sequencer sketch written down. The idea is, that you fill an array (or more precisely: a ring) as a kind of buffer with notes (in this case: overtones), which you can then play in different modes; right now the mode is just the direction of notes (up, down, up and down, reverse, random). I used a similar script to create a simple midi sequencer for my Make Noise 0-coast to play with…

You can tweak the parameters while playing (which is the main idea, of course), but it is just a very rough sketch and a quick test shows: it is buggy (also I did not manage yet to incorporate your dynamic use of amp and release) … but you will get the idea:

set :partials, 32
set :dura, 0.075
set :pdamp, 0.5
set :fund, 60
set :mode, "mirror" # default, "reverse", "mirror", random

use_synth :sine
use_synth_defaults attack: 0.05, sustain: 1

overtones = []

defonce :init do
  set(:overtones, (ring :r))
end

live_loop :build_overtones do
  get(:partials).times do
    sleep get(:dura)
    cnt = (tick % get(:partials)) + 1 # we need 1-based indexing
    freq = hz_to_midi(get(:fund) * cnt)
    if overtones.size < get(:partials)
      overtones.push(freq)
    end
  end
  set(:overtones, overtones.ring)
  sleep get(:dura) * get(:partials)
  overtones = []
end

# play_overtones
live_loop :play_overtones do
  p = get(:partials)
  cnt = (tick % p) + 1
  #use_synth_defaults amp: 1/(get(:pdamp) * cnt), release: (p - cnt + 1) * get(:dura)
  case get(:mode)
  when "reverse"
    play get(:overtones).reverse.look
  when "mirror"
    play get(:overtones).mirror.look
  when "random"
    play get(:overtones).shuffle.look
  else
    play get(:overtones).look
  end
  sleep get(:dura)
end
1 Like