sensorium / Mozzi

sound synthesis library for Arduino

Home Page:https://sensorium.github.io/Mozzi/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

RFC: Mozzi 2.0 part 2 - Configuration restructuring

tfry-git opened this issue · comments

As a continuation of #204 but not strictly dependent, here are some thoughts on what I would like to change regarding the configuration itself.

The first change I propose is easy enough to summarize: Prefix each Mozzi configuration #define with MOZZI_ in order to avoid name clashes. Since this only affects customization of the configuration, the extra typing should not be too cumbersome. Exceptions will be made for AUDIO_RATE and CONTROL_RATE, which are also commonly used inside existing sketches.

The second proposed change is the general setup for configuration. This would consist of:

  • MozziCustomConfig.h This file will simply contain definitions to be used in the configuration, i.e. (and I'm actually trying to be complete, here):
#define MOZZI_MONO 1
#define MOZZI_STEREO 2

#define MOZZI_OUTPUT_PWM 1  // Corresponds to "STANDARD_PLUS" on AVR; "STANDARD" has been deprecated for ages, let's drop it
#define MOZZI_OUTPUT_2PIN_PWM 2  // Formerly known as "HIFI"
#define MOZZI_OUTPUT_EXTERNAL 3  // Formerly known as EXTERNAL_AUDIO_OUTPUT
#define MOZZI_OUTPUT_PDM_VIA_I2S 4
#define MOZZI_OUTPUT_PDM_VIA_SERIAL 5
#define MOZZI_OUTPUT_I2S_DAC 6
#define MOZZI_OUTPUT_INTERNAL_DAC 7

#include <hardware_defines.h>

I.e. we're actually trying to use exactly the same config values across all boards. Naturally, not each value will be supported on each board.

Next, the user may (or may not) customize some of these options like so:

#include <MozziCustomConfig.>
#define AUDIO_RATE 32768
#define MOZZI_AUDIO_MODE MOZZI_OUTPUT_EXTERNAL
// [...]

#include <MozziGuts.h>

Finally, MozziGuts.h will (automatically) apply defaults, where nothing has been set, and check for invalid settings. This will likely be mostly handled inside (internal) platform specific files like, e.g.

  • mozzi_check_config_avr.h
#if not defined(AUDIO_RATE)
#define AUDIO_RATE 16384
#endif

#if not defined(MOZZI_USE_AUDIO_INPUT)
#define MOZZI_USE_AUDIO_INPUT false
#endif

#if not defined(MOZZI_AUDIO_MODE)
#define MOZZI_AUDIO_MODE MOZZI_OUTPUT_PWM
#endif

/// [...] The above is a bit boring to type out, so I'm skipping ahead to the second stage:

#if not (MOZZI_AUDIO_MODE == MOZZI_OUTPUT_PWM || MOZZI_AUDIO_MODE == MOZZI_OUTPUT_2PIN_PWM || MOZZI_AUDIO_MODE == MOZZI_OUTPUT_EXTERNAL)
#error Specified MOZZI_AUDIO_MODE is not supported on this platform
#endif

// [...] Etc., and finally:
#if (MOZZI_AUDIO_MODE == MOZZI_OUTPUT_PWM)
#define MOZZI_AUDIO_BITS 8
#define MOZZI_AUDIO_BITS_EXTENDED true
#elif (MOZZI_AUDIO_MODE == MOZZI_OUTPUT_2PIN_PWM)
#define MOZZI_AUDIO_BITS 14
#elif (MOZZI_AUDIO_MODE == MOZZI_OUTPUT_EXTERNAL)
#if not defined (MOZZI_AUDIO_BITS)
#define MOZZI_AUDIO_BITS 16
#endif
#endif

Ok, I've skipped over quite some stuff, here, but you get the basic idea. But also, you will probably have noted that there are a couple of details that will still need to be addressed.


I imagine, some of this proposal may actually be controversial, so please voice your concerns (and your additional thoughts).

Hi!

I tend to agree with this approach but I do have some concern with a few things. Some of these configurations need some additional personalization, for instance, with I2S, the pins used for that can be chosen in a given set for some platforms. Of course, ideally, these customizations should be possible to be done without touching the source library ie. by the method described here, but at the same time it should not be in complete plain view either as I believe the library is more accessible to new users by limiting the possible configurations at first. Of course that should not prevent advanced users to fiddle around by specifying very in-depth options. Maybe the I2S pins is not the best example, DMA configurations is probably more of a concern here.

The great thing about all this is that it will be very easy to have a clear view about what board supports which way to output the sound compared to the "Hardware limitations" that we have now. These check_config files will be very helpful for that, but we might need to think ahead a bit so that not every new port becomes an hassle to do. Porting things in Mozzi is, in my humble opinion, not extra easy even thought the last steps of modularizations you did are helping a lot. I am just for trying to have them not more complicated than what we have now, especially we do not want to rebut new porters ;).

Of course, having examples or more complicated code that can be compiled and run without any additional operations, for instance to share a complete design (hardware + software) is extremely appealing!

Not sure if that comment is of much use, but once again I am up for helping where I can!

How to present config options is a very valid concern, indeed. To spin one idea, we could provide a well documented configuration file example for users to copy into their own project. This could have the "basic" sections near the top, and "advanced" sections later, or the use-at-your-own-risk-stuff could even be split out to separate files.

Regarding difficulty of porting, I'm actually hoping, this will not make things all so much more complex, and might even help making the structure more obvious. I've started toying with some macros, that I think should make the "bookkeeping" relatively straightforward. Also, of course, the config checks are not technically required, so we might in fact document them as "you don't have to do this up front", much as we already do for many features in the implementation template.

As a quick suggestion, but you might be on that already, maybe this configuration file could leverage on the knowing of the board that is actually being programmed and display the configs by sections for a group of boards (for instance DMA config are of no concern for AVR, but some timer config might), in the same spirit than hardware_define.

I guess the hard question is to choose between a complete configuration, where items apply if needed, but where some might not have some effect on some platforms and a more sectioned config where generality might be lost. Just throwing another idea: maybe a "mixed" approach where common editable parameters (output pins, external_audio) are on the top, followed by another mostly common but more advanced section (audio_rate, Timers, DMA if applicable and maybe some others), finally followed by an "hardware specific section"? The point being to avoid users to believe that I2S for instance is a valid mode for AVR, but RP2040 users should not have too look to far to find it either… Maybe the last two sections should actually be in reversed order, with the "hardware specific" config before the "advanced config".

I've made quite some progress on this (see #211), even if it's also still a long way to go. Thus far the config still needs to be set from within the library code, that part depends on the "single compilation unit".

The new config structure is becoming visible, however, and works for AVR and ESP32, so far. As it turns out, the "config example" file has become really heavy (https://github.com/sensorium/Mozzi/blob/d0b5409bcdde3d2b77199e2beaa4bad4c316b777/MozziConfigExample.h). Actually, I think, that's only partially my fault, however, as the most part of it is made up of documentation, parts of which did not exist before, and parts of which used to be scattered around all different places (there's definitely more work left in that department, too).

At any rate, my next idea is a hybrid approach: We'll keep the above file (probably renamed) as the one master file where all config options are given, and fully documented. But in addition, we'll offer a whole range of known-to-be-usable configuration examples for specific setups. I.e. we have one example config file for "config_example_esp32_i2s_dac.h", another for "config_example_uno_hifi_mode.h", and a third "config_generic_external_output_32bit.h", etc. Users could then mix-and-match from there. Each of these files would carry only minimal comments, but importantly contain links to the primary documentation for each option used.

Since the new configuration approach is based on "if nothing was specified, explicitly, a sensible default is used", this approach should actually be feasible. Adding some new config option (say concerning the storage type for audio samples) will not mean having to adjust each and every example config.

(This should also be grand for supporting certain specialized boards really easily. Required pin config, etc. could all be given, then.)

Will try to have a closer look on that and comment soon but as a starter I also think an hybrid approach is the way to go: people can also easily submit (via PR) new configurations (for instance #169 could have gone through that without changing Mozzi's main code). If that comes true, we could even consider making a nice template for configurations descriptions that people can submit: hardware, wiring, config, all in a file. That only differs from your plan on the

Each of these files would carry only minimal comments

But it also depends on how complicated is the specific configuration of course.

Let me know if you need my help on a specific point, for now I think I would be more a burden than anything by jumping in with no consultation but do not hesitate.

Let me know if you need my help on a specific point, for now I think I would be more a burden than anything by jumping in with no consultation but do not hesitate.

As usual, I'm really going to need your help in testing and cleaning up the mess I'm creating! But in fact, I think cutting through the initial jungle is most efficiently handled alone (I'll be busy with that for a few more days). Thanks!

I think cutting through the initial jungle is most efficiently handled alone

That's exactly what I was thinking/meaning by burden ;).