What is the expected behavior for fout?

Hi,

I’m brand new to Csound, so I’m probably misunderstanding the fout opcode.

I expected fout to record the output of an instrument for an entire score, but I don’t quite understand what its doing.

In this first example, there are four 1/4 notes. the output of fout (foutStem.wav) contains only the last event in the score (400hz pitch). The main output is 4 notes as expected.

<CsoundSynthesizer>
<CsOptions>
</CsOptions>
; ==============================================
<CsInstruments>

sr	=	96000
ksmps	=	1
nchnls	=	1
0dbfs	=	1

instr 1
    aEnv adsr 0.01, 0.2, 0, 0, 0
    aVco poscil 0.5, p4
    aVca = aVco * aEnv
    fout "foutStem.wav", -1, aVca
    outs aVca
endin

</CsInstruments>
; ==============================================
<CsScore>
i 1 0.00 0.3 100
i 1 0.50 0.3 200
i 1 1.00 0.3 300
i 1 1.50 0.3 400
e
</CsScore>
</CsoundSynthesizer>


In this second example, there are four 1/8 notes. This time the output of fout is all four pitches,
but they are distorted and not occurring at the right time. The main output is as expected.

<CsoundSynthesizer>
<CsOptions>
</CsOptions>
; ==============================================
<CsInstruments>

sr	=	96000
ksmps	=	1
nchnls	=	1
0dbfs	=	1

instr 1
    aEnv adsr 0.01, 0.2, 0, 0, 0
    aVco poscil 0.5, p4
    aVca = aVco * aEnv
    fout "foutStem.wav", -1, aVca
    outs aVca
endin

</CsInstruments>
; ==============================================
<CsScore>
i 1 0.00 0.3 100
i 1 0.25 0.3 200
i 1 0.50 0.3 300
i 1 0.75 0.3 400
e
</CsScore>
</CsoundSynthesizer>

Due to the different results, I’m having a hard time hacking an understanding here.

There is a sentence in the docs (fout):

Notice that, unlike out, outs and outq, fout does not zero the audio variable so you must zero it after calling it. If polyphony is to be used, you can use vincr and clear opcodes for this task.

But I don’t understand what it means to “zero” it. I’m not sure if that is the cause of my problem but it could be?

hi -

it makes sense to me that the first example only records the last event,
because all previous calls to fout are overwritten by the last one.

what you want to do (= record the whole performance) needs another
architecture of the program: you need another instrument which collects
all the audio signals which you write to the output. (one instrument
which you call several times cannot do it; you need one instrument which
runs all the time.)

i think the most simple solution is to use the monitor opcode in this
always running instrument. you can find an example code here:

(by the way:the line “gaSig init 0” in Example_06A03.csd is not
necessary; i think it is a leftover from a previous version.)

best -
joachim

Hi @joachim, thanks for your repsonse.

If the expected behaviour of fout is to record the last event, then my second example suggests a bug somewhere? I’ll dig a bit deeper.

I thought monitor was only used to record the main output of Csound? Based on the docs, it does not look like I can pass it a specific instrument.

My goal is to record “stems” of each instrument for the entirety of a score. Maybe I can take your suggestion and send an instrument to a bus, and use fout to record the output of the bus.

Thanks to your suggestion, I was able to combine fout with the signal flow opcodes to record the output of an instrument.

I can now use this pattern to record the output of individual instruments.

Thanks for your help @joachim

<CsoundSynthesizer>
<CsOptions>
</CsOptions>
; ==============================================
<CsInstruments>

sr	=	96000
ksmps	=	1
nchnls	=	1
0dbfs	=	1

connect "sine", "sine_out", "bus_1", "bus_in"
alwayson "bus_1"

instr sine
    aEnv adsr 0.01, 0.2, 0, 0, 0
    aVco poscil 0.5, p4
    aVca = aVco * aEnv
    outleta "sine_out", aVca
endin

instr bus_1
    abus_in inleta "bus_in"
    fout "fout_stem_bus_1.wav", -1, abus_in
    outs abus_in
endin

</CsInstruments>
; ==============================================
<CsScore>
i 1 0.00 0.3 100
i 1 0.25 0.3 200
i 1 0.50 0.3 300
i 1 0.75 0.3 400
e
</CsScore>
</CsoundSynthesizer>

great — glad it helped.
yes this looks like a good solution.
other options would be to use a global variable, or the chn opcodes.
best -
joachim