Arduino Soundlab

1,910

13

21

Introduction: Arduino Soundlab

It is incredible what a wide range of amazing sounds can be generated with the FM synthesis technique, even using a plain Arduino. In a previous instructable this was illustrated with a synthesiser that had 12 pre-programmed sounds, but a viewer suggested that it'd be much cooler to have full control of the sound parameters with potentiometers, and so it is!

In this sound lab, tones can be controlled by 8 parameters: 4 for the ADSR envelope of the loudness and 4 for the frequency modulation that determines the texture.

The addition of the 8 potentiometers did not go at the cost of the number of keys: three sets of 8 keys are readout a few microseconds one after the other, for a total of 24 keys, corresponding to two full octaves. In fact, two Arduino pins are unused and expanding to 40 keys would be possible.

Look at the video for how to make wild sounds, here's a brief overview:

* A=attack: time for a tone to reach its maximum loudness (range 8ms-2s)

* D=decay: time for a tone to go down to its steady level of loudness (range 8ms-2s)

* S=sustain: steady level of loudness (range 0-100%)

* R=release: time for a tone to die out (range 8ms-2s)

* f_m : ratio of the modulation frequency to the carrier frequency (range 0.06-16) values below 1 result in undertones, higher values in overtones

* beta1 : amplitude of the FM modulation at the beginning of the note (range 0.06-16) small values result in minor variations of the sound texture. large values result in crazy sounds

* beta2 : amplitude of the FM modulation at the end of the note (range 0.06-16) Give beta2 a different value than beta1 to make the sound texture evolves in time.

* tau : speed at which the FM amplitude evolves from beta1 to beta 2 (range 8ms-2s) Small values give a short bang at the beginning of a note, large values a long and slow evolution.

Step 1: Construction

Clearly, this is still a prototype, I hope one day me or someone else will build this big and strong and beautiful with large keys and real dials for the potentiometers in an awesome enclosure....

Needed components:

1 Arduino Nano (It won't work with the Uno, which has only 6 analog inputs)

24 push-buttons

8 potentiometers, in the 1kOhm - 100kOhm range

1 potentiometer of 10kOhm for volume control

1 capacitor - 10microfarad electrolitic

1 3.5mm earphone jack

1 LM386 audio amplifier chip

2 1000microfarad electrolitic capacitor

1 ceramic 1microfarad capacitor

1 microswitch

1 8Ohm 2Watt speaker

1 10x15cm prototype board

Make sure you understand the attached schematics. The 24 buttons get connected in 3 groups of 8, to be read out at D0-D7, and to be activated on D8, D10 and D11. The pots have +5V and ground on the end taps and the central taps are fed to the analog inputs A0-A7. D9 has the audio output and gets AC-coupled to a 10kOhm potentiometer for volume control. The sound can be directly listened to with earphones, or amplified with an LM386 audio amplifier chip.

It is all fits on a 10x15cm protoptype board, but the buttons are too close to play well, so it'd be better to construct a larger keyboard.

The circuit can be powered through the USB connection on the Arduino Nano, or with an external 5V power supply. A 2xAA battery box followed by a step-up converter is a perfect powering solution.

Step 2: Software

Upload the attached sketch to the Arduino Nano and all should work.

The code is straigthforward and easy to modify, there is no machine code and no interrupts, but there are a couple of direct interactions with the registers, to interact with the timer, to speed up the button readout and to control the behaviour of the ADC for the potentiometer readout

Step 3: Future Improvements

Ideas from the community are always welcome!

I am most bothered by the buttons: they are tiny and click hard when pushed. It'd be really nice to have larger buttons that more comfortable to push. Also, force- or speed-sensitivy buttons would allow to control the loudness of the notes. Maybe 3-way pushbuttons or touch-sensitive buttons could work?

Other nice things would be to store sound settings in EEPROM, Storing short tunes in EEPROM would also allow to make much more interesting music. Finally, more complex sounds could be generated, if anyone knows how to generate percussion sounds in a computationally efficient way, that'd be awesome...

Arduino Contest 2019

Participated in the
Arduino Contest 2019

1 Person Made This Project!

Recommendations

  • Retro Tech Challenge

    Retro Tech Challenge
  • Back to School: Student Design Challenge

    Back to School: Student Design Challenge
  • Lamps and Lighting Contest

    Lamps and Lighting Contest

21 Comments

0
gerhard.et
gerhard.et

Question 6 months ago on Step 1

How should i manipulate the ports, if i use touchsensor as input keys? Only input, no pullup, with TTP223 capacitve touch-switch?

0
rgco
rgco

Answer 6 months ago

I never used those but i seems a good idea, since regular buttons click sound is disturbing. Yes, if these are set to active high, you will have to adapt the code to disable pullup and invert the logic (the present logic is for active low)

0
gerhard.et
gerhard.et

Reply 6 months ago

Hi rgco,
thank you for the quick answer.
It is correct, the sensors are set to active high, but this could be changed. But it might be less effort to change the settings for the input pins in the sketch. However, i have no idea how to do this. Could you please tell me, how i must change the code ( the lines "if(pinD0 != nokey){DDRD &=~(1<<0);PORTD |=(1<<0);}; ???)" for the pins?
For changing activation from active low to high i assume, that i have to interchange the values for "keypressed" and "keyreleased". Is this correct?
Thank you for answering again.
Gerhard

0
rgco
rgco

Reply 6 months ago

In principle it is a matter of changing the >0 to ==0 and vice versa in these lines:

if ( (butstatD1 & (1<<0)) == 0 and (prevbutstatD1 & (1<<0)) >0 ) keypressed=0;
if ( (butstatD1 & (1<<0)) >0 and (prevbutstatD1 & (1<<0)) == 0 ) keyreleased =0;

However, there are some more complications due to the matrix-setup. It's not obvious that the matrix-scheme will work for these touch-sensors. Basically the buttons are divided in 3 groups of 8, which get activated one after the other. with regular buttons, I had to introduce a delay of 3 microseconds between the reading of one row and the other. Those touch buttons are active components, which might need a lot more time. So to read 24 buttons, which is more than the Arduino has pins, I don't think the simple matrix methods works. Looks like it would need shift-registers but that's extra hardware.

Sorry I can only give some general advice, the coding you'll have to do yourself!
Cheers, -Rolf

0
gerhard.et
gerhard.et

Reply 6 months ago

Hi Rolf,
thank you again. I'm sorry, i did not inform you that i want to use your first version of the synth with only 19 buttons. As far as i understand the connection diagramm, these buttons connect to ground when pressed. I'm afraid the touch sensors could be destroyed when connecte to vcc via the internal pullup-restor of 10k . How can i change the definition of a pin to "INPUT" without "PULLUP"?
What i did not mention too:
My intension is to build three synths (e. g. three arduino nano), connected to a guitar-like keyboard with three "strings". For each "string" up to 14 keys are enough. Each synth may be monophon.
Cheers, Gerhard

0
rgco
rgco

Reply 6 months ago

Ah, pullup won't destroy anything, they are pulled up with a high resistance, somewhere in the 20-50kOhm range. Anyway the pullup is done with the PORTD PORTB PORTC writes, whenever a non-zero value is written there, it results in a pull-up, so just write zeros there instead of ones.

0
JohnC1315
JohnC1315

Question 10 months ago

hey this project looks great! I'm building a nice wooden case with wooden keys for it.

I just want to ask: would it be silly to stick 2 of these soundlabs together to get 4 octaves and 8 voice (split by octave) polyphony? I have been studying theccode, but it's a bit hard for me to decipher: I have most of my experience with C# Unity programming.

Also, how would this work with a multiplexer?
Thanks for the great project!

IMG_20201122_075811.jpgIMG_20201122_144837.jpg
0
JohnC1315
JohnC1315

Answer 7 months ago

Hi again,
I'm having trouble with this one. I built the full size, 2 octave synth just as yours is, but the keys did not play a scale. I tore it down and fully rewired the keys, same issue. I have checked my connections twice after that. Still not playing in tune. Also, the lowest C did not play. There was a weird issue where the notes never turned off as well.

I took a break and returned to it this week, building again from scratch. I am trying to build with just 1 octave for simplicity. I tried connecting only 2 keys to test if they were playing correctly before moving on. They don't play correctly. Same issues, but even worse than before. Is there something I'm missing?

0
rgco
rgco

Reply 7 months ago

Sorry to hear your struggles! difficult to judge from a distance. There are many wires. I would debug in pieces. hack the code such that the values from the pots are fixed to central values. Play a single button. Activate the serial print and see if the buttons are being pressed.

Note that I have posted 2 simpler versions of this project:
https://www.instructables.com/Arduino-Synthesizer-...
https://www.instructables.com/Arduino-Chrismas-Tun...
The latter is good in particular to test the speaker

0
JohnC1315
JohnC1315

Reply 7 months ago

Thanks for the reply! I was able to get better sound and correct envelopes. However the 2 keys I wired up were D2 and E2, but they play the notes B1 and C1 respectively. There are only 4 connections, so it was easy to see that they were connected correctly. No other keys are wired up. Is the key press logic changed by having keys unwired?

I tried checking the code too. Would E2 be number 17 in those conditional statements? In those lines of code, I don't understand where/ how the pin names are tested. Sorry for my code illiteracy, but I wanted to focus on making a nice case

0
rgco
rgco

Reply 7 months ago

Hard to judge from what you're writing. I suggest you keep adding buttons. In the code it is trivial to change the note assignment to each button. The notes run 0-23 which have been set up to correspond to C4-B5. If it sounds weird or out of order with all buttons in place, you can fix it in either hardware or software.
NB. I have started with a new budget microcontroller, the raspberry pi pico, it has more pins, more memory and higher speed. It should be able to do more octaves, higher polyphony and fancier sounds. I'm sure it won't take long someone does it (sorry my interests are moving more towards instrumentation for citizen science)

0
JohnC1315
JohnC1315

Reply 7 months ago

I just sat down for a few hours, running back and forth from piano to soundlab and rooted out the pins one by one. Now I got the little one octave synth working! These are the pitches I found related to the pins:

C0 = D11 - RX1
C0# = D11 - TX1
D0 = D11 - D2
D0# = D11 - D3
E0 = D11 - D4
F0 = D11- D5
F0# = D11- D6
G0 = D11- D7

G0# = D10 - RX1
A0 = D10 - TX1
A0# = D10 - D2
B0 = D10- D3
C1 = D10 - D4
C1# = D10 - D5
D1 = D10 - D6
D1# = D10 - D7

E1 = D8 - RX1
F1 = D8 - TX1
F1# = D8 - D2
G1 = D8 - D3
G1# = D8 -D4
A1 = D8 - D5
A1# = D8-D6
B1 = D8-D7

Sorry you mentioned your interests are drifting towards citizen science, but one more modification to this would make it really cool.
Shifting the octave up and down:

The original preset synth you posted had a button that cycled through the presets, so I tried copying that code and having it run "settones()" again with the base frequency (440) changed. It worked, erratically for a moment, then settled back to original frequency, with occasional distorted noises. Running the entire "setup()" didn't help. I'm assuming the main loop has to be suspended for a moment for this to work. Is it a simple mod to shift the octaves during runtime? Thank you very much for your replies so far!

0
rgco
rgco

Reply 7 months ago

Glad i works now! Yes, these pitches seem right, I called hem C4-B5 instead of C0-B1, referencing always to the A4 being 440Hz.
Rerunning setup() is not a good idea: it does some low-level things that you don't want to doing running and there is the filling of the sine and exp lookup tables.
For shifting octave, I would expand the number of notes in settones() to 36 or 48 or 60 or 72. Then some button, switch or pot could add 12,24,36 or 48 to the value of keypressed and keyreleased.

0
rgco
rgco

Answer 9 months ago

That's looking pretty!
Going to 40 keys is almost trivial, pin D12 and D13 can be used to add two more rows of 8 keys each. Surely two independent systems can have independent 4-fold polyphony for each half.
The potentiometers can be shared and the output can be mixed (summed) with the opamp. Using a faster microcontroller and getting native 8-fold polyphony would be more natural.

0
JohnC1315
JohnC1315

Reply 9 months ago

Hi thank you for the reply!

Using a faster micro controller sounds good, however I have arduino nanos all over the place (over 50 of them!)

I found the section of code that dictates 440 hz for setting pitch, so I assume I'd change that to add octaves.

For this prototype, I'd really like to add just 1 more key, so there would be 3 C keys. Even just 2 octaves, this would make it a lot more useful to play something. The logic code for key presses is quite hard for me to understand. I even printed it out and hilighted the different keywords... can you offer some advice for adding just an upper Ckey. And you say adding 40 keys would be trivial, but adding to that logic code doesnt look easy.

0
rgco
rgco

Reply 9 months ago

The next key will have to be on a new 'row' of 8 keys connected to D12 or D13.
The code uses direct port access to be fast, but it does not help readability indeed.
Basically all the lines and blocks relating to butstatD1 butstatD2 butstatD3 will need an extra entry for butstatD4



0
niklassteenackers
niklassteenackers

Tip 10 months ago

Hey, I love your work! I have a couple ideas on how to improve the interface: you could use MIDI input instead of the hard clicky buttons, also you could swap out all the pots for rotary encoders with integrated button, so only one knob would be needed for, say, asdr. What do you think? I hope I'm not too late at the party because this project has so much potential!

0
rgco
rgco

Reply 10 months ago

I see only now, awesome!