Ok fine!
CsoundUnity Package (UPM) development
very noisy indeed
Mneawhile, Iām trying the audio clip route, but itās not working either. Iāve tried
- using the
OnAudioRead()
method: I can send audio to a node this way, but itās noisy like the other attempts usingOnAudioFilterRead()
- Using AudioClip.SetData in teh yield callback, but Unity gives me an error saying I can only call SetData from the main thread. So setData must be called on the main thread, but we have no way to schedule calls to it unless we use some kind of yield callback.
I feel like Iām going around in circles here
Tried to sync the audiosources like this:
private void Update()
{
foreach (var node in csoundUnityNodes)
{
node.AudioSource.timeSamples = this.audioSource.timeSamples;
}
}
same noise
This can be done like I did in the CsoundFileWatcher, filling a queue of actions
static Queue<Action> _actionsQueue = new Queue<Action>();
fill the queue like this:
lock (_actionsQueue)
_actionsQueue.Enqueue(() =>
{
//your action here
});
and execute in the Update of any object like this:
float _lastUpdate;
float _timeBetweenUpdates = .2f;
private static void Update()
{
var startTime = Time.realtimeSinceStartup;
if (startTime > _lastUpdate + _timeBetweenUpdates)
lock (_actionsQueue)
{
while (_actionsQueue.Count > 0)
{
var action = _actionsQueue.Dequeue();
if (action == null)
continue;
action();
}
_lastUpdate = Time.realtimeSinceStartup;
}
}
Hmm. Ok, I have to return to something else now for a moment, but this is what my yield callback looks like. You need a:
private AudioClip clip;
private clipKsmpsIndex =0;
MYFLT[] channelSamples;
And the callback:
SetYieldCallback(() =>
{
float[] newSamples = new float[DSPBuffersize];
clip.SetData(newSamples, 0);
for ( int i = 0; i < newSamples.Length; i++, clipKsmpsIndex++)
{
if(clipKsmpsIndex >= ksmps)
{
channelSamples = GetAudioChannel("oscil");
clipKsmpsIndex = 0;
}
newSamples[i] = (float)channelSamples[clipKsmpsIndex];
}
clip.SetData(newSamples, 0);
});
But I donāt know, passing actions seems like weāre wasting time moving things around while there has to be an easy and fast way to do this
For example this guy says itās working for him:
Hmm, weāve already tried that though? In his case he can write a full Unity DSP buffer of samples on each call to OnAudioFilterRead()
. And then pick up a full bufferās worth in his slave components. In our case we have two different buffer sizes, so we canāt update the sample array while OnAudioFilterRead is running.
I still feel the audio clip way should work? I mean, how hard can it be to dynamically create an audio clip in a master object, and pass it to children?!
But we would have to use the SetData
method, as we donāt want unique OnAudioRead
methods for each Csound channel. But SetData
that canāt be called on k-boundaries, unless we use some of your black magicā¦
ok fair enough Iāll try with SetData!
Iāll keep my fingers crossed. If we can send audio like this to child components it will be an amazing feature.
first I should convert the MYFLT to floatā¦
I thought another thing Iād like to try first, in the master OnAudioFilterRead we can fill an array of samples obtained from GetAudioChannel, and just then update the slaves.
Iāll try this
Iām pretty sure I tried that already, but have another go, I may v have screwed it upā¦
Almost there, tried with a dictionary, just had lunch break
what do we get with GetAudioChannel? 32 samples with both audio channels (L R interleaved)?
The problem I see here:
Is that the PerformKsmps and the ksmpsIndex = 0 will happen when ksmpsIndex is 32 but will always miss one sample of the R channel
notice Iām trying to reset later:
if (channel == (numChannels - 1))
{
ksmpsIndex = 0;
}
No, just a single array of 32 MYFLT samplesā¦
I just tried filling a Unity DSP buffer sized array of samples from Csound, and then passing that to the child object, but I still get crappy audio. In my child Iām trying to pick up channelSamples in my OnAudioFilterRead()
method, but same result as alwaysā¦
public void ProcessBlock(float[] samples, int numChannels)
{
if (compiledOk)
{
for (int i = 0; i < samples.Length; i += numChannels, ksmpsIndex++)
{
for (uint channel = 0; channel < numChannels; channel++)
{
if (mute == true)
samples[i + channel] = 0.0f;
else
{
if ((ksmpsIndex >= ksmps) && (ksmps > 0))
{
tempArray = GetAudioChannel("oscil");
PerformKsmps();
ksmpsIndex = 0;
}
if (processClipAudio)
{
SetInputSample((int)ksmpsIndex, (int)channel, samples[i + channel] * zerdbfs);
}
channelSamples[i] = (float)tempArray[ksmpsIndex];
}
}
}
}
}
channelSamples[i] = (float)tempArray[ksmpsIndex];
shouldnāt it be
channelSamples[i + channel] = (float)tempArray[i + channel];
?
EDIT No they are different size, let me think a bit
Yes, of course! My bad. So, weāre up and running with this
Gees, what a nightmare that was, and the solution was so obvious in the end!
Should I send you what I have and you can make it look like real c# code
nouo I had the feeling I was close too! but glad that youāre faster