Understanding the scope

Hi there!
Just starting with sonic-pi and planning to use it to teach programming to secondary students. I find the scopes (specially the mono and stereo ones) a useful tool when it comes to explaining how sound waves and synths work but, unfortunately, I’m missing some things. I know it’s meant to be just an assisting and decoration tool but I’d be most grateful if someone could tell me how it works. If I just run “play 60” I can clearly see the sine wave, but the frequency i see doesnt match the midi note’s frequency. Im assumming there’s some kind of aliassing? Maybe designed on purpose? I guess what I need is to know the sample frequency it’s using and the length of the scope (the buffer) in seconds?
Has anyone done some research on this? Thanks!

1 Like

What do you mean by “the frequency i see”? Which visualization do you use, and how do you read out frequencies from it?

Hi Martin,
The scope im using is the “mono” one (but also expandable to “stereo”). By “the freq im seeing” I mean the visual count of positive peaks in one second (i do 10 s and then divide) in a certain time/point of the scope x axis.
If I do “play 60” (default beep synth) i should be seeing (counting) 261,63 peaks (freq of C4) in one second, which is quite far from the about 4 peaks i count in one second. If I do “play 70” te peaks are closer to each other but the “motion” of the wave changes its direction. That’s why im assuming some kind of aliassing.
It’s quite close to the representation of a tenth of a second of the wave. In this case the motion should be ignored, as it could be caused by the not multiple buffer size. That’s my best explanation.
I just want to know what the scope represents. But i get it’s not its purpose.
Thanks for your interest!

Not really sure if it is possible to read out frequencies this way. As you already registered, “motion” may change direction, which shows that the visual appearance depends on the draw rate of the oscillogram (or refresh rate of your screen). This is like the stroboscope for calibrating turntables, or like a truck’s wheel on the highway appearing to spin backwards.

Here is a small piece of code that shows this effect. For me, there is a “standing wave” at 43 Hz (and any whole-numbered multiple thereof). Admittedly, I would have expected 60 Hz.

# calculate midi note from frequency
define :to_note do |f|
  12 * Math.log(f / 440.0, 2) + 69

with_synth :sine do
  for f in range(40, 50)
    note = to_note(f)
    puts "Note: #{note}, frequency: #{f}"
    play note, sustain: 1, release: 0
    sleep 1

So, I think what is happening here is that you don’t see all peaks, due to the stroboscope-like effect. I.e. you probably miss most of them as they fall into the “dark periods”.

EDIT: Interestingly, I get the most distinct peak in the spectrogram for the same frequency…

1 Like

Browsing the code for the visuals on GitHub (file app/gui/qt/widgets/visualizer.cpp), I now also understand the 43 Hz. It is not really related to the repaint frequency, but to the buffer size used for the oscilloscope, which is 4096 samples (see line 28).

This gives an oscilloscope width of 4096 / 44100 = 0.09287... sec (44100 is the default sampling rate). That fits almost perfectly the 4 periods visible for the 43 Hz stationary wave.

So the exact frequencies for stationary waves are x * 1 / 0.09287..., so e.g. 43.0664… Hz for x = 4.

1 Like

Now that’s a scientific approach!

Not so far from the tenth of a second I suspected. This answer is all i wanted to know. You’re my hero. Thanks!


Hi, I wrote that visualization code. I think @mlange hit the nail on the head. The code he points at is the bit that does the drawing (and will stretch the waveform to the size of the window). The place where the sound wave and FFT are generated is here:
sonic-pi/scope.cpp at main · sonic-pi-net/sonic-pi (github.com)

1 Like