Issue when trying to create a sinewave from scratch

Hello,

I’m trying to only work with mathematical functions (no f-table / oscillator / enveloppe opcodes) so that everything becomes clearer and unified in my .csds and my mind.

I managed to create a sinewave with minimal code (having an abscissa being incremented every 1/sr sample and sending it trough an oscillating mathematical function),
but whenever I try to control the oscillation frequency there are jumps in the curve, the sinewave looks very unstable.

My tentative might be oversimplified and I don’t know how to solve that issue. I read the physical modelling chapter in the Floss manual but I like the idea of using a mathematical function w abscissa and ordinate.
Does anyone know what should be changed ? Thanks a lot !
Here is the .csd :
essaisine.csd (720 Bytes)

Did you get this worked out? I just posted this to your deleted post as I thought it was this post you had deleted :rofl:

ksmps = 1

instr 1
    iPI = 3.14159265359
    kIndex init 0
    iFreq = 300
    aOut = sin((iFreq*iPI*2*kIndex)/sr)
    outs aOut, aOut
    kIndex+=1
endin

The first one was not understandable enough :sneezing_face:
Thank you for your response. I tried your suggestion and the jumps in the curve still happen (with the frequency being modulated in k-time by rspline or transeg or whatever else) … Have not found a solution yet, still looking for it !
(.csd bellow)

sr = 192000 
ksmps =	1
nchnls = 2
0dbfs =	1

instr 1

	ipi = 3.14159265359
	kdx init 0
	kfrq = 440 * rspline(0.5, 2, 0.5, 2)
	aout = sin((kfrq * ipi * 2 * kdx) / sr) * 0.125
	outs(aout, aout)
	kdx += 1

endin

This crude oscillator won’t work like that because the input to the sin opcode jumps whenever we change the frequency, which causes a discontinuity in the signal. We should make it continuous instead, or at least that’s my understanding (I’m by no means a DSP guy). The following will work:

<CsoundSynthesizer>
<CsOptions>
</CsOptions>
<CsInstruments>
ksmps =	1
nchnls = 2
0dbfs =	1

instr 1
	iPi = 3.14159265359
	kPhi init 0
	kFreq = 440 * rspline(0.5, 2, 0.5, 2)
	kPhi += (2 * iPi * kFreq * (1/sr))
	aout = sin(kPhi)	
	outs(aout, aout)
endin

</CsInstruments>
<CsScore>
i 1 0 6
</CsScore>
</CsoundSynthesizer>

So instead of

out = sin(2 * \pi * freq * time)

it becomes:

out = sin(\phi)\\ \phi = \phi + (2*freq*(1/sr))

I’m not sure I’ve correctly represented in the code correctly in my second equation; I’m not a math guy either :rofl:

The easiest and most efficient approach would be to write to a table and then read through the table at a the right speed, or sample increment. So you’d basically roll your own table lookup oscillator. The efficiency of this approach is why almost all computer music language use lookup tables, than continuously call the sin function on each sample. The other downside with the approach above is you must set ksmps to 1, which makes things even less efficient.

It indeed works, thanks a lot for your time and clear explanation !
I’m used to setting ksmps to 1 since I’m working a lot on granular synthesis. It appears I’m very much into inefficient and overcomplicated things :thinking:

I don’t see why granular synthesis needs to have ksmps set to 1?

Because I use metro in a master instr that triggers a grain at high frequency, and I shape the grain and the granular cloud in the master instr with arrays so that I can create patterns/trains etc. I tried increasing ksmps and it instantly sounded very bad

but why? do you use a k-rate envelope for the grains?

Yes because I use metro to trigger schedulek which only accepts k variables…
Here is an example I just made :
granulation_test.csd (1.3 KB)

I see. You’re generating the grains yourself. Have you considered using one of the built-in grain opcodes? They are far more efficient that doing it from the ground up. They range from simple: grain, to sublime: partikkel.

I’ve actually been inspired by partikkel to make my own version because I felt limited ! But partikkel is indeed sublime

i had a look at your code but to be honest, i don’t understand what you
are doing.
i tried with ksmps=1 and ksmps=64, and i can confirm that it is a big
difference.
but the reasons are anywhere hidden in your code; it is not about
performing grains yourself.

just one comment:

	kamp[kx] = 0.125
	kfrq[kx] = 55 * (kx * 2 + 1)
	kpan[kx] = 0.5

what is the sense to set all array values to one number? you could use
the number instead. the only variable here is kx. for kx=8, you will
have 55*17 grain triggers per second — do you really want this?

best -
joachim

The idea was to be able to choose the number of grains in a “train” (to have the possibility to have 64 grains in a train if I want to - why would i ?..).
I used to use the index instead but I didn’ t like having to repeat lines. I also did this in order to create clouds more than timbres (then with way lower frequencies), and I like having some relation between the grains in a single train (with the incrementation, with “kx”).
I’m learning Csound by myself then I’m sure I’m making many mistakes ! Thanks a lot for your comment, I never have any feedback so it’s very helpful

yes sure — there is no learning without mistakes, and in particular
for a programming language.

i like to give feedback, and to help, if possible. it is only that i
cannot help for something i don’t understand. but i am sure you will
bring it to work. if you need any model for self-made grains you may
look here (if you did not know already):

j

1 Like