Skip to content

StereoOutput Constructor to send 2xStereo/4xMono #267

Description

@justinjools22

Hi this isn't an issue, rather sharing code I've adapted.

I have two DACs and wanted to send 4 separate mono waveforms. The constructor only accepts two arguments L/R so I added an additional 2. This would useful to add to the library for anyone else wanting to do this, could be called StereoOutput2.

Example usage:

#define SS_PIN PB0
#define SS_PIN2 PB1

DAC_MCP49xx dac(DAC_MCP49xx::MCP4922, SS_PIN); 
DAC_MCP49xx dac2(DAC_MCP49xx::MCP4922, SS_PIN2); 

void audioOutput(const AudioOutput f)  // f is a structure containing both channels
{
  // signal is passed as 16 bit. This DAC expects 12 bits so shift back four bits, and add a bias of 2^(12-1)=2048
  uint16_t outL = (f.l() >> 4) + 2048;
  uint16_t outR = (f.r() >> 4) + 2048;
  uint16_t outL2 = (f.l2() >> 4) + 2048;
  uint16_t outR2 = (f.r2() >> 4) + 2048;

  dac.outputA(outL);
  dac.outputB(outR);
  dac2.outputA(outL2);
  dac2.outputB(outR2);
}

AudioOutput updateAudio() {  

  return StereoOutput::fromNBit(12, aSaw1.next(), aCos1.next(), aTri1.next(), aSin1.next()); 

}

// StereoOutput constructor in AudioOutput.h
// 2xstereo/4xmono output: 4 arguments: l, r, l2, r2

/** This struct encapsulates one frame of mono audio output. Internally, it really just boils down to two int values, but the struct provides
 *  useful API an top of that. For more detail see @ref MonoOutput . */
struct StereoOutput {
  /** Construct an audio frame from raw values (zero-centered) */
//  StereoOutput(AudioOutputStorage_t l, AudioOutputStorage_t r) : _l(l), _r(r) {};
  StereoOutput(AudioOutputStorage_t l, AudioOutputStorage_t r, AudioOutputStorage_t l2, AudioOutputStorage_t r2) : _l(l), _r(r), _l2(l2), _r2(r2) {};  

  /** Default constructor. Does not initialize the sample! */
  StereoOutput() {};
#if !MOZZI_IS(MOZZI_AUDIO_CHANNELS, MOZZI_STEREO)
  /** Conversion to int operator: If used in a mono config, returns only the left channel (and gives a compile time warning). 
      This _could_ be turned into an operator for implicit conversion in this case. For now we chose to apply conversion on demand, only, as most of the time
      using StereoOutput in a mono config, is not intended. */
  inline AudioOutput portable() const __attribute__((deprecated("Sketch generates stereo output, but Mozzi is configured for mono. Check MOZZI_AUDIO_CHANNELS setting."))) { return _l; };
#  if GITHUB_RUNNER_ACCEPT_STEREO_IN_MONO
  inline operator AudioOutput() const __attribute__((deprecated("Stereo converted to mono on github runner"))) { return _l; };
#  endif
#endif
  AudioOutputStorage_t l() const { return _l; };
  AudioOutputStorage_t r() const { return _r; };
  AudioOutputStorage_t l2() const { return _l2; };
  AudioOutputStorage_t r2() const { return _r2; };
  /** See @ref MonoOutput::clip(). Clips both channels. */
  StereoOutput& clip() { _l = CLIP_AUDIO(_l); _r = CLIP_AUDIO(_r); return *this; };

  /** See @ref MonoOutput::fromNBit(), stereo variant */
template<typename T> static inline StereoOutput fromNBit(uint8_t bits, T l, T r, T l2, T r2) { return StereoOutput(SCALE_AUDIO(l, bits), SCALE_AUDIO(r, bits), SCALE_AUDIO(l2, bits), SCALE_AUDIO(r2, bits)); }

private:
  AudioOutputStorage_t _l;
  AudioOutputStorage_t _r;
  AudioOutputStorage_t _l2;
  AudioOutputStorage_t _r2;

};

#if MOZZI_AUDIO_CHANNELS > 1
StereoOutput MonoOutput::portable() const { return StereoOutput(_l, _l, _l, _l); };
#endif

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions