sensorium / Mozzi

sound synthesis library for Arduino

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

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Stereo hack on ESP8266

algomusic opened this issue · comments

I'm using I2S out on an ESP8266. When defining STEREO_HACK as true in mozzi_config.h I get a compile error in my sketch that int updateAudio() is redefined.

I find that if in MozziGuts.h (line 286) I change the definition of updatAudio() to return an int rather than be void, and in MozziGuts.cpp I replace lines 356 and 357 with:
uint16_t sample = updateAudio();
i2s_write_lr(sample, sample);
then a (hacked) stereo signal works. Of course this bypasses a bunch of infrastructure around audio_out_1 and audio_out_2 which may be in place to do real stereo, but ...

This is currently begin reworked. In fact, you might want to try again, after I've just merged one pack of changes.

Among the changes, with an external I2S DAC, ESP8266 will in fact always output two channels, now (identical in the case of a mono config).

Of course, the point of STEREO_HACK is to actually create a true stereo signal. See the existing examples for how to use it. However, I still have further changes for that in mind (to remove the "HACK" from STEREO_HACK).

Hallo, the current STEREO_HACK is disturbing me as well. Could you share your thoughts - I might pick this up as well. I am planning to add some more generic output functionality and this is disturbing me there...

Whoops, it seems I never quite finished up my PR for this: #113 . Will try to address that tomorrow or so.

(That PR is pretty much ready except for conflicts and minor details, but if you have some input to add on that: now would be a good time!)

I am actually working on a prototype along the following lines

  • in the configuration we can define CHANNELS which would define the number of output channels

  • in MultiChannelOutput I provide the MultiChannelOutput class (with one channel it would just be an array with one value

  • this class is used consistently for QueueHandling

  • updateAudio() and updateControl() will be optional by using attribute((weak)) and will still work

  • the end user can use the new function for providing the result

    void updateAudioN(int channels, AudioOutput_t *output ) {
    output[0] = ...
    output[1] = ...
    }

On a Rasperry Pico we could theoretically provide 16 PWM output lines...

I see MultiChannelOutput as a natural generalisation of the MonoOutput and StereoOutput classes, which were also introduced rather recently. And in fact, I was expecting the desire for an arbitrary number of channels to pop up sooner or later. My idea for covering this was to introduce the AudioOutput typedef, which can be set to whatever is needed via a compile time option. With this, after PR #113, any special casing is removed from all queue handling (except for a few lines to maintain backwards source compatibility with STEREO_HACK), and in fact also from the updateAudio() function signature.

So, for the most part, we're really thinking along pretty similar lines, as far as I can see. I do see that your approach of using an array structure in the first place is a good "one size fits all" idea, and I'm not opposed to changing the underlying internal representation for Mono-/StereoOutput. I do see it as a good idea, however, to wrap this representation inside a class. This gives a good way to organize important helper functions such as for clipping and shifting, and offers flexibility for future extensions(*) and modifications. Of course, if array-like indexing is important, we could easily add [] operators. (But handling an arbitrary number of channels can also be had using variadic argument lists, for instance).

The second thing I like better about my solution is the function signature. For one thing returning what is generated is a bit more readable. For another, it is really again a bit more performant - and that, I have actually studied in the assembly. Due to the fact that updateAudio() is in a separate compilation unit from MozziGuts (or whatever may replace it), the compiler is limited in what it can optimize, here. And in this case we're talking about a function that is called often.


(*) Suppose, for instance, that on some platforms we might not hardcode "channels", but rather generate some sounds with location information, while leaving the rendering of that to another piece of code or even hardware. Then a plain array of samples may prove to be too rigid a representation.

Cool - it would be really nice if we could get rid of the ifdefs related to the stereo hack. My biggest wish would be to replace / or enhance the r and l in the mono and stereo with an array syntax - This should reduce another level of ifs and prepare for the support of any number of channels in the future... (or really better replace the the StereoOutput with one single generic Mulitichannel implementation) - The way I see it the Mulitichannel would just represent an array of MonoOutput - so that we have all the existing functionality on each channel.

Maybe we ought to move this discussion over to #113 ?

For the moment, I have now resolved the conflicts in that PR, but I have not yet incorporated your input regarding Multichannel. I hope to get around to that on the weekend.