Lovre
(Lovre Bogdanic)
#1
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
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:
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?
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.
rory
(Rory Walsh)
#3
Yes you can use m
I think:
You can check the num of args using in_count()
.
Lovre
(Lovre Bogdanic)
#4
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:
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:
instr 1
k1 = 1
k2 = 2
k3 = cooling(k1, k2)
endin
but when I make plugin without outputs:
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:
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.
rory
(Rory Walsh)
#5
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:
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.
struct MyCoolOpcode : csnd::InPlug<64> {
And in this case inargs
becomes args
.
1 Like
Lovre
(Lovre Bogdanic)
#6
Cool! many thanks @rory ! I will give it a try