Skip to content

Commit 193f7d4

Browse files
committed
Removed addOscil from MetaOscil, improved example with explanations
1 parent cbb2884 commit 193f7d4

File tree

2 files changed

+40
-13
lines changed

2 files changed

+40
-13
lines changed

MetaOscil.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,17 @@ template<uint16_t NUM_TABLE_CELLS, uint16_t UPDATE_RATE, byte N_OSCIL>
3737
current_osc=oscillators[0];};
3838

3939
MetaOscil(){};
40-
41-
/** Add one oscil to the MetaOscil.
40+
41+
/* Add one oscil to the MetaOscil.
4242
@param osc is a pointer toward an Oscil
43-
@param cutoff_freq is the cutoff frequency of this Oscil */
43+
@param cutoff_freq is the cutoff frequency of this Oscil
4444
void addOscil(Oscil<NUM_TABLE_CELLS, UPDATE_RATE>* osc, int cutoff_freq)
4545
{
4646
oscillators[current_rank] = osc;
4747
cutoff_freqs[current_rank] = cutoff_freq;
4848
if (current_rank == 0) current_osc=oscillators[0];
4949
current_rank += 1;
50-
}
50+
}*/
5151

5252

5353
/** Set all Oscil of a MetaOscil.
@@ -223,5 +223,9 @@ template<uint16_t NUM_TABLE_CELLS, uint16_t UPDATE_RATE, byte N_OSCIL>
223223

224224
};
225225

226+
/**
227+
@example 06.Synthesis/NonAlias_MetaOscil/NonAlias_MetaOscil.ino
228+
This example demonstrates the Meta_Oscil class.
229+
*/
226230

227231
#endif /* META_OSCIL_H */

examples/06.Synthesis/NonAlias_MetaOscil/NonAlias_MetaOscil.ino

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,27 @@
1-
/* Example playing a sinewave at a set frequency,
1+
/* Example using a MetaOscil to generate an alias free square wave on a sweep
22
using Mozzi sonification library.
33
4-
Demonstrates the use of Oscil to play a wavetable.
4+
Waveforms which are not only sines (Saw, square, triangle) are composed by a lot of harmonics which are at frequencies multiple of the fundamental frequency.
5+
If the frequency of one of these harmonics is higher than half the sampling frequency (https://en.wikipedia.org/wiki/Nyquist_frequency) (AUDIO_RATE/2 here)
6+
it will create "aliases" (https://en.wikipedia.org/wiki/Aliasing) which will sound out of tune are they not harmonically related to the fundamental.
7+
The higher the pitch, the more harmonics are above the Nyquist limit and the more aliased will be present for a given waveform.
58
9+
One way to avoid aliases is to use "band-limited" waveforms which have a limited sets of harmonics in order to avoid them to reach the Nyquist limit.
10+
As these waveforms are band-limited they will sound less "crunchy" if they are used at frequencies lower than what they are meant to be because they
11+
lack the high frequency contents.
12+
13+
In order to paliate that, a common technique is to "swap" wave tables on the fly in order to keep the frequency content up to the Nyquist frequency but
14+
not above. This is the principal usage of MetaOscil.
15+
16+
MetaOscil can be used (after construction) as a proper Oscil but really is a bunch of oscillators with only one playing.
17+
It will switch between different oscils seemlessly depending on the asked frequency. This allows to switch between oscillators with less
18+
and less harmonics as the pitch goes up, in order to avoid aliases, which is demonstrated by this example.
19+
20+
The bandlimited tables are nammed according to the max frequency they can play without bringing aliases at a given frequency. For example:
21+
square_max_90_at_16384_512_int8.h ensures that no aliases will be present up to 90Hz at 16384Hz sampling rate (the default for Arduino).
22+
If your sampling rate is higher (say 32768 which is the default for most 32bits platforms) this table will be able to play up to
23+
180=90*2Hz without aliases, as the Nyquist frequency is two times higher.
24+
625
Circuit: Audio output on digital pin 9 on a Uno or similar, or
726
DAC/A14 on Teensy 3.1, or
827
check the README or http://sensorium.github.com/Mozzi/
@@ -13,12 +32,14 @@
1332
Mozzi help/discussion/announcements:
1433
https://groups.google.com/forum/#!forum/mozzi-users
1534
16-
Tim Barrass 2012, CC by-nc-sa.
35+
Tim Barrass 2012, Combriat T. 2021, CC by-nc-sa.
1736
*/
1837

1938
#include <MozziGuts.h>
2039
#include <Oscil.h> // oscillator template
21-
#include <MetaOscil.h>32768
40+
#include <MetaOscil.h>
41+
42+
// All the tables used for the MetaOscil need to be included
2243
#include <tables/BandLimited_SQUARE/512/square_max_90_at_16384_512_int8.h> // band limited table that guarantee no alias up to a frequency of 90Hz at a sampling frequency of 16384 (or 180Hz at a sampling frequency of 32768Hz)
2344
#include <tables/BandLimited_SQUARE/512/square_max_101_at_16384_512_int8.h> // band limited table that guarantee no alias up to a frequency of 101Hz at a sampling frequency of 16384
2445
#include <tables/BandLimited_SQUARE/512/square_max_122_at_16384_512_int8.h> // band limited table that guarantee no alias up to a frequency of 122Hz at a sampling frequency of 16384
@@ -37,6 +58,7 @@
3758
#include <tables/BandLimited_SQUARE/512/square_max_2730_at_16384_512_int8.h> // band limited table that guarantee no alias up to a frequency of 2730Hz at a sampling frequency of 16384
3859
#include <tables/BandLimited_SQUARE/512/square_max_8192_at_16384_512_int8.h> // band limited table that guarantee no alias up to a frequency of 8192Hz at a sampling frequency of 16384 (this is basically a sine wave)
3960

61+
// The proper Oscillators that will be managed by the MetaOscil
4062
// use: Oscil <table_size, update_rate> oscilName (wavetable), look in .h file of table #included above
4163
Oscil <SQUARE_MAX_90_AT_16384_512_NUM_CELLS, AUDIO_RATE> aSq90(SQUARE_MAX_90_AT_16384_512_DATA);
4264
Oscil <SQUARE_MAX_101_AT_16384_512_NUM_CELLS, AUDIO_RATE> aSq101(SQUARE_MAX_101_AT_16384_512_DATA);
@@ -56,9 +78,9 @@ Oscil <SQUARE_MAX_1638_AT_16384_512_NUM_CELLS, AUDIO_RATE> aSq1638(SQUARE_MAX_16
5678
Oscil <SQUARE_MAX_2730_AT_16384_512_NUM_CELLS, AUDIO_RATE> aSq2730(SQUARE_MAX_2730_AT_16384_512_DATA);
5779
Oscil <SQUARE_MAX_8192_AT_16384_512_NUM_CELLS, AUDIO_RATE> aSq8192(SQUARE_MAX_8192_AT_16384_512_DATA);
5880

59-
// use: MetaOscil <table_size, update_rate, number_of_oscil> MetaoscilName. All oscils used should have the same table_size.
81+
// use: MetaOscil <table_size, update_rate, number_of_oscil> MetaoscilName. All oscils used should have the same table_size and **have to be put in increasing order of cutoff_frequencies**.
6082
MetaOscil<SQUARE_MAX_90_AT_16384_512_NUM_CELLS, AUDIO_RATE, 16> BL_aSq {&aSq90, &aSq101, &aSq122, &aSq138, &aSq154, &aSq174, &aSq210, &aSq264, &aSq327, &aSq431, &aSq546, &aSq744, &aSq1170, &aSq1638, &aSq2730, &aSq8192};
61-
//MetaOscil<SQUARE_MAX_500_AT_16384_2048_NUM_CELLS, AUDIO_RATE, 4> BL_aSq;
83+
6284

6385
// use #define for CONTROL_RATE, not a constant
6486
#define CONTROL_RATE 256 // Hz, powers of 2 are most reliable
@@ -67,7 +89,8 @@ int freq = 10;
6789

6890

6991
void setup() {
70-
// Set the cutoff frequencies for all the Oscil in the MetaOscil
92+
// Set the cutoff frequencies for all the Oscil in the MetaOscil ie at which frequency the MetaOscil will switch to the next Oscillator. Note that these are the same frequencies than the tables names in this case.
93+
// This have to follow the order given at the MetaOscil creation: this needs to be in increasing order.
7194
BL_aSq.setCutoffFreqs(90, 101, 122, 138, 154, 174, 210, 264, 327, 431, 546, 744, 1170, 1638, 2730, 8192);
7295

7396
// Cutoff frequencies can also be set or changed individually.
@@ -87,12 +110,12 @@ void updateControl() {
87110

88111

89112
AudioOutput_t updateAudio() {
90-
//return MonoOutput::from8Bit(aSq90.next()); // try to use this line instead to hear the non-band limited version
113+
//return MonoOutput::from8Bit(aSq90.next()); // try to use this line instead to hear the non-band limited version, sounds a bit like a radio
91114
return MonoOutput::from8Bit(BL_aSq.next()); // return a sample of the correct oscil to acheive no alias
92115

93116
}
94117

95118

96119
void loop() {
97120
audioHook(); // required here
98-
}
121+
}

0 commit comments

Comments
 (0)