Cabbage Logo
Back to Cabbage Site

Pitch issue on Android with sf2 sequence playback

Hi!

I’m on the steep part of the learning curve and would appreciate help getting me over a bump.

I’ve extended sfload.csd that comes with the Environment Vars sample of the CsoundUnity package to play back a simple major scale sequence of notes from an array. I’ve also added basic functionality to change the preset instrument via a slider. In the Unity and Cabbage editors this works fine, but I’m having weird pitch issues in my Android build. The pitches for the different presets appear to be offset - some worse than others. I wonder if it’s an issue with the way I’m triggering the notes? I’m attaching my edit to sfload.csd and a recording of the out of tune playback from my Android device.

<Cabbage>
form caption("Sequencer"), size(300, 200)
rslider bounds(108, 78, 60, 60) channel("BPM") range(30, 300, 130, 1, 0.001)
rslider bounds(202, 76, 60, 60) channel("patch") range(0, 127, 0, 1, 1)
</Cabbage>
<CsoundSynthesizer>![sf2SequencerAndroidPitchIssue|audio](upload://is1bNlOKClTeCqKSeAlBVKpifqw.mp3) 
<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 SEQUENCER
    kBeat init 0
    kPatch = abs(chnget:k("patch"))
    kBPM = abs(chnget:k("BPM"))
    kNotes[] fillarray 60, 62, 64, 65, 67, 69, 71, 72    
    
    if metro(kBPM/60) == 1 then
        event "i", "PlayVoice", 0, 0.75, kNotes[kBeat], kPatch
        kBeat = (kBeat < 7 ? kBeat+1 : 0)
    endif
endin

instr PlayVoice
iptc    =   p5
inum	=	p4
idur    =   p3
ivel	=	100
kamp	linsegr	1, idur, 0, .1, 0
kamp	= kamp/500000						;scale amplitude
kfreq	=	1						;do not change freq from sf
a1,a2	sfplay3	ivel, inum, kamp*ivel, kfreq, iptc			;preset index = 60
	outs	a1, a2
endin

</CsInstruments>
<CsScore>
f0 z
i"SEQUENCER" 0 z
</CsScore>
</CsoundSynthesizer>

I think my mp3 didn’t make it as an attachment - here’s a link Android Pitch Issue

Wow that is super weird, I was expecting a wrong pitch in ALL notes, not randomly on some of them, like this it’s hard to tell what could be the cause of the issue.
I’ll do some tests later and let you know what I discover.

I was able to replicate it.
Honestly I have no idea why it behaves like this, the only thing I can notice is that it always behaves in the same way, so it looks like it’s an information retrieved from the sf file. It is a bit confusing since the same sf2 file works correctly on Editor.
I tried copying the file by hand connecting the device to the computer but it looks that making the copy from .bytes to .sf2 using C# is not the issue, as I have the same behaviour.
I tried other sf2 files, and I don’t have the same issue (I have other issues, like some notes are not playing), but the pitch is always correct.
There could be some info on the sf presets that is read as a pitch change by the sfplay opcode (I tried to use this instead of the interpolated version sfplay3, but the issue remains).

@rorywalsh any idea? I don’t have much experience with sf files so that’s all I can give :frowning:

[EDIT] I tried having a look at the sf_GMbank.sf2 file using Polyphone Soundfont Editor and all looks good there.

[EDIT2] I tried loading this general sound font file from MuseScore, and most of the presets (well basically all of them) don’t produce any sound on Android, while on Cabbage all is good :man_shrugging:

@giovannibedetti Thanks for checking - I’m glad you were able to replicate the issue. At least we know it’s not just on my end. Like you, I suspected some problem with the copied sf2 file, but I compared it to the original with WinDiff and the two files are identical.

Hmm, I found mention of the same issue in a post from 2019 - I need to look further down in that thread to see if a solution was found at the time.

[EDIT] It wasn’t as far as I can tell.

I will test it with the CsoundAndroid app, and if the behaviour is confirmed, I’m going to open an issue on the Csound repository, it’s out of my hands from what I can tell.

So the behaviour is the same on the Csound for Android app, I believe there are issues when selecting the presets.
The general soundfont from MuseScore works setting preset 0 on the Unity Editor with CsoundUnity 3.4.1, on CsoundQT 1.1.1.
It fails playing anything on the Csound for Android app (and of course if building an apk using Unity and CsoundUnity).

Here I’m switching preset every 8 notes. Works fine on pc, but not on Android.
You can toggle the comments on the first lines to choose which sound file to load.
TestSoundFonts_Android.csd (1.4 KB)

[EDIT] You might want to place the csd and the sf files in the Music/Csound folder, as I had some permission issues with the latest Csound for Android version, so the path to use could be something like this:

gisf	sfload	"/storage/emulated/0/Music/Csound/sf_GMbank.sf2"

Before opening an issue on the Csound repo I want to replicate it using the Csound for Android project from there (even if I know already it will be a pain)

Sorry for not giving this as much attention as I should but @giovannibedetti has far more experience here than I. But one thing I am curious about is how you deal with file assets on Android? I’m working on an Android app at the moment, and on startup I have to extract all files from the apk to the application folder before I can use any file reading opcodes in Csound. It’s a total pain. But maybe Unity have something worked out here that makes this a little easier to do?

There’s no shortcut in Unity. You will have to copy the files from the StreamingAssets folder or a Resources folder (there can be several Resources folders) to the PersistentDataPath, using a custom script. Afterwards you will have to set the Csound SFDIR to that folder. I guess it’s the same on Android.
Unity helps a bit with permissions usually (it sets the manifest automatically), but I never tried opening files from other locations on the phone using a “Browse” button. Maybe it’s easier than on plain Android, but I have some doubts :smiley:

Yeah, it seems all of the mobile platforms are locking down on file access. iOS is marginally better in that you don’t have to unzip assets but I recently had to write some code to access the downloads folder on iOS and that was quite some work.

If you’re working on a Csound Android app, can you test if the above behaviour with sound fonts replicates there too?
I couldn’t build the Csound Android project :confused:

I’m pretty sure it would work, but building a mobile app with Android Studio seems to be a far way removed from how we get things there with Unity. But I’ll try the next time I fire up Android Studio. :+1:

1 Like

Opened an issue on the Csound repo:

1 Like

Sound fonts issues have been fixed in CsoundUnity release 3.4.2, it includes Csound 6.19 beta.

@giovannibedetti Awesome, I can confirm the fix on my end. I’m looking forward to diving in! Thanks for looking into this and seeing it through to a fix.

1 Like

Thanks @giovannibedetti I saw that you and Victor were working hard on this. Great stuff. :clap:

1 Like