Csound Csound-dev Csound-tekno Search About

[Csnd-dev] [Csound API] Using csoundListChannels in C#

Date2021-11-05 10:53
FromGiovanni Bedetti
Subject[Csnd-dev] [Csound API] Using csoundListChannels in C#
Hi all, 

this is my first post on this list so forgive me if I'm doing something wrong.

I'm helping Rory to develop and maintain CsoundUnity, which you can find here: https://github.com/rorywalsh/CsoundUnity.
We would like to retrieve the list of the Csound channels using csoundListChannels (https://csound.com/docs/api/group__CONTROLEVENTS.html#ga5fa6839d0f6bae9a3c5a0e82e4d83a5f), but something is wrong with the current implementation, and this causes Unity to crash.

The GetChannelList method C# implementation can be found here:
https://github.com/rorywalsh/CsoundUnity/blob/7600d63988de5d9c810dc0697da9ad52d555afe5/Runtime/CsoundUnityBridge.cs#L682

The ChannelInfoProxy structure, that represents controlChannelInfo_s (https://csound.com/docs/api/structcontrolChannelInfo__s.html), can be found here: https://github.com/rorywalsh/CsoundUnity/blob/7600d63988de5d9c810dc0697da9ad52d555afe5/Runtime/CsoundUnityBridge.cs#L775

The ChannelHintsProxy structure, that represents controlChannelHints_s (https://csound.com/docs/api/structcontrolChannelHints__s.html), can be found here: https://github.com/rorywalsh/CsoundUnity/blob/7600d63988de5d9c810dc0697da9ad52d555afe5/Runtime/CsoundUnityBridge.cs#L788

The crash occurs when Marshalling a channel name, possibly because the size of the whole structure is wrong. The size of the structure is now 68.
The name is Marshalled with this line: string chanName = CharPtr2String(proxy.name);
and the CharPtr2String method is defined as:

internal static String CharPtr2String(IntPtr pString)
{
    return ((pString != null) && (pString != IntPtr.Zero)) ? Marshal.PtrToStringAnsi(pString) : string.Empty;
}

Before the crash happens, the address to be Marshalled as a string is something like: 0xa1bc8a7400000000, which looks wrong.
This happens after correctly Marshalling one channel with an empty name (that I assume it's the Cabbage form), from this simple csd:


form caption ("Basic Test"), size(300, 100)



-n

 
sr 	= 	44100 
ksmps 	= 	64
nchnls 	= 	2
0dbfs	=	1 

chn_k "freqSlider", 1, 3, 440, 20, 16000

instr 1
a1 oscil .2, chnget:k("freqSlider"), 1
outs a1, a1
endin



f0 3600
f1 0 4096 10 1
i1 0 5



The implementation of GetChannelList on the CsoundUnity master branch currently returns an empty dictionary and a warning message.
I'm looking for a fix in this branch: https://github.com/rorywalsh/CsoundUnity.git#fix-GetChannelList

Any hint?
Thank you all!

gb

Date2021-11-08 11:37
FromGiovanni Bedetti
SubjectRe: [Csnd-dev] [Csound API] Using csoundListChannels in C#
Hi all,

just to confirm that this was fixed on the C# side. The  ChannelHintsProxy  implementation was missing an attribute to correctly Marshal the attributes char*.
I noticed a little issue with audio channels that have names created with sprintf, for example:

Sfile sprintf "file_%d", itab       ;where itab is 900
chnset ain, Sfile

When calling csoundListChannels, this returns an audio channel named "file_900" but also an audio channel named "Sfile".

Interestingly, if I multiply the value by something (in this order), an audio channel "Sfile" is not returned:

chnset kgain * ain, Sfile

Instead this returns a "Sfile" audio channel again:

chnset ain * kgain, Sfile

This is not a big issue right now, but maybe it's worth having a look.
This is the opcode that triggers this behaviour:

opcode analyze, 0, iikiiik

itab, iupdt, kgain, ilo, ihi, itrsh, klp xin
ilen = ftlen(itab)
aphs phasor (sr/ilen)
kphs = k(aphs)
Sprgrs sprintf "progress_%d", itab
chnset kphs, Sprgrs
ain table aphs, itab, 1
Sfile sprintf "file_%d", itab
chnset ain, Sfile
iupdte chnget "update"
;number of divisons of an octave. Default is 12 and is limited to 120.
ifrqs = 12
;the number of conformations needed for an octave jump. Default is 10.
iconf = 20
;starting pitch for tracker. Default value is (ilo + ihi)/2.
istrt = (ilo + ihi) / 2.0
ilo = octmidinn(ilo)
ihi = octmidinn(ihi)
istrt = octmidinn(istrt)
ain tone ain, klp
koct, kamp pitch ain, iupdt, ilo, ihi, itrsh, ifrqs, iconf, istrt
krms rms ain
Soct sprintf "oct_%d", itab
Shz  sprintf "hz_%d",  itab
Samp sprintf "amp_%d", itab
Srms sprintf "rms_%d", itab

chnset koct, Soct
chnset koct, Shz
chnset kamp, Samp  
chnset krms, Srms

endop

Cheers!

Il giorno ven 5 nov 2021 alle ore 10:53 Giovanni Bedetti <giovanni.bedetti@gmail.com> ha scritto:
Hi all,

this is my first post on this list so forgive me if I'm doing something wrong.

I'm helping Rory to develop and maintain CsoundUnity, which you can find here: https://github.com/rorywalsh/CsoundUnity.
We would like to retrieve the list of the Csound channels using csoundListChannels (https://csound.com/docs/api/group__CONTROLEVENTS.html#ga5fa6839d0f6bae9a3c5a0e82e4d83a5f), but something is wrong with the current implementation, and this causes Unity to crash.

The GetChannelList method C# implementation can be found here:
https://github.com/rorywalsh/CsoundUnity/blob/7600d63988de5d9c810dc0697da9ad52d555afe5/Runtime/CsoundUnityBridge.cs#L682

The ChannelInfoProxy structure, that represents controlChannelInfo_s (https://csound.com/docs/api/structcontrolChannelInfo__s.html), can be found here: https://github.com/rorywalsh/CsoundUnity/blob/7600d63988de5d9c810dc0697da9ad52d555afe5/Runtime/CsoundUnityBridge.cs#L775

The ChannelHintsProxy structure, that represents controlChannelHints_s (https://csound.com/docs/api/structcontrolChannelHints__s.html), can be found here: https://github.com/rorywalsh/CsoundUnity/blob/7600d63988de5d9c810dc0697da9ad52d555afe5/Runtime/CsoundUnityBridge.cs#L788

The crash occurs when Marshalling a channel name, possibly because the size of the whole structure is wrong. The size of the structure is now 68.
The name is Marshalled with this line: string chanName = CharPtr2String(proxy.name);
and the CharPtr2String method is defined as:

internal static String CharPtr2String(IntPtr pString)
{
    return ((pString != null) &&amp; (pString != IntPtr.Zero)) ? Marshal.PtrToStringAnsi(pString) : string.Empty;
}

Before the crash happens, the address to be Marshalled as a string is something like: 0xa1bc8a7400000000, which looks wrong.
This happens after correctly Marshalling one channel with an empty name (that I assume it's the Cabbage form), from this simple csd:

<Cabbage>
form caption ("Basic Test"), size(300, 100)
</Cabbage>
<CsoundSynthesizer>
<CsOptions>
-n
</CsOptions>
<CsInstruments>
sr      =       44100
ksmps   =       64
nchnls  =       2
0dbfs   =       1

chn_k "freqSlider", 1, 3, 440, 20, 16000

instr 1
a1 oscil .2, chnget:k("freqSlider"), 1
outs a1, a1
endin

</CsInstruments>
<CsScore>
f0 3600
f1 0 4096 10 1
i1 0 5
</CsScore>
</CsoundSynthesizer>

The implementation of GetChannelList on the CsoundUnity master branch currently returns an empty dictionary and a warning message.
I'm looking for a fix in this branch: https://github.com/rorywalsh/CsoundUnity.git#fix-GetChannelList

Any hint?
Thank you all!

gb