Cabbage Logo
Back to Cabbage Site

Unity 3D music sequencer project - advice on options

No reason. As long as it outputs a new random number each time it’s all good.

hey Rory - i started doing more modification of the MainController script to add a lot of options like velocity as intensity value , instead of 1 being on and 0 being off. also added a tempo divisor setup from a master tempo value. i added a lot of enums to set up additional routing as well. unfortunately after my modifications it now seems like Unity crashes or hangs when starting the scene. i’m suspecting i may be inadvertently creating a stack overflow someplace. can you give the script a once over and see if you find anything obvious? the Csound script seems to compile so i don’t think that’s the issue. i’d normally track it down with log messages but since it crashes or hangs immediately i can’t find the error. MainController.cs.zip (2.9 KB)

if there’s nothing obvious i’ll revert back to my previous one and add a feature at a time.

I can try it out tomorrow at some point and let you know.

well, i commented out almost everything and started with testing the tempo change code, and it looks like that’s the culprit. so i think my math must be off and i’m sending negative tempo numbers or something. checking now. math looks suspect when i look closer.

okay further update - i did update the code and there was a math error, but after fixing it and testing the values printed it still seems to be crashing. looks like it’s this code causing the freeze/crash:

	//tempo/beat div can be called on the fly
	public void UpdateTempo(int value)
	{
		float divisor = beatDivisions[value];
		tempo = masterTempo / 60.0f * divisor;
		Debug.Log("LayerTempo is:"+tempo);
		csound.setChannel("tempo", tempo);

	}

so, if i just call csound.setChannel(“tempo”, tempo); at Start(), there’s no issue. the Debug Log statement prints correctly as long as i comment out the csound call when i run the scene. but if i comment out the call at Start() and call UpdateTempo(int value) it hangs or crashes every time the scene runs. wondering if this is a bug? it’s very repeatable. all i can think is that it doesn’t like two math operations using no parentheses or maybe wants them handled separately? it’s very weird, but annoyingly consistent. beatDivisions[value] is an array of preset tempo divisions corresponding to selected rhythmic division/multiplication of the master tempo. it all prints out correctly but Csound throws up when it hits it for some reason. anyway here it is. let me know what you think. thanks!
MainController.cs-rev1.zip (2.9 KB)

Are you still experimenting with the Unity project I created, o have you already started reimplementing your older libPd project? If you are still modifying my project could you create a package for me with everything but the streaming assets folder? It would be easier to see if I can find the issue when I can run the project. If not I will just go through the scripts and see if anything sticks out…

i’m still using a modified version of your original project. haven’t integrated it into my older project yet. as far as not including streaming assets, i have no objections except i’m using the SF2 files in streaming assets. right now the problem can probably be tested with the sine synth you included. at the moment i’ve disabled the other 7 layers for testing purposes.

here you go. most recent scene i used is scene3.testSequencer_ForRory.unitypackage (205.9 KB)

let me know if Csound throws up due to not being able to load the SF2 files, and i’ll include those as well.

Actually, are you on OSX? If so then maybe just zip the package the whole thing. I’m at my OSX machine right now…

It seems that the soundfonts are causing an issue. Maybe you can simply package the whole thing for me and I can take a look.

ok - will do. here you go:

some quick notes on the Main Controller script changes i made - on line 11 i have an enum called TempoDivision, line 44 a float array of tempo divisions. line 48 is the instance of the enum allowing selection of division in the Inspector.

on Start() there’s a function call on line 76 to that UpdateTempo function i pasted earlier. further down on line 81 i commented out a direct call for tempo change. if you reverse the commenting, blanking out line 76 and exposing line 81, it works fine. but it crashes or hangs in its current form.

I’ll have time to look at this tomorrow. Cheers.

I don’t really follow how/why you are casting an enum to an int when you pass it to UpdateTempo() function. Shouldn’t you be passing one of your enum members using the dot operator? But anyhow, that’s not the issue here. The issue here is that you were trying to access the Csound object before you assigned it. The first call to your UpdateTempo() function needs to be after you call GetComponent():

csound = GetComponent<CsoundUnity>();
UpdateTempo((int)layerDivision);

hi Rory, well that was a stupid mistake on my part, easily rectified. and i’m making some progress on things. but i’m having very strange and consistent errors in that your sine wave instrument and the SF2 player seem to work differently when it comes to the sequencer. take a look at this screenshot:

it shows the first position and fifth row enabled. when i use instrument 0 or 1 - your sine wave instrument - there are no issues with this setup - it will play the note correctly. however if i use instrument 2-7 (an Sf2 player instrument) i get a really weird but highly consistent behavior. as the screenshot shows, if the instrument is say, instrument 3 (playing a vibraphone patch), the result will be silent on playback on that position. now, if i enable the fifth position at the fifth row like so:

the sound will now play the two events as shown, correctly. basically the enabling cube is the same position as the index, so it’s a diagonal line going from lower left to upper right (0,0 - 1,1 - 2,2 and so on). but if i turn off the 5,5 position then the 0,5 position falls silent again.

i have no idea why the SF2 instruments are acting differently with this than the sine wave instruments but it’s absolutely consistent. i do know the SF2 instruments respond to velocity values - i changed it from the original setting of on or off. i also know that the sine instrument does not respond to velocity changes, which i’d like to have happen.

the more i think on this the more it seems like the CSD file is the culprit here. but it doesn’t look that radically different than the note event call to the sine instrument - with the exception of the velocity addition. does something pop out to you when you see this:

instr inst2
; play from score and midi keyboard

	mididefault	60, p3
	midinoteonkey	p4, p5
inum	init	p4
ivel	init	p5
ivel	init	ivel/127					;make velocity dependent
kamp	linsegr	1, 1, 1, .1, 0
kamp	= kamp/5000				;scale amplitude
kfreq	init	1						;do not change freq from sf

      
a1,a2	sfinstr	ivel, inum, kamp*ivel, kfreq, 11, gisf1
	outs	a1, a2
	
endin

vs this?:

instr inst0
	a1 expon .1, .5, 0.001
	aOut oscili a1, cpsmidinn(p4)
	outs aOut, aOut
endin

the differences between the calls to the synths are minuscule:

			    if kInst == 0 then
					event "i", "inst0", 0, kDur, kNoteValues[p4-1]+kOffset		
				elseif kInst == 1 then
					event "i", "inst1", 0, kDur, kNoteValues[p4-1]+kOffset
				elseif kInst == 2 then
					event "i", "inst2", 0, kDur, kNoteValues[p4-1]+kOffset,kNotesAmps[p4-1]

let me know if anything jumps out at you. full script hasn’t changed much. latest is here:

Sequencer-sf2player.csd (5.4 KB)

as always, feedback is helpful and vastly appreciated. thanks!

Try changing your sine wave instr to this:

instr inst0
    	a1 expon .1, p5, 0.001
    	aOut oscili a1, cpsmidinn(p4)
    	outs aOut, aOut
endin

Then pass the same amp values to it as you do with the other instrument. That should rule out issues with the amp values at least. But if the sine instrument starts to misbehave too, then you have your culprit.

okay the expon p5 value you suggested needed a divisor since it was a duration value and then i followed with changing the

event "i", "inst0", 0, kDur, kNoteValues[p4-1]+kOffset

to

event "i", "inst0", 0, kDur, kNoteValues[p4-1]+kOffset,kNotesAmps[p4-1]

at that point it began behaving pretty close to the same as the SF2 instrument, requiring the diagonal value to be enabled before playing. so your hunch appears to be right.

so in order to test this, i modified instrument 3 to ignore p5 by setting ivel to a static value and eliminating the kNotesAmps call at the end. at that point it pretty much worked the same as the sine instrument.

so this means somewhere in the script the amplitude mapping to velocity via p5 isn’t working properly. since i modified the amp call to be more than on/off it’s likely something i’ve done. just not sure how to fix this. one thing i am curious about though. on line 81 there’s a printks line that prints twice every time i click a cube to enable or disable it, yet as far as i can tell, the scripts in Unity only call the routine one time when it’s clicked. seems weird, though it may be unrelated as it happens on all layers and any instrument selected. at any rate, here’s the note message formatting when a cube is enabled:

	;get row number and create unique channel name
	SRowCubeIndex sprintf "rowCubeIndex%d", p4
	SRowCubeState sprintf "rowCubeState%d", p4
	SrowCubeNote sprintf "rowCubeNote%d",p4
	kCubeIndex chnget SRowCubeIndex
	kCubeState chnget SRowCubeState
	kCubeNote chnget SrowCubeNote

	;if user has enabled a note, update note amp array
	kChanged changed kCubeState, kCubeIndex
	if changed(kChanged) > 0 then
		kNotesAmps[kCubeIndex] = kCubeState
		kNoteValues[kCubeIndex] = kCubeNote
		printks "Updating row %d - index: %d - value: %d - note: %d - inst: %d",0, p4, kCubeIndex,kNotesAmps[kCubeIndex],kNoteValues[kCubeIndex],kInst
	endif

as far as i can tell it seems fine. i added kCubeNote call to your original script. here’s the relevant modified Unity function that calls it:

public void EnableCubeToPlaySound(int row, int index, bool state)
	{	

		//Debug.Log("Cell Instrument is:"+instrument);	
		row = row +1;
		string channel = "rowCubeIndex"+row;
		csound.setChannel(channel, index);
		channel = "rowCubeNote"+row;
		//get note plus modifier
		csound.setChannel(channel,noteRowList[index]+transpose);
		channel = "rowCubeState"+row;
		if (state==true)
		{
		csound.setChannel(channel, posIntensity[index]);
		}
		else if (state == false)
		{
		csound.setChannel(channel, 0);	
		}
		Debug.Log("Playing"+row+","+index+","+state);
	}

is there something i’m missing? it all looks like it should work fine. is there maybe an issue with how the changed function is working? it might be that if kCubeState is 0 it ignores the line? but that would mean the note would be always on, not off as it seems to be behaving currently. maybe it’s the order of operations? in the CSD script it’s index, then state/intensity, then note, but in Unity the order sent is index, note, and state/intensity.

Definitely not what is intended, but could be there form the start as I never dug into this deep enough. I’ll take a look…

[edit] Take a look at the kChanged changed kCubeState, kCubeIndex line. Is that right (it may well be my code, but life was easier back then!). It seems as soon a cubeState changes this will be triggered again. That’s your culprit.

@rorywalsh i’m a little confused here. do you think this explains the velocity/p5 misbehavior or the double printing? the former is what i’m most concerned about, the latter not so much. as i recall when you first put it together for me, you only used 1 or 0 for the state - there was no velocity. i’ve changed that, but i’m still trying to see how it can effectively substitute an index for a row (won’t play row 5 index 0, but plays row 5, index 5).

The double printing. I’m thinking that there may still be issues with your kNoteAmps array? Can you try printing the full array while debugging from time to time to see if it’s all good? Also, are you certain that kCubeIndex is always correct? There are so many moving parts here.

For my simple project it was ok to increment row at the start of the EnableCubeToPlay() method. But in your case it means kCubeNote will never be 0, is that Ok?

@rorywalsh - i believe as long as the kCubeNote means something like a MIDI note, it would mean you can’t use MIDI note 0, which sounds fine to me.

as far as updating the array, the printks statement seems to be correctly printing values that are set in my PosIntensity array, and the index is printing correctly as well. but i’m only printing when i select a particular cube by clicking on it. so are you thinking i should print all array values each time the sequencer event is called? maybe something like this after the instrument switching?:

kcount=0
loop:
    	printks "amps %d",kNotesAmps[p4-1]
    	loop_lt kcount, 1, 7,loop

this addition currently doesn’t compile so i’m doing something wrong. sorry - getting too late for me right now. i can send the project again with some testing directions if it’ll help you. and honestly if you see a better way or a workaround in the meantime, let me know.

You can also just print each one like this:

printks "amps %d, %d, %d, %d, %d, %d, %d, %d", 0, kNotesAmmps[0], kNotesAmmps[1], kNotesAmmps[2], etc...

But make sure it’s only called sporadically, and not on each k-cycle, otherwise it will clog up your output console and eat up CPU…

[edit] it’s a pity our time-zones are so out of sync!