Advanced Synthesis - Oscillator Sync

I don’t know you need to support it explicitly (though a documentation example is always appreciated), just so long as it works. Exposing phase on all our oscillators (at ‘ar’ rate) should be sufficient.

Probably not the right week to ask you to add negative feedback to your FM oscillator then? :slight_smile:

It would be helpful to me (as the author of that quark) if you could describe the problem that you had, so that a/ if it’s a usage problem, I could help you or b/ if it’s a bug, I could fix it.

It’s the second time in the last couple weeks where I woke up to find a message like “I tried one of James’s quarks and it didn’t work,” but with no actionable details… I would like to improve the situation but to do that, I need to know:

  1. What code did you run?

  2. What actually happened?

hjh

What do you mean? I don’t understand what you want.

Sam

Like this:

1 Like

You could save some time and look at WavetablePrep in the ddwWavetableSynth quark. It probably does pretty much the same thing you’re considering (re)implementing.

hjh

Here is how you’d do Sam’s large example in ddwWavetableSynth (well, it’s not Linkwitz-Riley but you could drop that into WavetablePrep’s filters collection and use it instead):

(
var size = 2048;
var sig = Env([0, 1, -1, 0], [1, 0, 1]).asSignal(size);
var stream = SoundFileStream(sig);

~wt = WavetablePrep(wtSize: size, numMaps: 8, ratio: 2, filter: \tenPctSlope)
.readStream(stream, action: { |exception, wtObject|
	wtObject.write("~/bl-saw.wav".standardizePath);
});
)

(
s.waitForBoot {
	~wtbuf = Buffer.read(s, "~/bl-saw.wav".standardizePath);
	s.sync;
	a = {
		var freq = MouseX.kr(50, 5000, 1);
		(MultiWtOsc.ar(freq, wtPos: 0, bufnum: ~wtbuf) * 0.05).dup
	}.play;
}
);

I dunno, I thought it’s kinda convenient – would hope others get some benefit from it too.

(I haven’t checked WavetablePrep’s compatibility with the oversampling Osc – I guess it’s pretty close? That’s on my to-do list, so I could replace the non-oversampling MultiWtOsc with Sam’s UGen.)

hjh

Well, I already did that part…so too late. The part I need to make is the Oversampling Oscillator that plays the 3D wavetable.

Sam

shure, im not here to bash anyone, it just I really couldn’t make it work, the first time I tried it worked as expected, I could load a .wav through the preprocess and then read it with the wave table oscillator. But now,I dont know why it does not preprocess the .wav anymore, it gives an array of 0’s and when I try to play it, it says that there is no data in the buffer.

I tried to uninstall it and reinstall it and the behavior is the same, and that is not the biggest problem. I dont know if it has to be with my computer or what but after few times of trying to make it work all the sound from my computer start to glitch really loud and super ugly, I mean all, YouTube, the sounds of the operating system, supercollider itself. So I have to close collider to fix the audio.

Again, Im not bashing anyone, first time I tried it I liked it a lot, but now I can’t use it anymore.

The code I run is exactly the one on the helpfile but with a one cycle waveform .wav file. I also tried other one cycle waveforms and all of them did the same behavior, it just worked with a longer wav file.

In the preprocess it says the table size is 0 also. I will try to rebuild the entire project and see if it works again, I let you know if thats the case.

w = WavetablePrep("/Users/home/Downloads/WaveEdit/banks/SineShift.wav".standardizePath);

w.read(action: { "done".postln });

w.tables.size  // 256 wavetable positions

w.write("/Users/home/Downloads/WaveEdit/banks/SineShift-wt.wav");

s.boot;

b = Buffer.read(s, "/Users/home/Downloads/WaveEdit/banks/SineShift-wt.wav");

(
a = {
	var trig = Impulse.ar(10);
	(MultiWtOsc.ar(
		TExpRand.ar(50, 500, trig),
		LFDNoise3.kr(3).range(0, 254.999),
		0, 0,
		bufnum: b, numTables: 8, wtSize: 2048, ratio: 2,
		numOscs: 5, detune: 1.008
	) * 0.1).dup
}.play;
)

Thanks for your work and collaboration.

I’ll raise an issue for it on your repo.

But essentially Yamaha added a feature on later FM synths where if the feedback is negative, then it squares the value. This means that you get saw waves (for low) values of negative feedback on a sine wave, and square waves for (low) negative values on a sine wave. Musically this allows some surprisingly cool things.

https://kunstmusik.com/2017/12/20/reface-dx-style-fm-feedback-saw-square/

And all I really meant was it sounds like you already have a lot on your plate, so I’d delay raising it as an issue.

You have no idea how long I’ve wanted this. :grinning:

I see you are doing more advanced techniques than me, but I had fairly good results just by doing a swipe FFT filter:

Aliased Version with no filter:

FFT filtered version:

(
var numFrames = 1024;
var sig = Signal.newClear(numFrames);
sig = sig.collect({ |sample, index|
    2.0 * (index / numFrames) - 1.0;
});
b = Buffer.alloc(s,numFrames);
b.loadCollection(sig);
)

(
x = {
	var baseFreq, playbackRate, slave, slaveFreq, master, masterFreq, sig, chain;
	masterFreq = 200;
	slaveFreq = SinOsc.ar(0.1, -pi/2).range(masterFreq,masterFreq*20);
	master = LFPulse.ar(masterFreq);
	baseFreq = s.sampleRate / (b.numFrames);
	playbackRate = (slaveFreq) / baseFreq;
	slave = PlayBuf.ar(1, b, playbackRate, trigger: master , loop: 1) *0.3;
	chain = FFT(LocalBuf(1024), slave);
	chain = PV_BrickWall(chain, (slaveFreq/1.5)/20000);
	sig = IFFT(chain)!2;
	}.play;
)

Could you send me both wav files privately? Your usage looks ok, and I was able to do a quick working demo this morning, so I guess it must be something specific to the data being processed.

The problem I could never solve to my satisfaction is rapid sweeping through wtPos (which is a major Serum idiom) – when sweeping very fast, there’s not enough time to fade one table out and fade in the next. If you can do that, I’d be grateful.

Not gonna lie, I’m a bit disappointed that WavetablePrep is headed for the dustbin. I’m happy that my MultiWtOsc will be superseded by a proper native UGen.

hjh

that sounds a lot like phase distortion, I implemented something like that but from sine to saw:

I think it sounds quite similar, you can go from sine to square or triangle or any other by changing the env.

(
~sig = Signal.sineFill(4096, [1], [-pi/2]);
~wt = ~sig.asWavetable;
r{
	~buf = Buffer.alloc(s, 4096*2);
	s.sync;
	~buf.sendCollection(~wt);
	s.sync;
}.play(AppClock);
)

(
{
	var sig, input, width, freq;
	width = SinOsc.ar(0.2).range(0,0.5);
	freq = 40;
	input = EnvGen.ar(Env.new([-1,0,1],[width,1 - width]),Impulse.ar(freq),timeScale: 1/freq).range(-1,1);
	sig = Shaper.ar(~buf, input);
	sig = sig!2;
}.play;
)

Well, my wavetable generator uses NRT and requires BufFFT to be installed, so having one that is in the language would be great. And I don’t have any of the fancy viewer stuff you have. My library doesn’t use wavetable format either. This makes things less efficient, but easier to deal with.

The images shown take things one step further with the wavetable creation. The buffer allows morphing on the x axis and anti-aliasing on the y axis.

The final version I envision would play back directly from the stored FFT buffer, allowing spectral manipulation without any latency. I can’t tell how difficult that will be yet.

Sam

Phase Distortion is a little different. I like phase distortion, it’s a shame that snobbery (it was a Casio thing) seems to have rendered it to the dustbin of history.

Sounds like reusing James code for generation might be a good idea then.

The FFT thing is interesting. I’ve never really considered doing something like that before. I feel that it would give you different results, but probably something pretty interesting.

Ah ok, thanks – if it needs any adjustments to provide the right data format for your plugin, let me know – a really solid wavetable solution would be great to have in SC. Really appreciate your work on the oversampling oscillators – definitely something I wanted for a good long while.

hjh

You were right!, it worked with the code you provided, now I have to see which program allows to create arbitrary wavetables with a given number of samples, does anyone recommends one for Mac?.

Thanks @jamshark70

The only one I know of is this:

These instructions from Surge may also be useful:

If you work out a good method then you should share it here…

1 Like