| 
 | 1 | +/*  Example using clipping to modify the spectrum of an audio signal  | 
 | 2 | +    and emphasise a tone generated by the difference in frequency of 2 waves,  | 
 | 3 | +    using Mozzi sonification library.  | 
 | 4 | +
  | 
 | 5 | +    Adaptation of the Difference_Tone example using FixMath.  | 
 | 6 | +
  | 
 | 7 | +    Demonstrates the use of EventDelay(), rand() and fixed-point numbers.  | 
 | 8 | +
  | 
 | 9 | +    Demonstrates Oscil::phMod() for phase modulation,  | 
 | 10 | +    Smooth() for smoothing control signals,  | 
 | 11 | +    and FixMath fixed point number types for fractional frequencies.  | 
 | 12 | +    This is the same technique than the FMsynth example but  | 
 | 13 | +    using FixMath instead of mozzi_fixmath.  | 
 | 14 | +
  | 
 | 15 | +		Mozzi documentation/API  | 
 | 16 | +		https://sensorium.github.io/Mozzi/doc/html/index.html  | 
 | 17 | +
  | 
 | 18 | +		Mozzi help/discussion/announcements:  | 
 | 19 | +    https://groups.google.com/forum/#!forum/mozzi-users  | 
 | 20 | +
  | 
 | 21 | +    Tim Barras, Thomas Combriat and the Mozzi team 2023, CC by-nc-sa.  | 
 | 22 | +*/  | 
 | 23 | + | 
 | 24 | + | 
 | 25 | +#include <Mozzi.h>  | 
 | 26 | +#include <Oscil.h>  | 
 | 27 | +#include <EventDelay.h>  | 
 | 28 | +#include <FixMath.h>  | 
 | 29 | +#include <mozzi_rand.h>  | 
 | 30 | +#include <mozzi_midi.h>  | 
 | 31 | +#include <tables/sin2048_int8.h>  | 
 | 32 | + | 
 | 33 | + | 
 | 34 | +// use: Oscil <table_size, update_rate> oscilName (wavetable), look in .h file of table #included above  | 
 | 35 | +Oscil<SIN2048_NUM_CELLS, AUDIO_RATE> aSin1(SIN2048_DATA);  // sine wave sound source  | 
 | 36 | +Oscil<SIN2048_NUM_CELLS, AUDIO_RATE> aSin2(SIN2048_DATA);  // sine wave sound source  | 
 | 37 | +Oscil<SIN2048_NUM_CELLS, AUDIO_RATE> aGain(SIN2048_DATA);  // to fade audio signal in and out before waveshaping  | 
 | 38 | + | 
 | 39 | +// for scheduling note changes  | 
 | 40 | +EventDelay kChangeNoteDelay;  | 
 | 41 | + | 
 | 42 | +const UFix<8, 0> freq1 = 184;  | 
 | 43 | +const auto harmonic_step = freq1 * UFix<8, 0>(12).invAccurate();  // harmonic_step = freq1/12;  | 
 | 44 | + | 
 | 45 | +void setup() {  | 
 | 46 | +  Serial.begin(115200);  | 
 | 47 | +  aSin1.setFreq(freq1);  | 
 | 48 | +  aGain.setFreq(0.2f);         // use a float for low frequencies, in setup it doesn't need to be fast  | 
 | 49 | +  kChangeNoteDelay.set(2000);  // note duration ms, within resolution of CONTROL_RATE  | 
 | 50 | +  startMozzi();                // :)  | 
 | 51 | +}  | 
 | 52 | + | 
 | 53 | +void updateControl() {  | 
 | 54 | +  if (kChangeNoteDelay.ready()) {  | 
 | 55 | +    UFix<4, 0> harmonic = rand((byte)12);  | 
 | 56 | +    auto shimmer = toUFraction(rand((byte)255));  // Creates a UFix<0,8>  | 
 | 57 | +    auto freq2difference = (harmonic * harmonic_step) + (harmonic_step * shimmer).sR<3>(); // the shimmering is divided by 8 here  | 
 | 58 | +    auto freq2 = (freq1 - freq2difference).asUFix();  | 
 | 59 | +    aSin2.setFreq((freq2));  | 
 | 60 | +    kChangeNoteDelay.start();  | 
 | 61 | +  }  | 
 | 62 | +}  | 
 | 63 | + | 
 | 64 | +AudioOutput_t updateAudio() {  | 
 | 65 | +  auto asig = (toSInt(aSin1.next()) + toSInt(aSin2.next())) * (toSFraction(aGain.next()) + UFix<1, 7>(1.2));  // this is a SFix<9,9> in the end  | 
 | 66 | +  return MonoOutput::fromAlmostNBit(11, asig.asRaw()).clip();                                                 // TODO, implement smart MonoOutput  | 
 | 67 | +}  | 
 | 68 | + | 
 | 69 | +void loop() {  | 
 | 70 | +  audioHook();  // required here  | 
 | 71 | +}  | 
0 commit comments