A new buffer player #2600
A new buffer player #2600
Comments
|
Thank you for the summary, it makes all sense to me. I argued before against making UGens more complex than necessary, and I have been able to implement a cross-fading buffer playback before by combining UGens, but it was indeed very involved, and so I think adding the cross-fade capability here would make sense. Also the multiplication with In my opinion, the Another question would be frame precision again. We want to ensure that start and stop positions even for large buffers are detected precisely. I think this is no problem with up to around 2^24 frames given as a 32-bit float? Name-wise, I think |
|
Thinking more broadly about it, would there be value in supporting multi-channel buffers? Currently, one would have to read each channel into a separate buffer using |
|
Would it make sense to just add interpolation to |
|
LoopBuf would also need an |
|
Wouldn't be a problem to add this. The
|
|
First pass at an argument order:
If How does the crossfade affect timing? If my loop is from 0 seconds to 2 seconds and my crossfade lasts 0.1 seconds, is the period of the resulting audio 2 seconds or 1.9 seconds? If the former, is it acceptable for the crossfade to be cut off if the entire buffer is less than 2.1 seconds long? startPos, startLoop, and endLoop are actually floats, so they still suffer from precision issues for long buffers. How do we deal with this? Would it be wise to have an argument controlling the type of interpolation, like LoopBuf? |
|
@snappizz I'd say we absolutely want the loop to be 2 seconds in your example. I imagine the "crossfade" to really be making sure there isn't a big discontinuity between the last and the first sample. Multiplying by the equivalent of Env([0,1,0],[fadeTime / 2, sampleLength]) is what I envisioned. |
As you certainly want to be able to modulate them, I suppose there is no other way than to accept a loss of precision there. Maybe it is better to specify |
Hmmm, but then you disallow a one-shot playback with given start and stop time. Wouldn't it be better to specify: If
I don't think you win any precision with this. Remember that for roughly the 2^24 range, you can give precise frame numbers encoded in a 32-bit float. Also this is easier to understand in terms of looping: You have precise start and stop points, but the loop-length would be in fact That last calculation shows that we might think carefully about whether we want to give positions and durations in seconds or sample frames, and furthermore, how these interact with the playback speed. I also would like to suggest that So from the above, I would suggest that |
|
Further thoughts on the cross-fade... There are actually quite a few more parameters that determine a cross-fade than just the length:
I'm still on the fence about Here's another attempt:
(should we really give a default for |
|
So exponential, As you may have noted, I have added an
This is to allow a "release" phase. With an explicit
We should still contemplate whether there is a problem doing
i.e. when we actually get two instances of
But that's quite ugly, too. |
|
I've started a wiki page here to compile the current state of the proposal: https://github.com/supercollider/supercollider/wiki/PlayBuf-2017 I'd definitely advise that we use stringent unit tests when developing this UGen! |
|
@snappizz thanks; although I think for discussion it's better to stay here in "issues", the wiki is better for compiling the "snapshots" of the discussion. I just wanted to explode the solution space even more with a slightly different proposal - shrink the functionality of the UGen by delegating the buffer playback again to another existing UGen such as I sometimes wish this had been done for other UGens such as |
|
This hypothetical UGen
Obviously we cannot use a shortcut of
Usage example:
|
|
But then we'll encounter the same issues as |
|
I do agree that we should aim for transparency and grant the user access to the read pointer. One idea is to introduce a new UGen, |
|
Ah I forgot about the float noise again. How would |
|
I just edited to clarify -- what I mean is that it runs in parallel with |
But what happens when your playback rate is positive and your loopEnd < loopStart? Or, if your loopEnd < loopStart and your playback rate is negative, does it play forward? |
@Sciss I don't understand what you mean here. I think the proposal is we specify a start time in either seconds or # of frames, and specify duration in number of frames. The problem with specifying an end time instead of a duration is this: |
Good questions. I think we could treat the entire buffer as a circle with the end joined at the beginning. This gives us the intuition necessary to tackle those cases. Say endLoop < startLoop = startPos, rate > 0, and isLooping = 1 (so endPos has no effect). Then the pointer starts at startLoop, wraps around the end of the buffer and back to the beginning, reaches endLoop, and then jumps "forward" to startLoop. Say endLoop > startLoop = startPos. rate < 0, and isLooping = 1. Then the pointer starts at startLoop, moves backwards and wraps around the beginning of the buffer and back to the beginning, reaches endLoop, and then jumps "backward" to startLoop. This also addresses my earlier question of "what happens if the loop region is 0 to 2 seconds and the crossfade is 0.1 seconds, but the buffer is 2.05 seconds long?" On the second half of the crossfade, you play 0 to 0.05. |
|
Wait, no. I got the second case wrong. That should be
|
@Sciss I could go either way. FadeTime in other UGens is in seconds. |
|
@vivid-synth thanks for the clarification with the two 1-seconds loops; seems reasonable to prefer duration then. I'm still wondering, if you have such long buffers, can't you split your material into several buffers, each of which is in the "safe" range for float positions? Sorry about the confusion with |
I'd want to fade both. If the first frame is (-)1, I as a user don't want it to start with a clipping sound. If this is controversial, we could have an optional |
|
"isLooping" should probably just be "loop", for consistency with PlayBuf |
|
Is there any potential for problems with crossfade (e.g. with exponents) if the duration is changed to a larger or smaller value in the middle of fading out? |
One option would be to use this as the first test case of sc3-plugins -> SuperCollider. I.e. it's considered unstable at first, so we put it in sc3-plugins, then when we're more confident we can migrate it over? |
|
I would latch any fade related argument during the actual fade. It doesn't make sense to change the fade-duration during an ongoing fade. |
|
@vivid-synth Sure, I was thinking that as well. I think our schedule would be to implement in plugins by 3.9 with a warning that the API is in flux, and then aim to make it stable enough for migration for 3.10. We can keep discussion here, however. |
|
@Sciss what I meant was, if we change the sample playback duration in the middle of a fade. Although the question of fade duration is also interesting. |
|
Although you want to continuously vary |
|
One downside of the idea of putting it in sc3-plugins is we won't have access to the various existing playbuf c++ macros. In addition to tests, may I suggest we document our code? It can be very hard to read UGen code that has no explanatory comments at all. |
|
It seems that we've worked out most of the details here, and the next step is to draft up an implementation. |
|
I'll volunteer to help work on this, maybe others who would be willing to help also can comment/ |
|
I won't chastise you if you want to get started on this, but I consider it pretty low-priority. Considering some of the major open projects in 3.9 (unit tests, ctor bugs in sc3-plugins, qtwebengine), I don't think it's the best thing to work on now. |
|
Moving this out of 3.9 |
|
I'm writing an implementation here: https://github.com/elgiano/xplaybuf I was heavily inspired by this discussion and the work with Eric Sluyter on super-bufrd. However, my implementation doesn't involve passing double precision position values across UGens. Features:
If anyone is interested, I appreciate discussion, comments, issues, and contributions :) |
To summarize the discussion at #2596,
PlayBufis missing two coveted features: the ability to set the end position of a loop, and crossfading.BufRdcan improve on this, but it has insurmountable precision issues with large buffers. It wouldn't be acceptable to add new arguments toPlayBufbecause it's too drastic of an API change for one of SuperCollider's most popular UGens. PromotingLoopBuffrom sc3-plugins to core is a possible solution, but it doesn't support crossfading.The best solution is to introduce a new UGen that overcomes these issues. I suggest that it be called Play or Player.
I have another idea to throw into the mix: can we consider getting rid of
* BufRateScale.kr(bufnum)?The text was updated successfully, but these errors were encountered: