GithubHelp home page GithubHelp logo

Comments (29)

bgold-cosmos avatar bgold-cosmos commented on June 21, 2024 1

Ah sorry, I forgot about d1 and d2 being different orbits by default.

Looking into this I think it may stem from #252 since I don't think there was a problem previous to that change, but I can't easily see why the new code shouldn't work. I'll try verifying some test cases and see if I can't figure out more clearly what's going on.

from superdirt.

bgold-cosmos avatar bgold-cosmos commented on June 21, 2024 1

OK, still working on a fix, but it definitely appears to be an issue with the handling of simultaneous cut messages. Shifting things even slightly causes it to work:

d1
 $ stack [
  s "bev(6,8)" # cut 1 # shape 0.9,
  ((1/1024) ~>) $ s "cp*8" # cut 2
  ]

is fine, but change the 1/1024 to 0 and the cut gets obliterated

(edited to add): also to be clear, this is a regression - the issue doesn't happen in an older branch I have from 2021

from superdirt.

cleary avatar cleary commented on June 21, 2024 1

@cleary

It is definitely configurable.

If it should be global by default, we need to change L 185 in DirtEvent from

var cutAllOrbits = ~cutAll ? false;

to

var cutAllOrbits = ~cutAll ? true;

We need to make sure that in current main, this is really the default behaviour. I've been on the develop branch for too long …

I'll give this a test tomorrow morning to confirm :)

from superdirt.

geikha avatar geikha commented on June 21, 2024 1

damn i totally forgot to report back! but i've been using the PR version for some months already and it's been working perfectly

from superdirt.

bgold-cosmos avatar bgold-cosmos commented on June 21, 2024

Did you mean # cut 2 on the last line? Because the cut 2 in the first example will supersede the cut 1 for the superimposed pattern.

from superdirt.

geikha avatar geikha commented on June 21, 2024

@bgold-cosmos sorry do you mean the last line of the last example or the last line of the first example?

either way, doesn't matter. what i've written it's what i meant :P

in the first example i want to have two different cut groups. one cutting the original and the other one cutting only the sped up samples. as for last example, each orbit has its own cut groups so it really doesn't matter which non-0 number i put in there.

from superdirt.

telephon avatar telephon commented on June 21, 2024

Yes, at #252 we removed the cut group for each orbit, and maybe something else went wrong.

from superdirt.

telephon avatar telephon commented on June 21, 2024

@bgold-cosmos If you switch on dump osc on the supercollider side, what messages do you see?

The key is somewhere either in DirtGateCutGroup:

DirtGateCutGroup {

	*ar { | releaseTime = 0.02, doneAction = 2 |
		// this is necessary because the message "==" tests for objects, not for signals
		var same = { |a, b| BinaryOpUGen('==', a, b) };
		var or = { |a, b| (a + b) > 0 };
		var and = { |... args| args.product };
		var sameSample = same.(\sample.ir(0), \gateSample.kr(0));
		var sameCut = same.(\cut.ir(0), \gateCut.kr(0));
		var free = and.(or.(\cutAllSamples.kr(0), sameSample), sameCut);
		^EnvGen.kr(Env.cutoff(releaseTime), (1 - free), doneAction:doneAction);
	}
}

and in DirtEvent:

if(~cut != 0) {
				server.sendMsg(\n_set,
					if(~cutAll.notNil) { orbit.dirt.group } { orbit.group },
					\gateSample, ~hash,
					\gateCut, ~cut.abs,
					\cutAllSamples, if(~cut > 0) { 1 } { 0 }
				)
			};

, and finally here:

sendGateSynth {
		server.sendMsg(\s_new,
			"dirt_gate" ++ ~numChannels,
			-1, // no id
			1, // add action: addToTail
			~synthGroup, // send to group
			*[
				in: orbit.synthBus.index, // read from synth bus, which is reused
				out: orbit.dryBus.index, // write to orbital dry bus
				amp: ~amp,
				gain: ~gain,
				overgain: ~overgain,
				sample: ~hash, // required for the cutgroup mechanism
				cut: ~cut.abs,
				sustain: ~sustain, // after sustain, free all synths and group
				fadeInTime: ~fadeInTime, // fade in
				fadeTime: ~fadeTime // fade out
			]
		)
	}

from superdirt.

telephon avatar telephon commented on June 21, 2024

I'm trying to reproduce this on the sclang side.

All this seems to work fine:

SuperDirt.default = ~dirt;

// cut same cut group, correct
(
fork {
	(type:\dirt, orbit:0, s: \sax, cut: 1).play;
	0.2.wait;
	(type:\dirt, orbit:0, s: \cr, cut: 1).play;
}
)

// don't cut different cut group, correct
(
fork {
	(type:\dirt, orbit:0, s: \sax, cut: 1).play;
	0.1.wait;
	(type:\dirt, orbit:0, s: \cr, cut: 2).play;
}
)

// don't cut different cut group, simultaneous, correct
(
fork {
	(type:\dirt, orbit:0, s: \sax, cut: 1).play;
	(type:\dirt, orbit:0, s: \cr, cut: 2).play;
}
)

// don't cut different cut group, absolutely simultaneous, correct
(
s.bind {
	(type:\dirt, orbit:0, s: \sax, cut: 1).play;
	(type:\dirt, orbit:0, s: \cr, cut: 2).play;
}
)

// cut same cut group, absolutely simultaneous, correct
(
fork {
	(type:\dirt, orbit:0, s: \sax, cut: 1).play;
	(type:\dirt, orbit:0, s: \cr, cut: 1).play;
}
)

// cut same cut group, absolutely simultaneous, correct
(
s.bind {
	(type:\dirt, orbit:0, s: \sax, cut: 1).play;
	(type:\dirt, orbit:0, s: \cr, cut: 1).play;
}
)



from superdirt.

telephon avatar telephon commented on June 21, 2024

@bgold-cosmos maybe you can find a minimal reproducer and then check in tidal what the actual events are that are being sent?

from superdirt.

bgold-cosmos avatar bgold-cosmos commented on June 21, 2024

@telephon
The Tidal events look fine, its seems that when there are two bundles with the same timestamp that one n_set will override the other?

To see this on the sclang side, I think you need to have some cutting going on in each group. I notice an issue with this:

(
fork {
	(type:\dirt, orbit:0, s: \bev, cut: 1).play;
	(type:\dirt, orbit:0, s: \cr, cut: 2).play;
	0.3.wait;
	(type:\dirt, orbit:0, s: \bev, cut: 1).play;
	(type:\dirt, orbit:0, s: \cr, cut: 2).play;
}
)

You'll hear two overlapping "bev" samples playing, which should not be happening.

Minimal Tidal code to do something like this is

d1
 $ stack [
  s "bev*8" # cut 1,
  ((0/1024) ~>) $ s "cp*8" # cut 2
  ]

Looking at the OSC dump in supercollider it look like

[ "#bundle", 16676975298944028671, 
  [ 12, 1004, 1 ],
  [ 15, 1004, "resumed", 1 ],
  [ 12, 1003, 1 ],
  [ 15, 1003, "resumed", 1 ],
  [ 12, 1001, 1 ],
  [ 15, 1001, "resumed", 1 ],
  [ 12, 1000, 1 ],
  [ 15, 1000, "resumed", 1 ],
  [ "/n_set", 3, "gateSample", -1128873534, "gateCut", 1, "cutAllSamples", 1 ],
  [ "/g_new", 1098, 1, 3 ],
  [ "/s_new", "dirt_sample_1_2", -1, 1, 1098, "bufnum", 520, "sustain", 16.0552, "speed", 1, "freq", 261.626, "endSpeed", 1, "begin", 0, "end", 1, "pan", 0, "out", 34 ],
  [ "/s_new", "dirt_gate2", -1, 1, 1098, "in", 34, "out", 36, "amp", 0.4, "gain", 1, "overgain", 0, "sample", -1128873534, "cut", 1, "sustain", 16.0552, "fadeInTime", 0, "fadeTime", 0.001 ]
]
[ "#bundle", 16676975298944028671, 
  [ 12, 1004, 1 ],
  [ 15, 1004, "resumed", 1 ],
  [ 12, 1003, 1 ],
  [ 15, 1003, "resumed", 1 ],
  [ 12, 1001, 1 ],
  [ 15, 1001, "resumed", 1 ],
  [ 12, 1000, 1 ],
  [ 15, 1000, "resumed", 1 ],
  [ "/n_set", 3, "gateSample", -1175928170, "gateCut", 2, "cutAllSamples", 1 ],
  [ "/g_new", 1099, 1, 3 ],
  [ "/s_new", "dirt_sample_1_2", -1, 1, 1099, "bufnum", 715, "sustain", 0.445122, "speed", 1, "freq", 261.626, "endSpeed", 1, "begin", 0, "end", 1, "pan", 0, "out", 34 ],
  [ "/s_new", "dirt_gate2", -1, 1, 1099, "in", 34, "out", 36, "amp", 0.4, "gain", 1, "overgain", 0, "sample", -1175928170, "cut", 2, "sustain", 0.445122, "fadeInTime", 0, "fadeTime", 0.001 ]
]

The only difference I can see from this and the similar dump from a working situation is here the two bundles have the same stamp.

from superdirt.

telephon avatar telephon commented on June 21, 2024

Here is a shortened one:

(
fork {
	(type:\dirt, orbit:0, s: \bev, cut: 1).play;
	0.3.wait;
	(type:\dirt, orbit:0, s: \bev, cut: 1).play;
	(type:\dirt, orbit:0, s: \cr, cut: 2).play;
}
)

I think I know now. The group gets set with cut 1 and cut 2 in one block of calculation and it overrides before anything could happen that would have freed the first one.

OK, will think of a solution, may need some reworking.

from superdirt.

telephon avatar telephon commented on June 21, 2024

I think there is no other way than to go back to the more complicated separate cut groups. I wonder if we could use the occasion to use them for something else as well.

from superdirt.

telephon avatar telephon commented on June 21, 2024

One difficulty is that currently we are able to cut across orbits. That was a feature of the current approach that we lose if we implement the cutGroups as server groups: every orbit must have its own group, but one group can't live in several groups.

It would be possible to keep track of every synth, but that causes a lot more messaging (for freeing them when they are done).

from superdirt.

telephon avatar telephon commented on June 21, 2024

The proposed fix avoids the complicated separate groups but instead adds a bit of timing inaccuracy for the cut. We could make up for it though, but let's see if this solution is reasonably close.

@bgold-cosmos @ritchse let me know how it goes.

from superdirt.

geikha avatar geikha commented on June 21, 2024

@telephon

This fix delays each cut group by one control period right? The one set by ServerOptions.blockSize, which defaults to 64 samples.

Just making sure.

If that is the case it seems like that could be a good fix. I don't know how high other users might set their block size tho.

Will test eventually tho and I'll let you know

from superdirt.

telephon avatar telephon commented on June 21, 2024

Yes, that is what happens. So each cut group will cut by a blockSize earlier. So for example, at 48kHz and 64 block size that will be a bit more than a millisecond for the second cut (64/48000), and 4 ms for the fourth (64/48000*3). It could be problematic when you have a lot of cut groups.

One problem I see is that it cuts early, so that it "eats up" the latency, it'll produce "late" errors when we have too many. 0.3 sec (default) will be eaten up with 225 cut groups.

A solution would then be to delay the cut – then we get a little overlap that grows with the cut number. Again, in our example setting, the 225th cut group would be cut 0.3 sec late.

It is a band aid, but it does keep things simple.

from superdirt.

telephon avatar telephon commented on June 21, 2024

If people change block size, they usually lower it to get tighter feedback.

from superdirt.

geikha avatar geikha commented on June 21, 2024

When we talk about the amount of cut groups, these go for each orbit (or cutAll) right? The amount of cut groups in one orbit won't affect the latency of cut groups in another one. That being the case:

I think overlapping isn't as good of an idea in some use cases. For example, if you have quite a loud constant sound such as a sine wave, white noise or a bass that doesn't decay, the overlapping will be noticeable even in very small amounts as an unprecedented peak will appear in the sound. While an early cut, even if slightly noticeable, makes more sense to me. There have been countless times when, for example, writing sub-bass patterns on a piano roll, I've had to end a note, which is followed by another one of the same pitch, very so slightly early so that it becomes noticeable they are in fact different notes. In other words I think cutting early has more sense conceptually than overlapping even if it's just some milliseconds.

from superdirt.

telephon avatar telephon commented on June 21, 2024

yes, you are right. Also for efficiency, it may be important not to overlap (it may cause spikes).

I'll add a safety net.

When we talk about the amount of cut groups, these go for each orbit (or cutAll) right? The amount of cut groups in one orbit won't affect the latency of cut groups in another one. That being the case:

The absolute total number is what counts, independent if you cut in your group or in all groups. So if you don't set cutAll, you can reuse the low cut numbers in your orbit. Only if you cut all, you may have to move to higher numbers if you don't want to cut another orbit.

What do you think, is that reasonable?

from superdirt.

geikha avatar geikha commented on June 21, 2024

I actually don't think we are being able to communicate this last idea properly. I don't blame either you or me of course, this is quite hard to put into words without it being confusing heh. I'll make up the following term to see if it helps:

Cut supergroup: a cut supergroup would be a cut of cut groups that run independently from each other on the tidal side. For example, each orbit has it's own cut supergroup, since if you use cut 1 on both d1 and d2, they don't affect each other, even if they are using the same index to indicate a cut group, these are different since they are on different cut supergroups. There is a special cut supergroup that can be used on tidal via cutAll which will allow you to cut notes between different orbits.

Does this make sense? I what I'm saying even right? lol. at least conceptually, i know implementation might be different. if this is the case, what i was trying to say is:

latency would only build up as you use more cut groups per each supergroup, right? so the third cut group of d1 would have the same latency as the third cut group in d2. they don't affect the latency of each other. and if you use cutAll then yes, they sum up because you're using the same cut supergroup

from superdirt.

telephon avatar telephon commented on June 21, 2024

Does this make sense? I what I'm saying even right?

yes, that's conceptually correct! :)

latency would only build up as you use more cut groups per each supergroup, right? so the third cut group of d1 would have the same latency as the third cut group in d2. they don't affect the latency of each other.

yes, latency (or earliness) is a direct function of the actual cut number value.

and if you use cutAll then yes, they sum up because you're using the same cut supergroup

no, also then, they don't sum up. It is just that if you use cutAll and you want to separate them, you need high cut numbers (because you need lots of different ones), and then you geht a high "earliness" because of that.

from superdirt.

geikha avatar geikha commented on June 21, 2024

ok totally got it now!!! i think this is the way to go certainly πŸ˜„

from superdirt.

telephon avatar telephon commented on June 21, 2024

Actually, not solved, sorry. Will need another solution …

from superdirt.

telephon avatar telephon commented on June 21, 2024

(reason: there still may be cuts in the same block, if you cut very quickly, from another parallel stream)

from superdirt.

telephon avatar telephon commented on June 21, 2024

@ritchse, @bgold-cosmos if you like, you can test this branch: https://github.com/musikinformatik/SuperDirt/tree/topic-flotsam

This should work reliably, it may have a little more cpu load in sclang for very dense cutting.

from superdirt.

cleary avatar cleary commented on June 21, 2024
d1 $ s "bev(6,8)" # cut 1

d2 $ s "bev(6,8)" # speed 2 # cut 1

as for last example, each orbit has its own cut groups so it really doesn't matter which non-0 number i put in there.

Ah sorry, I forgot about d1 and d2 being different orbits by default.

I'm coming in very late to this issue, as far as my usage goes, I regularly use cut groups across orbits in both tidal and in estuary/minitidal across cells.

My understanding is that they are not orbit specific at all - instead functioning on a global level, and this is (imo) a good thing -

I feel a bit confused by these comments because it's something I've definitely leveraged in the past.

@telephon is the flotsam proposal changing (what I understand to be) this global functionality?

from superdirt.

telephon avatar telephon commented on June 21, 2024

@cleary

It is definitely configurable.

If it should be global by default, we need to change L 185 in DirtEvent from

var cutAllOrbits = ~cutAll ? false;

to

var cutAllOrbits = ~cutAll ? true;

We need to make sure that in current main, this is really the default behaviour. I've been on the develop branch for too long …

from superdirt.

cleary avatar cleary commented on June 21, 2024

@telephon - here's my test

d1 $ slow 2 $ s "moog" # cut 1

d2 $ s "~ sd" # cut 1   

I'd expect the short sd to cut the longer moog sample, but it doesn't (and I'm sure this behaviour existed in the past, but I can't easily verify it).

Is this an option we can raise up to the startup.scd option level?

from superdirt.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.