How to: write a soft synthesizer

category: code [glöplog]
g.: video, as in, not youtube? I don't have the original, but I could probably get ahold of it if need be.
added on the 2013-05-31 14:44:40 by ferris ferris
no youtube is totally cool. found it
googling for slides now
Ah, never uploaded the slides anywhere :) I'll do that real quick.
added on the 2013-05-31 14:55:33 by ferris ferris
btw, anyone remember what the old northern dragons talk was that went over getting started with 4k's? I think it was Pilgrimage '05 or something, but it has an awesome starting point for synth coding with more or less the same approach as mu6k's (and mine, back then) but more example code to get started with. I believe the source to sprite-o-mat helped me as well :)
added on the 2013-05-31 14:57:41 by ferris ferris
Ferris: this?
added on the 2013-05-31 15:21:34 by raizor raizor
Sharing the good stuffs. I played with this http://blargg.8bitalley.com/bl-synth/

I like the approach, for that it gives band-filtered square waves with simple, compact yet efficient code. To get other sounds than square waves out of this, you approximate things with square waves. Works great to a get a "80's chiptune" feel (actually, it's used in several 8-bits console emulators).
raizor: YES :D awesome; I never actually saw the video :)
added on the 2013-05-31 16:45:28 by ferris ferris
marmakoide: yeah, that's an awesome resource as well :)
added on the 2013-05-31 16:45:53 by ferris ferris
random ugly thing here. anybody knows where this code is from?
Code: struct T_LRC { float iL, // Spulen-Strom iC, // Kondensator-Strom uC; // Kondensator-Spannung float reso, cut; // Widerstrand, L = C }; void inline lrc(T_LRC &flt, float in ) // LRC bandpass { flt.iL += flt.cut * flt.uC; flt.iC = (in - flt.uC) * flt.reso - flt.iL; flt.uC += flt.cut * flt.iC; }

Code: amp = 1.0f; f = .025f; c1 = 1.0f; s1 = 0.0f; ... // --- ta --- sawenv = svalue; tsaw += sawfrq - (int)tsaw; flt.cut = 0.9f; flt.reso = 0.9f; lrc( flt, tsaw ); // --- bd --- amp *= 0.9997f; f *= 0.9997f; s1 += c1 * f; c1 -= s1 * f; float outfront = flt.iL*sawenv+(s1*amp);

i have that lieing around in some unfinished something. i'm sure it was some code from here. really just some ugly tiny thing.
added on the 2013-05-31 17:35:22 by yumeji yumeji
what kb_ said.
added on the 2013-05-31 23:57:39 by trc_wm trc_wm
That said, I _have_ been thinking about doing some walkthroughs like Gargaj's bass video, though; that's a format that actually makes sense. I mean, in sound design especially, I personally think it's all in the details/tweaks, but someone can follow the broad outline of what you're doing and be able to make something with their own character in no time. It's a good springboard for sure.

In all fairness, that idea is not a softsynth specific thing - plenty of good (and not-so-good) sound design tutorials on YouTube. Applying those techniques to a synth is usually relatively straightforward.
added on the 2013-06-01 00:54:33 by Gargaj Gargaj
I think I have enough hints to start learning softs! Thank you guys very much!
added on the 2013-06-01 10:29:19 by phaazon phaazon
Really helpful topic!
What is the way of generating the music? Prerender the whole thing at startup or just render blocks of samples as the demo flow?
added on the 2013-06-01 12:57:43 by kt kt
kt: I suppose pre-rendering in a 64k isn't a completely unreasonable option anymore given how fast CPUs are, but generally in 64k you generate / mix realtime. In 4k the songs are usually so short and simple (few instruments, few effects) that rendering the whole thing in memory usually only takes 10-20 seconds, but it wins you considerable space by not having to buffer your DSP effects.
added on the 2013-06-01 13:11:38 by Gargaj Gargaj
In 64k's you gen/mix realtime if your synth is fast enough, i know some people that had to just pre-render last year due to some synch bugs (don't know exactly why they had bugs though).

About 4k's.. if you pre-gen the music you only need to do one simple "render-pass" and then ask windows to play that huge sample, the amount of code is really small compared to creating a thread and keep buffers updating on the fly as the song progresses.
added on the 2013-06-02 12:42:39 by whizzter whizzter
.. or you allocate one big buffer for the whole sound track, delegate sound rendering to another thread, and just start playing the buffer hoping that the sound thread renders faster than the buffer is played back. With multicore CPUs (and you can pretty much assume everyone has one nowadays) that's actually a viable thing to do.
added on the 2013-06-02 14:42:05 by kb_ kb_
Pre-rendering very heavy synth instruments to samples if you don't change the parameters for that instrument is a one good optimization trick. Vesuri put that to good use in http://pouet.net/prod.php?which=54136
added on the 2013-06-02 14:45:44 by visy visy
kb_, that sounds pretty reasonable. But of course the API you're using must guarentee to play the sample from the memory location you've given. Do any do that?
added on the 2013-06-02 15:29:59 by revival revival
revival, waveOut does. Check the example code in the 4Klang source. :)
added on the 2013-06-02 15:34:04 by kb_ kb_
what kb_ said.

I wonder if trc_wm was looking into the future there?
Haha, that was the one API I was CERTAIN you couldn't use that way. Oh well :-) Thanks.
added on the 2013-06-02 17:51:08 by revival revival
Well, given how old the API is, they surely didn't want to create buffer copies back then. :D
yumeji: it's from the dialogos 2001 4k src by delta9 & franky, check http://www.active-web.cc/html/research/bin/4ksrc.zip
added on the 2013-06-03 10:42:49 by arm1n arm1n