Alternative sine-wave oscillator object

Status
Not open for further replies.

MarkT

Well-known member
Following this paper: https://ccrma.stanford.edu/~jos/pdf/GordonAndSmith86.pdf

I've created a sine wave generator that should perform as well as the AudioSynthWaveformSineHires object without
nearly so much computation, basically 2 muls-rshifts and 2 add/subs per sample. Perhaps a candidate to replace the
inefficient AudioSynthWaveformSineHires class?

https://github.com/MarkTillotson/Audio/blob/coupled_form_resonator/synth_coupled_resonator.cpp
https://github.com/MarkTillotson/Audio/blob/coupled_form_resonator/synth_coupled_resonator.h

Seems to perform OK, I've made the frequency() setting function phase-continuous, and I think I've tweaked it so overflow
never happens (some of these iterative methods can go slightly above the nominal amplitude at times at the extremes of
frequency).

I did a fair bit of modelling in Python for this and another (single multiply) iteration, and this performed better at low
frequencies.
 
This is very cool. So you are versed in python and cpp? Your code is amazingly easy to read, good job.

Can I ask: what might you be able to do with this? I'm trying to gain the cpp skills to build this for the teensy, it looks like you might have the skills to do it in an afternoon :)
 

Attachments

  • jupyternotebook-plot1.zip
    282.7 KB · Views: 93
This is very cool. So you are versed in python and cpp? Your code is amazingly easy to read, good job.
Among others, yes - I try to make code clear so I can understand it down the line - visual formatting is everything for
code clarity and for spotting bugs by eye - lots of whitespace always!
Can I ask: what might you be able to do with this? I'm trying to gain the cpp skills to build this for the teensy, it looks like you might have the skills to do it in an afternoon :)
Not sure what you mean - there's an image and a wav file there, not a user of JupyterNB myself.
 
OK, let's try this.
Code:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.image import imread
import sounddevice as sd
from scipy.signal import correlate
import noise

terrainsize = 256

#load terrain from 256x256 or 512x512 png
zvalues = imread('terrain256.png')

#terrain is perlin noise
#perlin noise generator coeffs

freq=1400
octaves=33

for y in range(terrainsize):
            for x in range(terrainsize):
                zvalues[x][y] = int(noise.snoise2(x / freq, y / freq, octaves) * 32767)

sps = 44100                #sample rate
duration_s = 1#0.0029            #duration of our waveform. .0029 at 44.1k makes 128 entry buffer. Set long as needed
each_sample_number = np.arange(duration_s * sps)

scale_x = terrainsize / 13.1  #this scales the orbit x size
scale_y = terrainsize / 8.1  #scale orbit y size. Changing these vales changes orbit from circular to ellipse

offset_x = 140                 #center of orbit offset x terrain axis
offset_y = 120                 #center of orbit offset y terrain axis

freq_hz = 108.0            #osc freq    
fm=1.00
                              # for this demo, moving these values will aptly demonstrate the wave terrain.
def wavetable(_size): ##122uS per loop on my machine to make geometry calculations on 2900uS buffer frame of audio
    wavex = np.sin(2 * np.pi * each_sample_number * freq_hz * fm / sps)
    wavey = np.cos(2 * np.pi * each_sample_number * freq_hz * fm / sps)
    tablex = np.int16(offset_x + (wavex * scale_x))
    tabley = np.int16(offset_y + (wavey * scale_y))
    ctablex = np.clip(tablex,0,terrainsize-1)  #clipping to terrainsize takes as long as making the tables
    ctabley = np.clip(tabley,0,terrainsize-1)  
    ctablez = [x for x in range(_size)]
    for v in range(0,_size):
        ctablez[v] = zvalues[ctablex[v],ctabley[v]]

    ctablez = np.int16(ctablez)    
    return ctablez

That's code for a wave terrain oscillator. The wav file is the result of playing back a Perlin noise terrain. It uses two oscillators in quadrature to generate an x,y coordinate to read magnitude from a table. This version uses a 256x256 table for 16 bit use. but a terrain oscillator with 65536 x 65536, tracking a plane of coordinates from -(2,147,483,648) to + (2,147,483,647) would give you very good lfo accuracy. Of course, the great thing about it is it makes an excellent oscillator in general. Maybe I'll try to hack your code. I just need to be able to read a 256x256 array, not as easy in c as in python. Nothing is as easy in c as it is in python :)
 
OK, let's try this.
...

That's code for a wave terrain oscillator. The wav file is the result of playing back a Perlin noise terrain. It uses two oscillators in quadrature to generate an x,y coordinate to read magnitude from a table. This version uses a 256x256 table for 16 bit use. but a terrain oscillator with 65536 x 65536, tracking a plane of coordinates from -(2,147,483,648) to + (2,147,483,647) would give you very good lfo accuracy. Of course, the great thing about it is it makes an excellent oscillator in general. Maybe I'll try to hack your code. I just need to be able to read a 256x256 array, not as easy in c as in python. Nothing is as easy in c as it is in python :)

Had a quick play with this - it needs interpolation between samples to prevent aliasing for low frequencies I think
- it had the jaggies at 108Hz due to the small orbit size. In other words the map should be bilinearly interpolated
or similar (you'd get that for free in a renderer implementation!). C arrays are just as easy to read as Python surely
- so easy you can read off the end of them even!

I was actually thinking of doing an explicit quadrature oscillator object for the Audio lib as it happens. I found another good
paper on recursive oscillators too, http://www.claysturner.com/dsp/2nd_OSC_paper.pdf
 
That will be perfect for building an am radio transceiver in the audio object. Very cool, thanks.

This reminds me: we need a half wave detector as well. The full wave rectifier is not suited as a detector.
 
And here it is!

And I've been looking at the output on my spectrum analyzer today, couldn't see any issues and the main peak has
perhaps a trace of phase noise close-in:
quadrature_oscillator_10k.png

The frequency span is 200Hz, tone at 10kHz
 
Status
Not open for further replies.
Back
Top