CsoundUnity 3.4.0
https://github.com/rorywalsh/CsoundUnity
CsoundUnityChild.cs
Go to the documentation of this file.
1/*
2Copyright (C) 2015 Rory Walsh.
3
4This file is part of CsoundUnity: https://github.com/rorywalsh/CsoundUnity
5
6This interface would not have been possible without Richard Henninger's .NET interface to the Csound API.
7
8Contributors:
9
10Bernt Isak Wærstad
11Charles Berman
12Giovanni Bedetti
13Hector Centeno
14NPatch
15
16Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
17to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
18and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
19
20The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
21
22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
24ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
25THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26*/
27
28using System.Collections.Generic;
29using UnityEngine;
30
31#if UNITY_EDITOR || UNITY_STANDALONE
32using MYFLT = System.Double;
33#elif UNITY_ANDROID || UNITY_IOS
34using MYFLT = System.Single;
35#endif
36
40[RequireComponent(typeof(AudioSource))]
41public class CsoundUnityChild : MonoBehaviour
42{
43 #region PUBLIC_FIELDS
44
48 [Tooltip("The gameObject with the CsoundUnity component to load Audio Channels from")]
49 [SerializeField]
50 public GameObject csoundUnityGameObject;
51
52 public enum AudioChannels { MONO = 1, STEREO = 2/*, QUAD?, FIVE_PLUS_ONE???*/}
53
59 [Tooltip("Audio Output settings")]
61
65 [SerializeField, HideInInspector]
67
71 [SerializeField, HideInInspector]
72 public List<string> availableAudioChannels;
73
77 [SerializeField]
78 public List<MYFLT[]> namedAudioChannelData = new List<MYFLT[]>();
79
80 #endregion PUBLIC_FIELDS
81
82 #region PRIVATE_FIELDS
83
84 [SerializeField, HideInInspector]
85 int bufferSize;
86 int numBuffers;
87 private MYFLT zerodbfs;
88 private AudioSource audioSource;
89 private CsoundUnity csoundUnity;
90
91 #endregion PRIVATE_FIELDS
92
93 private void Awake()
94 {
96 {
97 csoundUnity = csoundUnityGameObject.GetComponent<CsoundUnity>();
98 if (!csoundUnity)
99 Debug.LogError("CsoundUnity was not found?");
100 }
101
102 AudioSettings.GetDSPBufferSize(out bufferSize, out numBuffers);
103
104 audioSource = GetComponent<AudioSource>();
105 if (!audioSource)
106 Debug.LogError("AudioSource was not found?");
107
108 audioSource.velocityUpdateMode = AudioVelocityUpdateMode.Fixed;
109 audioSource.spatialBlend = 1.0f;
110 audioSource.spatializePostEffects = true;
111
112 // this will invert the audio channels
113 // 0---------180-----360
114 // normal----mono----reverse
115 // audioSource.spread = 360.0f;
116
117 /* FIX SPATIALIZATION ISSUES
118 */
119 if (audioSource.clip == null)
120 {
121 var ac = AudioClip.Create("DummyClip", 32, 1, AudioSettings.outputSampleRate, false);
122 var data = new float[32];
123 for (var i = 0; i < data.Length; i++)
124 {
125 data[i] = 1;
126 }
127 ac.SetData(data, 0);
128
129 audioSource.clip = ac;
130 audioSource.loop = true;
131 audioSource.Play();
132 }
133
134 if (namedAudioChannelData.Count == 0)
135 for (var chan = 0; chan < (int)AudioChannelsSetting; chan++)
136 {
137 namedAudioChannelData.Add(new MYFLT[bufferSize]);
138 }
139
141 // TODO: force doppler level of the AudioSource to 0, to avoid audio artefacts ?
142 // audioSource.dopplerLevel = 0;
143 }
144
148 public void Init(CsoundUnity csound, AudioChannels audioChannels = AudioChannels.MONO)
149 {
150 AudioChannelsSetting = audioChannels;
151
152 for (var chan = 0; chan < (int)audioChannels; chan++)
153 {
154 namedAudioChannelData.Add(new MYFLT[bufferSize]);
155 }
156
157 this.csoundUnity = csound;
158 this.csoundUnityGameObject = csound.gameObject;
159 this.availableAudioChannels = csound.availableAudioChannels;
160 this.selectedAudioChannelIndexByChannel = new int[2];
161 zerodbfs = csoundUnity.Get0dbfs();
162 }
163
169 public void SetAudioChannel(int channel, int audioChannel)
170 {
171 //Debug.Log($"CsoundUnityChild SetAudioChannel channel: {channel}, audioChannel: {audioChannel}");
172 selectedAudioChannelIndexByChannel[channel] = audioChannel;
173 }
174
175 void Start()
176 {
177 if (csoundUnity) zerodbfs = csoundUnity.Get0dbfs();
178 }
179
180 void OnAudioFilterRead(float[] data, int channels)
181 {
182 if (csoundUnity != null)
183 {
184 ProcessBlock(data, channels);
185 }
186 }
187
188 void ProcessBlock(float[] samples, int numChannels)
189 {
190 // print("CsoundUnityChild DSP Time - " + AudioSettings.dspTime * 48000);
191 if (availableAudioChannels == null || availableAudioChannels.Count < 1 || !csoundUnity.IsInitialized)
192 {
193 return;
194 }
195
196 for (int i = 0; i < (int)AudioChannelsSetting; i++)
197 {
199 if (string.IsNullOrWhiteSpace(chanToUse)) continue;
200 if (!csoundUnity.namedAudioChannelDataDict.ContainsKey(chanToUse)) continue;
201 namedAudioChannelData[i] = csoundUnity.namedAudioChannelDataDict[chanToUse];
202 }
203
204 for (int i = 0, sampleIndex = 0; i < samples.Length; i += numChannels, sampleIndex++)
205 {
206 for (uint channel = 0; channel < numChannels; channel++)
207 {
208 switch (AudioChannelsSetting)
209 {
210 case AudioChannels.MONO:
211 // sample is multiplied by 0.5f to obtain the same volume as the original audio file,
212 // since the mono channel is duplicated between the channels
213 samples[i + channel] = samples[i + channel] * (float)(namedAudioChannelData[0][sampleIndex] / zerodbfs * 0.5f);
214 break;
215 case AudioChannels.STEREO:
216 samples[i + channel] = samples[i + channel] * (float)(namedAudioChannelData[(int)channel][sampleIndex] / zerodbfs);
217 break;
218 }
219 }
220 }
221 }
222}
CsoundUnityChild is a component that can output AudioChannels found in the csd of the associated Csou...
int[] selectedAudioChannelIndexByChannel
An array containing the selected audiochannel indexes by channel: MONO = 0, STEREO = 1
List< MYFLT[]> namedAudioChannelData
A list to hold the current audio buffer data for each channel
AudioChannels AudioChannelsSetting
Defines if this CsoundUnityChild will use one (MONO) or two (STEREO) channels. In the case of a MONO ...
void SetAudioChannel(int channel, int audioChannel)
Used after Init(), sets the audioChannel index from the CsoundUnity.availableAudioChannels for each c...
List< string > availableAudioChannels
A list to hold available audioChannels names
GameObject csoundUnityGameObject
The gameObject with the CsoundUnity component to load Audio Channels from
void Init(CsoundUnity csound, AudioChannels audioChannels=AudioChannels.MONO)
Initializes this CsoundUnityChild instance setting the CsoundUnity reference and the audioChannels se...
Csound Unity Class
Definition: CsoundUnity.cs:271
readonly Dictionary< string, MYFLT[]> namedAudioChannelDataDict
public named audio Channels shown in CsoundUnityChild inspector
Definition: CsoundUnity.cs:353
MYFLT Get0dbfs()
Get 0 dbfs
List< string > availableAudioChannels
list to hold available audioChannels names
Definition: CsoundUnity.cs:348
bool IsInitialized
Is Csound initialized?
Definition: CsoundUnity.cs:358