-
Notifications
You must be signed in to change notification settings - Fork 761
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Topic/output limiter via gui #5106
Topic/output limiter via gui #5106
Conversation
Thanks for this. Note that in the current configuration this will affect recording since the record node by default is added to the tail of the root node. It's a bit outside the scope of this PR, but if we're going to continue with the current approach of nodes after the default group for certain purposes I think we really need a clear and documented specification about how those nodes should be ordered and interact. At the moment it's vague and implicit. For the current case, I'm not sure the best approach, but perhaps a flag to say whether volume (incl. clip) affects recording would be a good approach. I think this should default to no as the default record sample format is float, so there is no issue with dynamic range and we can always process later. This approach allows that we may want to monitor/limit separately from record levels, without supporting every unlikely possibility (eg. record limit but not volume, etc.). My instinct as well is that Volume, Recorder and ServerMeter should not handle this ordering, as they should be fairly simple, agnostic where possible, and dumb. This could be done in Server, but as it's already a huge class, a separate manager might be better. ServerUtilities? |
Thanks for your feedback! The reason I considered to affect the recording as well is that I prefer to record exactly what I hear in SC. If I hear harmonic distortion generated by the clipping on the monitoring it should be reflected on the recording as well. I am really too unexperienced in SC for how people use it actually, this is just my opinion and regarding the issue it seems there is a lot of different opinions on this topic. But I am also OK by implementing your suggestion. How should we proceed? |
I also rely on recording to float and then mastering / scaling later. If what I'm hearing is wrong in a live performance, I want to be able to fix it later in a mix, etc. I would be very against anything that doesn't let me capture an unadulterated signal. |
As I understand this, the purpose of this feature is not as an effect, but as a last resort safety feature for ears and speakers. If it's an effect it should be in user code I think, not as a built-in. If it's a safety, it means that if it kicks in something's gone wrong, so I agree with @joshpar that my first preference would be that recordings don't include that accident and can be fixed by scaling. |
Perhaps Agreed that safety limiting should not affect recording. |
Yeah that could work. Though somehow having possibly unused groups lying around seems a little messy. It might be a good use case for Server:reorder since that could just skip over any non-existing ones. I wonder if record shouldn't have a separate level control as well. Hmm... |
There probably would be user questions about "why so many groups" but groups are CPU-cheap and it's completely unambiguous, and would require no complex logic to determine which server components are or aren't there.
|
We miss a way to give groups an internal precedence, so I think this is a reasonably clear way of doing it in the current system. Then a quark like This seems to be going toward a consensus, right? @joshpar ? Do you think the groups should be just an abstract order (0, 1, 2...) or should they be semantically bound to their functionality (volumeGroup, rawAudioGroup, auditionGroup / volumeGroup, scopeGroup, limiterGroup / or similar ?). |
I could imagine also that we could place the record before the volume, and integrate limiting in the volume group, for simplicity. |
actually I believe that volume shouldn't influence recording! |
Yes - I agree with these things and the Griup approach
Josh
/*
Josh Parmenter
www.realizedsound.net/josh
*/
… On Aug 20, 2020, at 09:39, Julian Rohrhuber ***@***.***> wrote:
actually I believe that volume shouldn't influence recording!
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or unsubscribe.
|
My suggestion would be to have a standard If you want an effect on all audio that is part of the recording, it can be added to the tail of the default group or after the default group. The whole thing is a breaking change, because recordings using int format may now clip, even though the volume is lowered. So recorder should indeed have its own level control. Does this make sense? |
Thanks for the suggestions! From my understanding this would result in generating these default ServerGroups at
This means that Recorder, Scope etc. needs not to be added to the Root-Node but to UnprocessedAudio Group, the same for Volume to ProcessedAudio (if this group should be created) As this seems to me a major breaking change should this be done in this PR by applying some more commits on top? I have an implementation of the solution described above by creating the 2 groups in |
Another question would be how to indicate the function of the group as a "RawAudioGroup" as you can't give a group a name (yet). The current Group 1 - default group name is created by a hardcoded GUI hack
btw, wouldn't |
Good point. If we have multiple groups created for system purposes, then we'd need a data structure to represent them, with names.
Here's where things get tricky. IMO the recorder should write a signal that is volume controlled but not limited. Probably the scope should behave similarly. If a user generates a loud signal and relies on the volume control to bring it down to a reasonable range, and then they record it -- do you think they want the very loud (possibly out of range) signal in the file, or the one that is turned down? If the recorder is in the unprocessed audio group, then they will get a very loud recording (and, if they used an integer recording format, it would suffer clipping even though the volume controlled hardware output was not clipped). I would estimate a near 100% probability of complaints about that. I'm finding it hard to escape the conclusion that we would need to put the volume control immediately after the sources, then do recording and scoping, and then the safety limiter at the end where the threshold is equal to the set volume. |
My intuition was different at the start (and I think @joshpar 's as well) – but you do have a point. Especially when we record float, a lower level also won't make a problem (just as a higher one wouldn't). So let's assume we don't make this a breaking change, but just make sure the limiter always comes after anything else. Then it may be enough to add one specific group (let's call it "volume group", ID 2), and any recorder is added to the tail of it, while any effects are added to the head. One important thing is: I suppose we want one such group, and not one for each client? If yes, then there would be an instance variable in server:
this would be initialised in volume and recorder would @capital-G 's code adds a clipping to the volume itself, which needs to be changed to make this work. |
@muellmusik @joshpar @jamshark70 what do you think: should we keep the volume on the recording? And is it reasonable to add a standard group 2? |
@telephon Well... It's an interesting conversation. I can see the argument that you might intuitively expect the volume to affect recording. I think it might help to adopt the principle of designing for the common cases, and then making more exotic ones easy if possible. I think we agree that recording by default should be float and not limited. So... Common Other configs seem less likely. Intuitively one might want to limit recording, but with float that's not needed. The main thing is that this is well documented. So I think Volume then Record then Limiter is sensible. If Volume and Recorder could be made more flexible to support the exotic applications (e.g. if Volume supported a Group as target instead of just a Server) that would be great. Then individual Volumes per user etc are pretty simple to implement. I don't mind much about the group structure. It might be good to have a design document specifying how the whole defaultGroups business works and interacts with this. That could help with thinking it through. Devil's Advocate: Can I just ask, are we sure a clip at the end is really going to improve things or make them more 'safe'? Presumably the D/A convertor clips in any case? These sound more or less identical to me on headphones:
|
If I'm correct about this, then a proper limiter might be a better option. |
-1 and 1 is still loud if the gain to your speakers or volume on your device is turned all the way up. It’s a guard, but it doesn’t really prevent the threat of hearing damage.
A limiter would introduce latency, no?
I think anything user controlled (like Volume) should be present in recording. The feature here is technically user controlled on / off, but there isn’t a level set by the user, it’s just on or off. So I think this clip shouldn’t be in a recording, but Volume should. I’m fine bypassing both though.
Josh
/*
Josh Parmenter
www.realizedsound.net/josh
*/
… On Sep 8, 2020, at 05:13, Scott Wilson ***@***.***> wrote:
Can I just ask, are we sure a clip at the end is really going to improve things or make them more 'safe'? Presumably the D/A convertor clips in any case? These sound more or less identical to me on headphones:
If I'm correct about this, then a proper limiter might be a better option.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or unsubscribe.
|
Again, the issue is: the user has turned down the system volume and expects that the system will not allow out any sounds significant louder than this volume level. That is, the user expects the signal reaching the DAC to be well below full scale. But scsynth might generate a multiple-hundred-dB signal which, when multiplied by the system volume control's attenuation factor, is still far above full scale. So the DAC clips to full scale, but this still blows out the user's eardrums because the system was calibrated for signals below full scale. The system volume control is later in the chain than scsynth, so if scsynth clips to full scale, the final output would be below full scale. This would be an improvement over the current situation in macOS. |
Ah, okay, that makes sense. I was checking at full volume.
Yes. But in this case, the clip is sensible. |
Yes, we should also try not to break too much, or nothing if possible. So I'll list what the different things currently do:
It seems that extensions that try to be after everything will usually refer to the root node (id: 0). One place to put the limiter would be after the root node. But I have the vague memory that this is unspecified and leads to weird things. All the usual synths start in the default node (id: 1). The main task is to have a place to safely put the limiter, so that it'll come after all other things that are put in some kind of end position. |
Should this rawAudioGroup have a specific ID? I am still unsure b/c it is nice to have a hardcoded ID for this group as it would make the creation of groups more deterministic. As we seem to agree on the order
the question remains on how such a So either
Another question which I would be glad to get some recommendations or thoughts on:
On a sidenote: In
In case you need to change the OSC protocol message you have to touch the code at multiple places and you will only find the occurrences by searching through the code. |
As a principle, I am generally opposed to the idea of hardcoded or even permanent IDs, because it's poor design OOP-wise, breaking encapsulation, and encourages brittle, hybrid ways of working. Ideally I think nothing should have a hardcoded ID that isn't intrinsic to scsynth as a standalone app and its OSC API. That would mean only the root node with 0. Anything else should probably be built at higher level in clients, and in a manner appropriate to the language/use. Default group, volume nodes, etc. are all sclang things, not built into the server, and normally accessed using higher level constructs like server abstraction objects. There is a precedent for a hard coded ID with the default group, but not a clear one since multi-user scenarios complicate that. (To really be safe you have to go So, I'd say maybe the group could have a hardcoded ID, but I'd think carefully about that. Can it be done without? The actual processing nodes I'd say definitely not. |
There is of course perhaps a case that clipping could be built into the server and controlled via an OSC command, but that's a separate issue I suppose. |
Yes, we are talking about a standard. If we have, in the sclang library, another default group like discussed here, I think this group should be useful not only for clipping. If it is only really needed because of the clipping, then I'd prefer to have it hardcoded into the server, without a running synth. But if there are good uses of a standard group – it is very much worthwile establishing. |
This is definitely not a rule in sclang. There are some files that have long series of class definitions, which makes perfect sense.
If we end up not hardcoding the clipping in the server, this would be completely OK. But see below.
The implementation should include a refactoring of Volume (so that it can run relative to any group or target), which can have a common superclass, perhaps |
I guess one perspective is that if it's needed for safety, then maybe it should be there for all clients. Don't personally have a strong opinion though. |
yes. Also if it is for safety, it can be a flag at startup. |
Just to mention here that #5110 is merged, and nevertheless this PR is still a useful addition. |
I will continuing working on it starting thursday, sorry for the stale development over the last few weeks. |
@capital-G no worries, thanks for taking it on. this PR is very much appreciated. :) |
Comming back to this issue it seems that #5110 indeed already achieved the feature of non-exploding outputs by applying a clipping on the server level of the macOS implementation (and this is the only OS where I had issues w/ exploding audio levels). As applying a sclang limiter does not change the outcome of the signal anymore after #5110 I will close this issue as the implementation of would only introduce breaking changes but no benefits. |
Purpose and Motivation
Implements general limiter as discussed in #4894 so could close #4894
First time I am doing something in SC and C++, so please be kind but do not hold back feedback!
Types of changes
To-do list
Would love to run tests but I could not figure out what
as stated here means.
Sidenote: there are no mac binaries for clang-format version 8 - and building it yourself takes some time (~1 hour w/ pulling, setup etc) - maybe its possible to switch to another version or add a hint how to build this yourself on mac and else.