Cabbage Logo
Back to Cabbage Site

CsoundUnity 3.0, "sfload: cannot open SoundFont file"

Yes it would be nice to have everything together, but we need to add VR packages dependencies (there is no way of defining them per Sample), so those VR packages would be imported also for non VR projects.
That doesn’t look ideal, so it would be better to have the VR samples in another repo.
Maybe a submodule could work? Never used it, having a look!

Right, I see what you mean. Does your proposed VR package ship with CsoundUnity, or are you planning for users to import it into a project that already have CsoundUnity installed?

I simply created a new project, imported the CsoundUnity package, and two VR packages, Oculus XR Plugin and XR Plugin Management, then copied some prefabs from the Oculus samples.
So this is not in the form of a package but it’s a simple Unity project.

Hi, back to the initialization question in CsoundUnityBridge, here’s what I would suggest given the various challenges with a generic approach to Android file initialization. This would certainly work well enough for me, and eliminate any future need to modify the package code as distributed

  1. (as you have already), put back the appropriate environment variable settings (SFDIR, SSDIR, SADIR) for Win, Mac, Android
  2. Document the need for extra file copying on Android IF one is using opcodes that require additional files to be present (sound font, sound files, perhaps cad includes …haven’t tried this myself)
  3. Show a code example, including the need to address execution order in the project (again I’m not a super-fan of this, but it’s easy, it works, and it may not be worth the trouble to do better right now)

Thanks again for your help on this.

I will also take a look at the sample repo/project when you’re done and see how I can help. BTW, there is an update of the XR Interaction Toolkit (pre 1.0) that I haven’t tried yet, but our examples should probably use the new one

1 Like

I’m finally back to sfload!
I was hoping to use @rorywalsh’s suggestion to start the instrument using soundfonts after copying the .sf file in the right place (the persistentData folder that will be set as the SFDIR environment on CsoundUnityBridge creation), but sfload has to be placed in the header section of a Csound orchestra:

https://csound.com/docs/manual/sfload.html

So the only solution other than modifying the execution order is creating a prefab holding the CsoundUnity that uses soundFonts, and instantiating it after the sound file is in the right place.
This looks a bit weird but it’s an approach I’m using often when dealing with plugins and libraries when I need to delay their initialization (and there is no API that makes this possible).
But I’m thinking about the fellow CsoundUnity users who could not be comfortable with this :sweat:

Is there any other way of loading soundFonts? Consider that I don’t think I can use fluid opcodes, since those would be plugins (so another issue to handle :fearful:)
Also it looks that fluidLoad has to be run in the orchestra header too: https://csound.com/docs/manual/fluidLoad.html

Fair play for taking the time to look into this. You should be able to use the fluid opcodes though, loading libraries shouldn’t be that tricky? I find loading them explicitly using the --opcode-lib is pretty fool proof. But it is an extra moving part to maintain.

I’ve never really used them but can’t the same functionality be written with vanilla Csound?

Yes, I have some good news.
First thing, what I’d like to do, is creating samples that work on all platforms and don’t require any additional setup by the user (so they will work out of the box as soon as they are imported from the Package Manager)
And plugins are a bit harder to handle on Android :sweat_smile:
So I went with the simplest route, copying the soundfonts (I have them as TextAssets in the Resources folder of the sample) to the persistentData path (I will later add the possibility to set the path in the CsoundUnity inspector, but now I am setting the env dirs to persistentData path), and then instantiating the CsoundUnity instance that will make use of them.
So basically with this simple script everything is working great!

using System.IO;
using UnityEngine;

namespace Csound.EnvironmentVars
{
    public class Initializer : MonoBehaviour
    {
        [SerializeField] private string[] _soundFontsNames;
        [SerializeField] private CsoundUnity _csoundUnityPrefab;
        private CsoundUnity _csoundUnityInstance;

        void Start()
        {
            foreach (var sfName in _soundFontsNames)
            {
                var dir = Path.Combine(Application.persistentDataPath, "CsoundFiles");
                if (!Directory.Exists(dir))
                    Directory.CreateDirectory(dir);

                var destinationPath = Path.Combine(dir, sfName + ".sf2");
                if (!File.Exists(destinationPath))
                {
                    var sf = Resources.Load<TextAsset>(sfName);
                    Debug.Log($"Writing sf file at path: {destinationPath}");
                    File.WriteAllText(destinationPath, sf.text);
                }
            }
            // if you need to do something with Csound, use this instance!
            _csoundUnityInstance = Instantiate(_csoundUnityPrefab);
        }
    }
}

This is how my sound font files look in the editor :sweat_smile:

This is my Initializer GameObject:
image

And this is my CsoundUnity prefab:

This is the sfload csd:

<CsoundSynthesizer>
<CsOptions>
-n -d 
</CsOptions>
<CsInstruments>

; By  Menno Knevel - 2020

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

; load in two soundfonts
isf	sfload	"sf_GMbank.sf2"
ir	sfload	"07AcousticGuitar.sf2"
	sfplist isf
	sfplist ir
; first sf_GMbank.sf2 is loaded and assigned to start at 0 and counting up to 328
; as there are 329 presets in sf_GMbank.sf2 (0-328).
; then 07AcousticGuitar.sf2 is loaded and assigned to replace the 10th preset of already loaded sf_GMbank.sf2
	sfpassign	0, isf	
	sfpassign	10, ir

instr 1 ; play French Horn, bank 0 program 60

inum	=	p4
ivel	=	p5
kamp	linsegr	1, 1, 1, .1, 0
kamp	= kamp/500000						;scale amplitude
kfreq	=	1						;do not change freq from sf
a1,a2	sfplay3	ivel, inum, kamp*ivel, kfreq, 60			;preset index = 60
	outs	a1, a2	
endin
	
instr 2	; play Guitar replaces sf_GMbank.sf2 at preset index 10

inum	=	p4
ivel	=	p5
kamp	linsegr	1, 1, 1, .1, 0
kamp	= kamp/700000						;scale amplitude
kfreq	=	1						;do not change freq from sf
a1,a2	sfplay3	ivel, inum, kamp*ivel, kfreq, 10			;preset index = 10
	outs	a1, a2	
endin
	
</CsInstruments>
<CsScore>

i1 0 1 60 100
i1 + 1 62 <
i1 + 1 65 <
i1 + 1 69 10

i2 5 1 60 100
i2 + 1 62 <
i2 7 1 65 <
i2 7 1 69 10

e
</CsScore>
</CsoundSynthesizer>

:partying_face:

What do you think @ceberman?

Bravo! This looks like the simplest possible solution :clap:

1 Like

How does it look?
First draft :sweat_smile:

So basically, with this move we are able to customize also the plugin directory and all of the other Csound Global Environments variables!
Probably the next step would be grouping the selections being able to select multiple values at once from the Platform enum, but it takes some more thinking.
This was a pretty brutal approach, but it seems to work great!
Pushed to the custom_SSDIR branch!

This looks great. :+1: Seems like it could be time for a new release. Actually, I’m half tempted to look at the iOS stuff. :grimacing: It would be nice to have options on all major platforms.

That’d be awesome!
It shouldn’t need lots of code changes.
I’d use the custom_SSDIR branch as a starting point, since it handles global environment variables in a customizable way.

  • add the iOS library under a “iOS” folder in the Runtime folder
  • define the _dllVersion name of the iOS library in CsoundCsharp
  • add iOS to the supported platform enum
  • get an iOS developer account :sweat_smile:
  • steal an iOS device somewhere to test it :man_supervillain:
  • set up a party! :partying_face:

Nice steps! I should one important one to the start of the list:

  • find some time to do the work!
1 Like

hahah exactly :smiley:
I will have a look maybe this evening on the first three dots :wink:

I already have dots 4 and 5 :+1: Looks like you just need to party then :rofl:

1 Like

Yay!
I’ll ping you when I have good news then :wink:

Wow this looks fantastic as an approach!! And much more elegant than anything I considered.

I’m not sure if you were ready for me to try using it, but I did install the package in a new project (package manager: https://github.com/rorywalsh/CsoundUnity.git#feature/custom_SSDIR) and I had a few questions (Unity 2020.3.26f1 Windows)

  1. Is there a sample installed in the git repository for the EnvironmentVars prefab and the Initializer script?

  2. I did try setting up my own object and I didn’t get the editing fields in the CsoundUnity object once I set “Environment Settings” to 3: Is there a specific location in the project that the .sf file needs to be in?

Thanks!!!

Not yet, I’m adding one now, but you can use the scripts above. The important bits are that the sf2 files have to be inside a Resources folder, and that the CsoundUnity instance has to be a prefab, and instantiated later.

If you toggle the little arrow on the left of EnvironmentSettings you will see the settings lines!

Note that some of the Added Environment Variables printed are wrong and don’t reflect the values that those will have when the game is run on different platforms. They will all share the same path (because persistentData folder and streamingAssets folder will point to the same directories because the platform is always the one you’re using, in this case the Windows Editor).
I’m considering of removing them, or make some changes so that they will make more sense :sweat_smile:

EDIT: Just pushed a sample, but I’m having a crash when running it in a clean project :confused:
EDIT 2: I found the issue, it is very stupid. I don’t know how it is possible I pushed such a thing! I’m sure I tested it and it was working :confused:
EDIT 3: I pushed the fix, but it’s still crashing for me today, not sure what is wrong
EDIT 4: The issue is in the copy from the text asset to the sf2 file, there is something wrong happening! Will investigate. For now, simply put the sf2 files under streaming assets, and copy them from there to the persistent data folder. Or wherever you want with the new environment settings! :smiley:
EDIT 5: it should be fixed! I had to read the sf2 files as bytes and not as a strings :sweat_smile:

@rorywalsh about that party…

https://github.com/rorywalsh/CsoundUnity.git#feature/iOS_support

Oh that was fast. I’m on my Mac tomorrow. If I get a spare moment I’ll give this a go. :+1: It’s good to include this regardless. Even though it’s untested, we might snare an eager iOS user who keen to get it working :wink:

I had to make small changes to the code, everything was already there!
Hopefully it will work on the first try :sweat_smile:
I will update the other platforms libs to 6.17, then will prepare the new release 3.2.0!