# Creating and Arduino synthesizer without the tone library

I am thinking about trying to make an Arduino synthesizer using the true analog output on the Due. However I would like to be able to play multiple notes at the same time on a single buzzer. Is this possible and how would I do it?

• what is `buzzer`? .... is it able to produce different tones? Oct 26, 2019 at 19:02

You just have to add the waveforms. For example, if you want to play pure tones (the simplest and most boring timbre), you generate a sine wave for each of them and add them together:

``````struct Note {
float frequency;
float phase;
bool is_active;
} notes[MAX_NOTES];

void output_sample()
{
static uint32_t previous_time;
uint32_t now = micros();
uint32_t elapsed_time = now - previous_time;
previous_time = now;
float output = 0;
for (int i = 0; i < MAX_NOTES; i++) {
Note *note = &notes[i];
if (note->is_active) {
output += cos(note->phase);
note->phase += 2*M_PI*note->frequency*1e-6*elapsed_time;
if (note->phase >= 2*M_PI) {
note->phase -= 2*M_PI;
}
}
}
analogWrite(DAC_PIN, 2048 + round(output * (2047.0 / MAX_NOTES)));
}
``````

The function `output_sample()` should be called as frequently as possible. You can change the `notes` array any time to add, remove or change notes.

There is some room for optimization here, like:

• storing `2*M_PI*note->frequency*1e-6` as the “frequency” in order to save some calculations

• using a wave table instead of the `cos()` function (I don't know how good is the Due at transcendental math)

• replacing `elapsed_time` by a constant if you can manage to output the samples at a fixed rate.

Edit: I wrote “You can change the `notes` array any time to add, remove or change notes.” Here is how to start or stop a note, i.e. to add or remove it from the list of active notes:

``````// Start a note. Returns an index to be used with stop_note(), or -1 if
// we couldn't start the note because we are already outputting the
// maximum number of simultaneous notes.
int start_note(float frequency)
{
int i;  // index of the note in the notes[] array

// Find a free slot in the array.
for (i = 0; i < MAX_NOTES; i++)
if (!notes[i].is_active) break;  // found

// Couldn't find a free slot?
if (i == MAX_NOTES) return -1;

// Setup the note parameters.
notes[i].frequency = frequency;
notes[i].phase = 0;
notes[i].is_active = true;
return i;
}

// Stop the note with the given index.
void stop_note(int index)
{
if (index >=0 && index < MAX_NOTES)
notes[index].is_active = false;
}
``````
• How would I add notes here? I am not extremely familiar with structs. Nov 29, 2019 at 18:36
• @Someone: You find a cell in the array where `is_active` is `false`, and you set the desired frequency, and set `is_active` to `true`. Nov 29, 2019 at 19:17
• how would I add an item to the note array? Dec 1, 2019 at 3:04

Sound is nothing else than a multiple simple waves combined in to one. So, theoretically you can play as many sounds (tones) as you like on a single pin. If you want to go true analog than you probably want to use a sin wave to generate sound. However, in that case you can do the following: Either make a function that would be capable of generating a sin wave of your desired frequency. In case of true analog this would probably be done by calculating actual sin values and using the map() function mapping 0 - 1 to 0 - 1024 and writing to the pin. The frequency can be adjusted by changing the delay between each step of changing the voltage or DAC value. However, this will not allow for multiple frequencies. Alternatively for multiple frequencies to be played at the same time you would need to calculate the Fourier inversion of all the waves you want to play and send the results of that to the DAC.

• And you would need to use a speaker instead of a buzzer, since they can produce a single tone at a time. Oct 26, 2019 at 19:10
• Fourier inversion” is needless math jargon for what is simply the sum of the tones. Oct 26, 2019 at 19:32
• @EdgarBonet yes, it's basically a sum. Oct 26, 2019 at 20:06
• How would I go about doing this? Oct 26, 2019 at 21:02
• Mixing sounds is not as simple as summing them mathematically (nor summing and averaging to bring the level back down). I made that mistake once years ago, and the results were crap. Once I found a proper sound mixing function I never looked back... Oct 26, 2019 at 21:30