-
Notifications
You must be signed in to change notification settings - Fork 193
Metaoscillators to non-aliased sounds #124
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
Conversation
weep using it, and tables for band_limited square wave
|
Just a thought: This may not be the only use-case for switching oscillators. E.g. waveform selection in a synthesizer. Not sure, whether there is a nice way to cover this and your use-case, but if you have an idea on that... Regarding your question of adding the oscillators, since the number of oscillators is fixed, I think it would make most sense to add them all in a single call, as an array (or as an initializer list), probably even in the constructor. Thus, you would call it as Regarding using tables: At first thought that would sound easier to me, too, and should save a few bytes of RAM. But I may not be aware of all implications. Regarding table names: Agreed, all information should be included. Regards |
|
Hi @tfry-git , I personally always took care of oscillator selection with defining oscillators: for a nice synthesis sometimes their relative phases need to be adjusted which is not the purpose of this… The only other use I could think of was to reproduce for instance the "split keyboard" behavior, with low frequency notes and high frequency notes being very different… Do not know how much of use that would be though… I didn't know about initializer list, thanks! Everytime I discover new things :)! This would indeed make more sense, but is this present in Arduino? I will test… For the tables/oscil switch: I was thinking at first that switching between tables would be a bigger overhead than switching between oscillators… After wrapping up the For the tables: for this to be interesting I think a good number of tables would need to be added to Mozzi (several for the square, triangle and saw waves at least…) which is maybe something you want to prevent… I think that organizing these set of tables in subfolders can help to have it clean and would not be a problem… So comes the question, do you think that this would be of value for Mozzi? I did it because I was annoyed by aliases on most of my projects and wanted something that I could handle like an regular Oscillator, once the setup is done. There is nothing revolutionary here, or that could not be done in the user sketch by swapping tables, but I personally think that having a good set of band-limited tables could be of value. Best, |
|
Hi @tfry-git! So I tried initializing part of this object at construction with something like: I also tried something like: I think that would work to go through an intermediate array like: In the meantime, I also generated a lot of wavetables, removing one harmonic at a time and calculating to maximum frequency that can acheived without alias… That makes quite a lot of tables… If we get that into Mozzi maybe we will want to limit that amount (or not?). Best and thanks for your help… |
|
Sorry, I seem to have set up a nice trap for you ;-). I've actually spent many hours fighting this problem in a different context, and so should have known better. Anyway, I think the way out will be yet another scary concept: Variadic templates. I believe the following constructor should work (but haven't tried): To be used as: Regarding number of tables: I don't see much of an issue with that, as none of this will be compiled in, unless explicitly requested. But @sensorium should probably comment on that. |
|
... thinking about it, I wonder whether it wouldn't be possible to make the MetaOscil truly contain the Oscils (an array of them, instead of an array of pointers), with a variadic constructor that will simply take the table-names? Trying to implement that might involve a serious risk of knots in our brains, though. |
|
Hi @tfry-git ! Now that this seems to be working I'll make the code prettier, add some comments and a good set of tables and test. I'll then convert this to a regular PR and see if we want it in or not.
Certainly, but personally I'm not sure this is desirable: doing so will remove all simple access to the individuals oscillators composing a meta-oscillator. Not sure it is actually useful but for instance an example I can think of is not having all the oscillators of a meta not at the same phase. This can allow, if using a fixed frequency filter (which is dephasing), to keep the phase constant over all frequencies but compensating the phase shift induced by the filter in a frequency dependent manner at the oscillator level. Maybe that can be useful… Nothing related to the code in this PR (but related to my crusade against aliases): I wonder if it is possible to "over-sample" the signal by calling an oscillator two times in Will let you know when I'm done implementing these changes, that should not be very long… Thanks for your help! |
|
Hi! @tfry-git You opened the Pandora box: I also implemented a way to set all the cutoff frequencies using a variadic templated function! The cutoff frequencies can still be set independently as before but also "all-in-one" using I demonstrate the two different use in a example, put in the "Synthesis" folder. I order to remove the transitions from one Oscil to another, I made my example kind of an extreme case with a awful lot of Oscil (17), but still fits largely in a standard Arduino. It demonstrate a band limited square wave, keeping the crunchy sound at low frequencies without aliasing at high ones. I also generated a lot of tables for the triangle, saw and square waves, of different sizes. They are arranged in folders and sub folders in the tables folder. That makes an awful lot of added files but theoretically, in order to achieve a sound containing all "samplable" frequencies without alias you have to use them all! Obviously in real life a small amount of alias of very high frequency is not a big deal and some can be dropped. As you can see in the example, the declaration of all these Oscil is a bit tedious, however having so many Oscil does not impact performances as only one is played at a time, it just impacts the memory usage. I think that this can be very useful for synth implementation for instance where the crunchy sound of hard soundwaves is important while aliases really need to be avoided. Thanks for your help and let me know if you have further comments! |
…w initialization in the setup via a for loop for polyphonic purposes
|
Hei,
Except that it works great in my opinion. I'll let you know! Best, |
|
Okay, I think this is better. As said in my previous comment I have now:
Upon test this seems to work great even if can be a bit heavy to declare, you can have a look here for an example on a personal project. Best, |
|
I have no objection against this going in as is, but a few thoughts, that you may or may not to address:
|
|
Hi! Thanks for your comments, here are my thoughts about it:
|
|
Hello! Best and long live Mozzi! |
|
Hi Tom, |
|
@sensorium Thanks for your comment! |
|
@sensorium I appended the example with some explanation about what this is capable of. I also removed a function of the class ( I have used that on my own synth and it seems to be very reliable and enhancing the sound quality. Let me know if you think something else should be amended! Best, |
|
Hi, I am wondering if we could merge this? I am using it all the time (that the only difference between the branch I'm using and sensorium/master) and I think it is really worth it! This is obviously a bit heavy to use, but if the MCU supports it it really makes a huge difference on sounds which are in the treble range with non-sinusoidal waveforms. Cheers, |
|
I'm a git fool - how can I get just the files I need to test this? Thanks... |
|
Good question, the easier might be for you to fork my repo somewhere but I'm sure @tfry-git has a better solution! |
|
Hey Tom, it works here with the example. Let's include it in the release. |
|
Woops! I meant the Wavefolder. I'll try this one... |
|
Tested and working on 32U4 and 328 boards. |
|
The end of a long story! |
Hi,
Because of the usually low sample rate of Mozzi, especially on AVR, wavetables of big-harmonics contents waves are very prone to aliasing. This is particularly the case of the saw and the square waves, but also triangle to a lesser extend.
This is a proposition to resolve this, even if can probably be used for other things like splitting keyboard-like kind of behavior.
The idea is to provide a
MetaOscilclass that can switch between differentOscildepending on the current frequency. This allows for instance to swap between different band-limited tables seamlessly in order to produce no alias: at low frequencies, tables with a lot of harmonics can be used whereas at high frequencies these harmonics have to be removed from the tables in order to avoid aliases.The
MetaOscilproposed here can, after definition, be used exactly as a standardOscilexcept that it will internally change the oscillator used depending on the frequency. Transition is done at the same phase.Note that this is still in draft state: there are very little comments and it would probably be useful to the user to have more wavetables to play with, I added only four tables of the square wave with different limiting frequencies for the sake of the example. I would be interested in your feedback before pushing it to a clean mergeable state… In particular:
BL_aSq.addOscil) a bit heavy, but I do not really have ideas to do it better while keeping the performancesHope to hear your point on that!