|
1 |
| -/* Example playing a sinewave at a set frequency, |
| 1 | +/* Example of Ring Modulation synthesis, |
2 | 2 | using Mozzi sonification library.
|
3 | 3 |
|
4 |
| - Demonstrates the use of Oscil to play a wavetable. |
| 4 | + Demonstrates the use of Oscil::phMod to modulate an Oscillator by itself: a ring modulator. |
| 5 | + Ring Modulation is a part of frequency modulation synthesis (FM). |
| 6 | + Compared to "standard" FM where one oscillator modulates another |
| 7 | + in Ring Modulation the output of one oscillator is used to modulate |
| 8 | + itself, directly, of after further modulation, or to modulate one of its |
| 9 | + modulator (looking at the DX7 diagram is probably clearer). |
| 10 | +
|
| 11 | + Here we demonstrate the simple case of RM, one oscillator modulating himself. |
| 12 | + The equivalent diagram is: |
| 13 | +
|
| 14 | + _____ |
| 15 | + \/ | |
| 16 | + |----| | |
| 17 | + | 1 | | |
| 18 | + |----| | |
| 19 | + |_____| |
5 | 20 |
|
6 | 21 | Circuit: Audio output on digital pin 9 on a Uno or similar, or
|
7 | 22 | DAC/A14 on Teensy 3.1, or
|
|
25 | 40 | #include <EventDelay.h>
|
26 | 41 | #include <Smooth.h>
|
27 | 42 | #include <mozzi_rand.h>
|
| 43 | +#include <mozzi_midi.h> |
28 | 44 |
|
29 |
| -EventDelay kModulationChangeDelay; |
30 |
| -Smooth<uint8_t> kSmoothModulation(0.9f); |
31 |
| -// use: Oscil <table_size, update_rate> oscilName (wavetable), look in .h file of table #included above |
| 45 | +EventDelay kModulationChangeDelay; // to change the modulation amount |
| 46 | +EventDelay kChangeNoteDelay; // to change the base note |
| 47 | +Smooth<uint8_t> kSmoothModulation(0.99f); |
32 | 48 | Oscil<SIN2048_NUM_CELLS, MOZZI_AUDIO_RATE> aSin(SIN2048_DATA);
|
33 |
| -//Oscil <SIN2048_NUM_CELLS, MOZZI_CONTROL_RATE> aSin2(SIN2048_DATA); // controls the amount of Ring Modulation |
34 | 49 |
|
35 |
| -int8_t prev_sample = 0; |
36 |
| -uint8_t ring_mod, smoothed_ring_mod; |
| 50 | +uint8_t ring_mod_amount, smoothed_ring_mod_amount; |
| 51 | + |
| 52 | +UFix<8, 0> notes[4] = { 40 - 12, 52 - 12, 28 - 12, 30 - 12 }; // note played. Because of the ringModulation the oscillator is called *two times* |
| 53 | + // hence produces a note which an octave to high, so we compensate for that here (12 midi notes makes an octave). |
| 54 | + |
37 | 55 |
|
38 | 56 | void setup() {
|
39 |
| - Serial.begin(115200); |
40 | 57 | kModulationChangeDelay.set(2000);
|
41 |
| - startMozzi(); // :) |
42 |
| - aSin.setFreq(64); // set the frequency |
| 58 | + kChangeNoteDelay.set(300); |
| 59 | + startMozzi(); // :) |
| 60 | + aSin.setFreq(mtof(notes[0])); // set the frequency |
43 | 61 | }
|
44 | 62 |
|
45 | 63 |
|
46 | 64 | void updateControl() {
|
47 |
| - //ring_mod_amount = int(aSin2.next() + 128); |
48 |
| - //Serial.println(ring_mod_amount); |
49 |
| - //ring_mod_amount = 255; |
50 | 65 | if (kModulationChangeDelay.ready()) {
|
51 |
| - ring_mod = rand(150); |
| 66 | + ring_mod_amount = rand(255); // next target value of modulation |
52 | 67 | kModulationChangeDelay.start();
|
53 | 68 | }
|
54 |
| - smoothed_ring_mod = kSmoothModulation(ring_mod); |
| 69 | + smoothed_ring_mod_amount = kSmoothModulation(ring_mod_amount); // smoothing of the modulation |
| 70 | + |
| 71 | + if (kChangeNoteDelay.ready()) { |
| 72 | + aSin.setFreq(mtof(notes[rand(4)])); |
| 73 | + kChangeNoteDelay.start(); |
| 74 | + } |
55 | 75 | }
|
56 | 76 |
|
57 | 77 |
|
58 | 78 | AudioOutput updateAudio() {
|
59 |
| - prev_sample = aSin.phMod(int32_t(prev_sample) * smoothed_ring_mod); |
60 |
| - return MonoOutput::from8Bit(prev_sample); // return an int signal centred around 0 |
| 79 | + return MonoOutput::from8Bit(aSin.phMod((int32_t(aSin.next()) * smoothed_ring_mod_amount) << 4)); |
61 | 80 | }
|
62 | 81 |
|
63 | 82 |
|
|
0 commit comments