rorywalsh / CsoundUnity

GNU Lesser General Public License v2.1
70 stars 19 forks source link

Pass arrays to channels? #21

Closed Despair-Bear closed 3 years ago

Despair-Bear commented 3 years ago

Hey there. Was just curious, am currently trying to pass an array of strings to a csound string channel from Unity and was curious if this is possible? I see that there are chnget and chnset opcodes that support arrays but don't see anything in the Csound6.NativeMethods portion of the code. Was curious if this is currently possible or if there is a way to simply pass each individual element and reliably update on the csounds side. Was attempting to check if an S variable had changed and if it had to add the new value to an array on the csound side, but this is proving more difficult than I had as anticipated. Not sure if the changed opcode is very reliable for strings and can't find much information online. Any insight you have would be greatly appreciated. Thanks!

giovannibedetti commented 3 years ago

Hi. Right now there's no way to pass an array of strings, so you should use a different string channel for each string of your array. This feature should be available in Csound7, and it will be then added in CsoundUnity. Regarding the changed opcode, it should work as long as your strings to check are k rate vars. If you have issues with that, post your code here so that we can have a look. Out of curiosity, are you using the new develop branch imported via Unity Package Manager?

Despair-Bear commented 3 years ago

I'm using the package version 2.3 for windows from the releases page.

I noticed that the chnset method within csounds which allows you to pass in arrays instead of a single string/value pair also seems to throw a syntax error, is this also something that is currently not included in the package and will be updated with Csound7?

Thanks very much for the response. Being able to use csound within Unity so easily has been fantastic.

EDIT: So I'm attempting to call chnset when looping through an array and set the values as I'm assuming that the array args for chnset will be in Csound 7. For context I'm sending output from oscili to a channel on a separate fx processing instruments. Running into a strange issue when I'm trying to do this though for some reason this code works:

chnset aout[0], Sc[0]
chnset aout[1], Sc[1]

But this code does not:

kInd = 0
while kInd <= 1 do
    ;printks Sc[kInd], 1
    chnset aout[kInd], Sc[kInd]
    kInd += 1
od

Any insight/thoughts greatly appreciated

giovannibedetti commented 3 years ago

I'm not sure which version of Csound is used in that version, it's from 2017! Indeed I found that the array version of chnset has already been added in Csound 6.14 by @rorywalsh, so let's ask him if he has more info than me! Btw if you are on Unity >2018.2 I suggest you to try the newest package:

Open the PackageManager, press +, Add package from git URL, and paste https://github.com/rorywalsh/CsoundUnity.git#develop

Lots of new features, and it's updated to Csound 6.15! It's been a while since we're working on it, but still we didn't find the time to publish it. It works on Windows, MacOs, and Android 64bit (also on Oculus Quest)!

Despair-Bear commented 3 years ago

Hmm... when I go to add via the package manager I receive the following error

Cannot perform upm operation: Unable to add package [https://github.com/rorywalsh/CsoundUnity#develop]:
  Package name 'https://github.com/rorywalsh/CsoundUnity#develop' is invalid. [InvalidParameter]
UnityEditor.EditorApplication:Internal_CallUpdateFunctions()

Running Unity 2019.4.9f1 on Windows

giovannibedetti commented 3 years ago

sorry wrong link, try this: https://github.com/rorywalsh/CsoundUnity.git#develop

rorywalsh commented 3 years ago

Hi @Despair-Bear Right now the array version version just wraps the regular versions of the channel opcodes. There is no way to pass arrays to and from host software. But you have some options all the same. Numeric arrays can be obviously be passed back and forth by way of function tables.

Strings arrays can be passed as a delimited strings. You could easily write a string to array UDO. I wrote an opcode to do this, but it would probably be best to avoid the need to load external opcodes and simply write it in Csound. In fact, @joachimheintz has published one here that you could use.

Regarding the trouble you're having with the array version of chnget, you need to use i/k/S after the chnget/chnset name. Check out the example file here. It should give you a little more info than the manual help file. It was not possible to override teh existing opcodes, hence the need to give them unique names, as shown here.

Despair-Bear commented 3 years ago

sorry wrong link, try this: https://github.com/rorywalsh/CsoundUnity.git#develop

Excellent, thank you that worked :D

Despair-Bear commented 3 years ago

Hi @Despair-Bear Right now the array version version just wraps the regular versions of the channel opcodes. There is no way to pass arrays to and from host software. But you have some options all the same. Numeric arrays can be obviously be passed back and forth by way of function tables.

Strings arrays can be passed as a delimited strings. You could easily write a string to array UDO. I wrote an opcode to do this, but it would probably be best to avoid the need to load external opcodes and simply write it in Csound. In fact, @joachimheintz has published one here that you could use.

Regarding the trouble you're having with the array version of chnget, you need to use i/k/S after the chnget/chnset name. Check out the example file here. It should give you a little more info than the manual help file. It was not possible to override teh existing opcodes, hence the need to give them unique names, as shown here.

Ahh okay cool. Pertaining to the last part (chnget/chnset for arrays) would it be more efficient to copy a single value to an array of equal size or would an opcode like the example below be more efficient? I essentially have an array of channels which all require the same value and I am unsure if allocating the same variable to an array to pass to chnset would be faster than just individually calling chnset on each channel name string within the array.

;sets all channels to a single a-var starting at index 1
opcode setconnchnls,0,aS[]p
  aVal, Schnls[], iCnt xin
  chnset aVal, Schnls[iCnt]
  if iCnt < lenarray:i(Schnls)-1 then
   setconnchnls aVal, Schnls, iCnt+1
  endif
endop
rorywalsh commented 3 years ago

I think both approaches are fine but I think it will be faster with chnseta. Those opcodes have only been in the wild a short time, so if you hit any issues with them lease let me know. They were developed as a result of this thread. Victor sums it up in the last post with

Of course a C opcode is always more efficient than a UDO.

Despair-Bear commented 3 years ago

Thanks for the help, much appreciated