# Csound opcode with arbitrary number of input arguments

**URL:** <https://forum.csound.com/t/csound-opcode-with-arbitrary-number-of-input-arguments/1575>\
**Category:** Developers\
**Created:** [March 8, 2024, 1:15pm UTC](https://forum.csound.com/t/csound-opcode-with-arbitrary-number-of-input-arguments/1575 "2024-03-08T13:15:36Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Lovre](https://forum.csound.com/letter_avatar_proxy/v4/letter/l/bbce88/32.png) [@Lovre](https://forum.csound.com/u/Lovre)\
**Post date:** [March 8, 2024, 1:15pm UTC](https://forum.csound.com/t/csound-opcode-with-arbitrary-number-of-input-arguments/1575/1 "2024-03-08T13:15:37Z")

</div>

Hello dear Csounders!

Is it possible to register a csound opcode with an arbitrary number of input arguments?

So that an opcode can be called with one, two or more e.g. a-values:

- my\_cool\_opcode(av1)
- my\_cool\_opcode(av1, av2)
- my\_cool\_opcode(av1, av2 …. av10)

I guess one way would be something like

```csound
void csnd::on_load(Csound *csound) {
  csnd::plugin<MyCoolOpcode>(csound, "my_cool_opcode.a", , "a", csnd::thread::a);
  csnd::plugin<MyCoolOpcode>(csound, "my_cool_opcode.aa", , "aa", csnd::thread::a);
  csnd::plugin<MyCoolOpcode>(csound, "my_cool_opcode.aaa", , "aaa", csnd::thread::a);
  ...  
  csnd::plugin<MyCoolOpcode>(csound, "my_cool_opcode.aaaaaaaaaa", , "aaaaaaaaaa", csnd::thread::a);
}

```

but this would then mean that I also need to make x-different constructors, something like:

```csound
struct MyCoolOpcode : csnd::Plugin<0, 1> {}
struct MyCoolOpcode : csnd::Plugin<0, 2> {}
struct MyCoolOpcode : csnd::Plugin<0, 3> {}
...
struct MyCoolOpcode : csnd::Plugin<0, 10> {}

```

Is there a more elegant way to do this?

---

<div class="post-metadata">

**Author:** ![Philipp](https://forum.csound.com/letter_avatar_proxy/v4/letter/p/46a35a/32.png) [@Philipp](https://forum.csound.com/u/Philipp)\
**Post date:** [March 8, 2024, 1:29pm UTC](https://forum.csound.com/t/csound-opcode-with-arbitrary-number-of-input-arguments/1575/2 "2024-03-08T13:29:48Z")

</div>

I can’t really help you. But maybe check the code of the linseg opcode out, which can take an arbitrary number of input arguments.

---

<div class="post-metadata">

**Author:** ![rory](https://forum.csound.com/user_avatar/forum.csound.com/rory/32/7_2.png) [@rory](https://forum.csound.com/u/rory)\
**Post date:** [March 8, 2024, 2:07pm UTC](https://forum.csound.com/t/csound-opcode-with-arbitrary-number-of-input-arguments/1575/3 "2024-03-08T14:07:41Z")

</div>

Yes you can use `m` I think:

> <https://github.com/csound/csound/blob/a1580f9cdf331c35dceb486f4231871ce0b00266/Engine/entry1.c#L34-L66>

You can check the num of args using `in_count()`.

---

<div class="post-metadata">

**Author:** ![Lovre](https://forum.csound.com/letter_avatar_proxy/v4/letter/l/bbce88/32.png) [@Lovre](https://forum.csound.com/u/Lovre)\
**Post date:** [March 9, 2024, 6:06am UTC](https://forum.csound.com/t/csound-opcode-with-arbitrary-number-of-input-arguments/1575/4 "2024-03-09T06:06:53Z")

</div>

Hi @Philipp and @rory! That is exactly what I was looking for! I think that _N_ is the best type for me since I’m interested in any count/rate i,k,a,S.

But check this out…

If I make following plugin:

```csound
struct MyCoolOpcode : csnd::Plugin<1, 'N'> {

    int kperf() {
        int numInputs = in_count();
        for(int i = 0; i < numInputs; i++) {
            std::string input_value ="kperf: input:" + std::to_string(inargs[i]);
            csound->message(input_value);
        }
        return OK;
    }

};

#include <modload.h>

void csnd::on_load(Csound *csound) {
    csnd::plugin<MyCoolOpcode>(csound, "cooling.N", "k", "N", csnd::thread::k);
}

```

I can use it as expected in an instrument:

```csound
instr 1
    k1 = 1
    k2 = 2
    k3 = cooling(k1, k2)
endin

```

but when I make plugin without outputs:

```csound
struct MyCoolOpcode : csnd::Plugin<0, 'N'> {

    int kperf() {
        int numInputs = in_count();
        for(int i = 0; i < numInputs; i++) {
            std::string input_value ="kperf: input:" + std::to_string(inargs[i]);
            csound->message(input_value);
        }
        return OK;
    }

};

#include <modload.h>

void csnd::on_load(Csound *csound) {
    csnd::plugin<MyCoolOpcode>(csound, "cooling.N", "", "N", csnd::thread::k);
}

```

And use it in similar way:

```csound
instr 1
    k1 = 1
    k2 = 2
    cooling(k1, k2)
endin

```

I get → **csound command: Segmentation violation** when accessing second input argument.

Any ideas what is wrong here? I am using Csound 6.18 on Windows 11.

---

<div class="post-metadata">

**Author:** ![rory](https://forum.csound.com/user_avatar/forum.csound.com/rory/32/7_2.png) [@rory](https://forum.csound.com/u/rory)\
**Post date:** [March 9, 2024, 9:55am UTC](https://forum.csound.com/t/csound-opcode-with-arbitrary-number-of-input-arguments/1575/5 "2024-03-09T09:55:21Z")

</div>

No, in this case you must define the max number of inputs you need, even if you have no intention of ever using that many. Something like:

```csound
struct MyCoolOpcode : csnd::Plugin<0,64> {

```

Also, if you are building an opcode with no outputs there is a special `csnd::InPlug` struct you should use.

```csound
struct MyCoolOpcode : csnd::InPlug<64> {

```

And in this case `inargs` becomes `args`. 👍

---

<div class="post-metadata">

**Author:** ![Lovre](https://forum.csound.com/letter_avatar_proxy/v4/letter/l/bbce88/32.png) [@Lovre](https://forum.csound.com/u/Lovre)\
**Post date:** [March 9, 2024, 9:57am UTC](https://forum.csound.com/t/csound-opcode-with-arbitrary-number-of-input-arguments/1575/6 "2024-03-09T09:57:10Z")

</div>

Cool! many thanks @rory ! I will give it a try 🤞
