CsoundUnity: Where is the read output from csound actually passed to Unity's AudioSource?

Hey all,

Doing some mucking around with optimization in Unity. Trying to figure out where the output from csound is actually passed to Unity’s audio engine. Was trying to figure out if there’s a way to apply Unity’s “Preserve Sample Rate” setting that they have for audio sample files to csound, so it doesn’t automatically upsample in the case of mismatch. Still delving into Unity and how it works, so this may not be possible, but looking into it

Hi @DespairBear,

Welcome back!
This is the line where we grab the Csound output.

Thanks, good to be back :stuck_out_tongue:

Ah okay, so is the samples array somehow linked in to the AudioSource? So setting the samples array will then be fetched/outputted by the AudioSource?

Yes everything works thanks to the OnAudioFilterRead callback, that is used to read the AudioSource samples and pass them to Csound (if an AudioClip is provided, and processAudioClip is true) and then fill the AudioSource samples with the output from Csound.

Ahh okay, that makes sense. I wonder if there is a way to prevent Unity’s default upsampling. OnAudioFilterRead is called based on Unity’s AudioSettings sample rate correct? I wonder if there’s a way to force synchronization with csounds sample rate on a single object or if that is currently impossible. My initial thought is to have some sort of check on each OnAudioFilterRead where frames not within the csounds instance sample rate are essentially ignored. I don’t know if OnAudioFilterRead would be stable enough for an operation like this though, if it’s linked to some constant in a manner similar to FixedUpdate or if there’s fluctuations that might make such an approach unreliable. The documentation on how it actually functions seems sparse

Having a generic low, medium and high setting for csounds with predetermined ksmps and sr values to save DSP CPU for sounds that might be more in the background, where it wouldn’t matter as much if they have a very sample rate would be extremely handy.

Realized kind of a janky solution that seems to do the trick

If your csound instance is set to run at a sample rate lower than that of your Unity project, you can just have a quick check of the csound instance’s sample rate and the projects and then set the pitch of the AudioSource object. So 10K sample rate csound instance, 44.1K sample rate Unity project, AudioSource pitch set to 0.2268

The instance I was running, differences in performance:
10K sr Unity Project, 10K sr csound, Audio Source Pitch 1.0: peak~2.4% consumption
44.1K sr Unity Project, 10K sr csound, Audio Source Pitch 1.0: peak~9.1% consumption
44.1K sr Unity Project, 10K sr csound, AudioSource Pitch 0.2: Peak~2.4% consumption

So this seems to solve the issue without any complicated solutions. Obviously if there was a way to forcibly set OnAudioFilterRead’s sample rate per AudioSource instance, that would be ideal for long term stability purposes, but this seems to do the trick well enough with current versions of Unity

1 Like

This is very interesting, thanks for reporting.
I never tried messing with the pitch of the CsoundUnity’s AudioSource, this is really smart!
Yes the ideal solution would be having more control on how the OnAudioFilterRead callback works (and a more detailed documentation).
I will add this trick to the CsoundUnity docs (and add you to the contributors if you want), many thanks!!

Oh awesome, yeah absolutely, glad to be of service :smiley:

I modified the code so I can easily set the sample rate in inspector right on the Csound Unity script. I could push up a PR if you wanted to scope if it’s something you may want to include in the package.

Yes please!
I tried messing with the AudioSource’s pitch and I didn’t hear / see any change, so yes a pull req would be great :wink:
Be aware that I pushed a new version yesterday!

Sweet, I’ll get that in this evening :+1:

Actually make it tomorrow, realized I need to update and test CsoundUnityChild to work with this as well :stuck_out_tongue:

1 Like

You need only fork the current project. Clone the fork to your PC, and checkout the branch you wish to make the pull request to. Make your changes. Push your changes to your fork. Then from your fork’s github page, you can make a pull request. You don’t need any permissions to do this.

1 Like

Sweet thanks, put in a PR for an initial review :+1:

1 Like

Thanks!
Will review later this evening, but it looks good!

1 Like

So got another question. Where is the AudioSource actually linked to csound’s out opcode?
Does this happen somewhere in CsoundUnityBridge? Or is this somewhere in the precompiled DLL?

There is no link, the destination of the out opcode depends on the Csound options.
In this case we grab that output with the API (GetOutputSample).
Sorry yesterday I didn’t have time to look at the pull request!

https://github.com/rorywalsh/CsoundUnity/blob/master/Runtime/CsoundUnity.cs#L866

There are also other methods for grabbing a single sample.

1 Like

Ah okay, thanks for clarifying, finally clicked. One final question, is there a maximum number of output channels that csounds supports in a single instance? I see up to 8 in the documentation, but I’m assuming there’s a way it could write to more than that

I don’t think there is a maximum. Just set nchnls to whatever you like.

I’m not sure, maybe @rory has more info on this.
For sure you can use chnset to output as many aux channels you need.
In CsoundUnity we’re limited by Unity of course, in the ProjectSettings/Audio you can go up to Surround 7.1. But the availability of this channel setup depends on the target platform.