Hi all,
I’m resuming this thread because I finally had time to do some tests with Unity on Android.
I can confirm that it works, my android device produces sound!
That’s great news
First of all I am sorry for this long post, but I wanted to be clear explaining the problem I have.
One of my first experiments was trying to read an audio file.
Since on Android files gets compressed inside an apk, reading an audio file from the streaming assets like I was doing on the desktop version doesn’t work anymore.
This is the method I am using to load files:
//send score works also with instruments with string names,
//but sending stop with i-instrName doesn't work
//so use ints for now
//also, to stop the instrument, this should be started with infinite duration
void SendScoreEvent(int instrNum, bool isStart)
{
var sign = "";
var score = "i ";
if (!isStart)
{
sign = "-";
score += sign + "" + instrNum + " 0 0";
}
else
{
var path = Path.Combine(Application.streamingAssetsPath, AudioFilesPaths[0]);
Debug.Log($"Checking path: {path} \nFile Exists? " + (File.Exists(path) ? "true" : "false"));
//sending score with full path enclosed in escape chars
score += (instrNum + " 0 -1" + " \"" + path + "\"");
}
Debug.Log("sending score: " + score);
csoundUnity.sendScoreEvent(score);
}
This gave me the ability to start/stop an audiofile playing.
When running on android, File.Exists(path) returns false. This is why I need all of this stuff, here is some Debug.Log of the error:
jar:file:///data/app/com.CSound.CsoundAndroidTest-2/base.apk!/assets/14 - Pray For Me.mp3
sending score: i 1 0 -1 "jar:file:///data/app/com.CSound.CsoundAndroidTest-2/base.apk!/assets/14 - Pray For Me.mp3"
INIT ERROR in instr 1 line 30:
mp3in: jar:file:///data/app/com.CSound.CsoundAndroidTest-2/base.apk!/assets/14 - Pray For Me.mp3:
failed to open file
The counterpart in csound is this simple csd:
<Cabbage>
form caption("Read soundfile"), size(300, 200)
</Cabbage>
<CsoundSynthesizer>
<CsOptions>
-n -d -m0d
</CsOptions>
<CsInstruments>
sr = 48000
ksmps = 32
nchnls = 2
0dbfs = 1.0
instr 1
;prints p4
ibufsize = 2048
ar1, ar2 mp3in p4, 0, 0, 0, ibufsize
;ar1, ar2 soundin p4, 0, 0, 0, ibufsize
outs ar1, ar2
endin
</CsInstruments>
<CsScore>
</CsScore>
</CsoundSynthesizer>
Now since I have to first ‘open’ the apk looking for the files, I was trying to preload all the audiofiles I need in a dictionary with a UnityWebRequest, something like this:
public string[] AudioFilesPaths;
private Dictionary<int, byte[]> _audioFileBytes;
// Use this for initialization
void Start()
{
_audioFileBytes = new Dictionary<int, byte[]>();
var count = 0;
foreach (var fileName in AudioFilesPaths)
{
var path = Path.Combine(Application.streamingAssetsPath, fileName);
Debug.Log($"Checking path: {path} \nFile Exists? " + (File.Exists(path) ? "true" : "false"));
#if UNITY_EDITOR_OSX
path = "file://" + path;
#endif
LoadBytesFromPath(path, (bytes) =>
{
Debug.Log($"bytes loaded: {bytes.Length}");
_audioFileBytes.Add(count, bytes);
});
count++;
}
}
void LoadBytesFromPath(string path, Action<byte[]> onBytesLoaded)
{
StartCoroutine(LoadingBytes(path, onBytesLoaded));
}
IEnumerator LoadingBytes(string path, Action<byte[]> onBytesLoaded)
{
Debug.Log($"LoadingBytes from path: {path}");
using (var request = UnityWebRequest.Get(path))
{
request.downloadHandler = new DownloadHandlerBuffer();
yield return request.SendWebRequest();
if (request.isNetworkError || request.isHttpError)
{
Debug.Log(request.error);
yield break;
}
var bytes = request.downloadHandler.data;
onBytesLoaded?.Invoke(bytes);
}
}
And now the real question, since maybe I missed something from the docs:
How to send bytes data from Unity to CSound, and fill some tables to load from them later?
We have a setSample method that doesn’t seem viable, and what I need is something like setTableSample(s), but we only have a getTableSample method.
What am I missing?
Thank you for reading guys!