Cabbage Logo
Back to Cabbage Site

Cabbage AU plugin troubleshooting

Hey all, just a heads up to be careful when reading and writing audio in your .csd files if you’re going to be making AudioUnit plugins. When apps like Logic Pro find new AudioUnits, they test them several times with different audio channel configurations. When this happens, Cabbage sets the nchnls and nchnls_i settings in your .csd file internally to match the audio channel configuration of each test. Do not assume the number of audio channels available matches what you set the nchnls and nchnls_i variables to in the global section of your .csd file.

Reading and writing to more channels than are available may cause problems in your .csd that will make the AU plugin fail to validate, and the scan being done by Logic Pro may hang forever requiring the user to press the “Abort” button or use the “Force Quit” option. This will make your plugin unavailable for use in these DAWs.

Here are some tips to avoid this in your .csd files:

  • Don’t use Csound opcodes that require multiple channels like ins and outs. There might not be multiple channels available. Use opcodes like inch and outch instead.

  • Always check the nchnls_i and nchnls variables before using inch and outch to make sure the channel you want to read or write actually exists. The nchnls_i and nchnls variables are changed by Cabbage internally and their values are updated at i-time, which means they will be set correctly when used in instr definitions. If only one output channel is available, then nchnls will return 1 in your instrument. Do not write to output channel 2 if nchnls == 1.

Here is an example pass-through effect .csd that shows how to avoid reading and writing to more channels than the host DAW provides:

<Cabbage>

form caption("Untitled") size(400, 300), colour(58, 110, 182), pluginid("def1")

</Cabbage>
<CsoundSynthesizer>
<CsOptions>

--midi-device=0
--nodisplays
--nosound
-+rtmidi=null

</CsOptions>
<CsInstruments>

// sr is set by host DAW

// nchnls_i might be changed to match host DAW input channel count.
nchnls_i = 2

// nchnls might be changed to match host DAW output channel count.
nchnls = 2

ksmps = 64
0dbfs = 1


// Pass through instrument.
//
// Safely passes audio from input to output using the `inch` and `outch`
// opcodes to avoid writing to Csound channels that don't exist.
//
// Note that the `nchnls_i` and `nchnls` variables might not be the same
// as what they were set to in the global section above.
//
instr 1
    // Create an array of signals. One for each output channel.
    a_signal[] init nchnls

    // For each output channel that has a matching input channel, read
    // the host DAW input channel into the signal array.
    // 
    // Note that the `k_chnl` variable used in the `inch` opcode is
    // always less than `nchnls_i`.
    //
    k_chnl = 0
    while (k_chnl < nchnls && k_chnl < nchnls_i) do
        a_signal[k_chnl] = inch(k_chnl + 1)
        k_chnl += 1
    od

    // Output the signals to the host DAW.
    k_chnl = 0
    while (k_chnl < nchnls) do
        outch(k_chnl + 1, a_signal[k_chnl])
        k_chnl += 1
    od
endin

</CsInstruments>
<CsScore>

i1 0 z

</CsScore>
</CsoundSynthesizer>
1 Like

Nice summary Andy, thanks for posting :wink: