How to add release time when stopping a sound

I am trying to make a simple keyboard that plays SoundFont sounds on unity.
Since Csound is new to me, I created the following as a test.

instr PlayOrStop
    kStart chnget "start"
    if changed(kStart) == 1 then
        event "i", "SoundFont", 0, -1, gkNote, gkVel
    endif
    
    kStop chnget "stop"
    if changed(kStop) == 1 then
        event "i", "SoundFont", 0, 0, gkNote, 0
    endif
endin

instr SoundFont
    mididefault     60, p3
    midinoteonkey	p4, p5
    inum	init	p4
    ivel	init	p5
    ivel	init	ivel/127	
    kamp	linsegr	1, 1, 1, 0.5, 0   ;envelope
    kamp	= kamp/3000	
    kfreq	init	1
    a1,a2	sfplay3	ivel, inum, kamp*ivel, kfreq, 0 
    outs	a1, a2
endin

When you press PlaySound, the sound is played, StopSound will stop the sound.

The problem is that when I press StopSound, the sound immediately disappears and the release time that I should have set in SoundFont does not work. (Of course, this is because the vericity is zero.)

For example, what event should I issue to make the sound release over 0.5 seconds?
Thanks in advance.

Hi @KANIYO and welcome to the forum.
Try having a look at one of the ‘r’ opcodes like:
https://csound.com/docs/manual/linenr.html
or
https://csound.com/docs/manual/linsegr.html

1 Like

Thanks for the quick answer!!!

I read the page you linked to. I am trying to avoid issuing midi events as I am planning to eventually import them into Unity (iOS). This is because I do not know how to loop back Midi events on Unity (iOS).

What I want to build is a simple piano. It should play a sound when a finger touches the keys, and the sound disappears when the finger leaves the keys.

I have already included linsegr. I have tried changing some values but it doesn’t seem to work…

kamp linsegr 1, 1, 1, 0.5, 0    ;envelope

I would be very happy if you could give me some more details.
Thanks in advance.

Hehe sorry it was late and I didn’t notice you were already using linsegr.
I think the issue lies in the event opcode, that doesn’t check for release segments.
Try this (using turnoff2):

instr PlayOrStop

    kStart, kval cabbageGetValue "start"
    insno nstrnum "SoundFont"
     
    if changed(kStart) == 1 then
        event "i", "SoundFont", 0, -1, gkNote, gkVel
    endif
    
    kStop chnget "stop"
    if changed(kStop) == 1 then
       
        turnoff2 k(insno), 0, 1
        ;event "i", "SoundFont", 0, 0, gkNote, 0
    endif
endin
1 Like

Thanks for your cooperation. But I just can’t get it to work. The sound didn’t stop.
Here is my code. What am I doing wrong …

<Cabbage>
    form caption("TITLE") size(200,200), guiMode("queue") pluginId("def1")
    button bounds(30, 20, 80, 40) channel("start") text("PlaySound")
    button bounds(30, 100, 80, 40) channel("stop") text("StopSound")
</Cabbage>
<CsoundSynthesizer>
<CsOptions>
-n -d
</CsOptions>
<CsInstruments>
sr = 44100
ksmps = 32
nchnls = 2
0dbfs  = 1

;load a soundfont
prints "------------LOAD SF--------------\n"
strset 1, "88KeysMultiTonesPiano.sf2"
isf sfload 1
sfplist isf
sfpassign 0, isf


gkNote init 60
gkVel init 100


instr PlayOrStop

    kStart, kval cabbageGetValue "start"
    insno nstrnum "SoundFont"
     
    if changed(kStart) == 1 then
        event "i", "SoundFont", 0, -1, gkNote, gkVel
    endif
    
    kStop chnget "stop"
    if changed(kStop) == 1 then
        turnoff2 k(insno), 0, 1
        ;event "i", "SoundFont", 0, 0, gkNote, 0
    endif
endin



instr SoundFont
    prints "HELLO\n" 
    mididefault	60, p3
    midinoteonkey	p4, p5
    inum	init	p4
    ivel	init	p5
    ivel	init	ivel/127					;make velocity dependen
    kamp	linsegr	1, 1, 1, 17, 0          ;envelope
    kamp	= kamp/3000						;scale amplitude
    kfreq	init	1						;do not change freq from sf
    a1,a2	sfplay3	ivel, inum, kamp*ivel, kfreq, 0	;preset index = 0
    outs	a1, a2
endin


	
</CsInstruments>
<CsScore>
f0 z
i "PlayOrStop" 0 z
</CsScore>
</CsoundSynthesizer>

Hi !

Try to add
printk2 kStop
to see how it actually behaves.

Tarmo

E, 1. mai 2023 11:06 KANIYO via The Csound Community <noreply@forum.csound.com> kirjutas:

1 Like

Inside the SoundFont instrument, the time it takes for the sound to fade out after the release is set to 17 seconds!
Try this:

;kres linsegr   starting value, duration of first segment, value after first segment, duration of release segment, ending value
kamp	linsegr	1, 1, 1, 0.3, 0          ;envelope

So here the sound starts with an amplitude of 1, after 1 second amplitude is still 1, and when released, after 0.3 seconds, amplitude is 0.

Also I noticed I made you use cabbageGetValue, which won’t work on Unity. Sorry for that, my brain is on holiday!! :man_facepalming:
Use chnget as you were doing already:

instr PlayOrStop

    kStart chnget "start"
    insno nstrnum "SoundFont"
 
    if changed(kStart) == 1 then
        event "i", "SoundFont", 0, -1, gkNote, gkVel
    endif

    kStop chnget "stop"
    if changed(kStop) == 1 then
        turnoff2 k(insno), 0, 1
    endif
endin

Another little note is about loading sf files in Unity: probably Csound won’t be able to find the file at runtime, import the Environment Vars sample from the CsoundUnity section of the Unity package manager and have a look at the SFDIR scene. You will have to place your sf file under a Resources folder, and rename it to < name of the file >.bytes

1 Like

I was able to do it! 17 seconds was clearly a mistake!
Now that the test is complete, I’m going to let this thread be complete for now, although the integration into Unity may cause problems again.

Thank you so much!

1 Like

If I use the turnoff2 method, all sounds will be lost when multiple sounds are played on the same inst.
Is there any opcode or method to release only certain notes?
Thanks in advance.

If you use fractional instrument numbers I think you can turn off just those matching the fraction.

1 Like

Thank you for your help!!
I am trying to build a keyboard with 88 keys. The sound source is SoundFont.
Sorry for my lack of understanding. Does that mean that I have to define 88 insts?

Have a look here:

Section

Using Multiple Triggering

1 Like

Hi!

Here is a snippet from one instrument that I found:

I was able to do this by using fractional instrument. Thank you very much.
I don’t know if anyone will need this, but I will leave the code.

<Cabbage>
    form caption("TITLE") size(300,200), guiMode("queue") pluginId("def1")
    button bounds(30, 20, 80, 40) channel("start1") text("Start1")
    button bounds(150, 20, 80, 40) channel("start2") text("Start2")
    button bounds(30, 100, 80, 40) channel("stop1") text("Stop1")
    button bounds(150, 100, 80, 40) channel("stop2") text("Stop2")
</Cabbage>
<CsoundSynthesizer>
<CsOptions>
-n -d
</CsOptions>
<CsInstruments>
sr = 44100
ksmps = 32
nchnls = 2
0dbfs  = 1

;load a soundfont
prints "------------LOAD SF--------------\n"
isf sfload "soundfont.sf2"
sfplist isf
sfpassign 0, isf


instr PlayOrStop    
    kpreset     init 1
    kNote1      init 60
    kNote2      init 64
    kVel        init 100
    krelease    init 0.2
 
    kStart1 chnget "start1"
    if changed(kStart1) == 1 then
        instrnum1  =         2 + i(kpreset)/100 + i(kNote1)/100000
        event "i", instrnum1, 0, -1, kNote1, kVel, krelease, kpreset
    endif

    kStart2 chnget "start2"
    if changed(kStart2) == 1 then
        instrnum2  =         2 + i(kpreset)/100 + i(kNote2)/100000 
        event "i", instrnum2, 0, -1, kNote2, kVel, krelease, kpreset
    endif


    kStop1 chnget "stop1"
    if changed(kStop1) == 1 then
        instrnum1  =         2 + i(kpreset)/100 + i(kNote1)/100000
        turnoff2 k(instrnum1), 4, 1
    endif

    kStop2 chnget "stop2"
    if changed(kStop2) == 1 then
        instrnum2  =         2 + i(kpreset)/100 + i(kNote2)/100000 
        turnoff2 k(instrnum2), 4, 1
    endif

endin


instr 2
    inum	    init	p4
    ivel	    init	p5
    irelease    init    p6
    ipreset     init    p7
    ivel	    init	ivel/127			    ;make velocity dependen
    kamp	    linsegr	1, 1, 1, irelease, 0    ;envelope
    kamp	    = kamp/3000						;scale amplitude
    kfreq	    init	1						;do not change freq from sf
    a1,a2	    sfplay3	ivel, inum, kamp*ivel, kfreq, ipreset
    outs	a1, a2
endin
	
</CsInstruments>
<CsScore>
f0 z
i "PlayOrStop" 0 z
</CsScore>
</CsoundSynthesizer>
1 Like