Multiple sinewave player

hello all,
I am looking for general advices on how to start my audio synthesis project.
What I need to do is to play - let’s say - 15 sinewaves with different frequencies, under the following conditions:

  • good resolution (CD audio quality or more).
  • audio frequency (min. 40 / max 1500 Hz)
  • summed together (single mono output)
  • settable volume for every single sinewave (only once, not in real time)
  • not too bulky final product

From my investigation on SSD and other digging on the web, I suppose that to generate all the sinewaves with arduino is not the way to go, so I am curious about solutions on a wide range of possibilities (keeping the DIY and the open source philosophy, of course).
The question is: how to think of it. To use external DACs and amplifiers or also external oscillators, or a totally different product? What’s tour advice on this topic?

I thank you all so much for your time, any thought you will share is very much appreciated.

Antonio

How about Audacity]on a regular computer/soundcard?

Audacity ® | Free, open source, cross-platform audio software for multi-track recording and editing. (audacityteam.org)

That is what I would do, generate one sin look up table and have 15 separate pointers step through them at different rates. Multiply each sample you read by the steps own volume value 0 to 1. Then add them together and output through an I2S interface.
Piece of cake if you use the right processor, like a Teensy 4.1.

Hello @Grumpy_Mike, thank you so much! That’s in fact the way I tried some time ago with an arduino uno, but of course the clock speed was the down side. Now I ordered the teensy and will follow your suggestions.

hem… @DVDdoug, I know I can use the computer, but why not an original Moog synthesizer? :wink:

Thank you all

The Teensy4.x boards are so fast you’ll be able to call the sin() function directly I suspect - its many hundreds of times as powerful as an Uno for instance, thousands of times
more powerful for floating point.

To generate sine waves though you don’t need either table lookup or an implementation
of sin() (or floating point). Search term “fast sine oscillator code”…

Hello MarkT, thank you!
This is even more piece of cake!

Antonio

Which will not sound any better than going through a correctly constructed look up table.

ok, but are the two methods equivalent in term of audio quality?
I am not too technical guy, so I will go for the hardest way only if I have a better result.

Thanks

Antonio

A lot depends on what you want to do with these sin waves, and also how accurate you need these frequencies to be and are they harmonically related. There is no need increasing the quality if it is not needed. You can increase the quality but not be able to notice any difference because you are using other components in the system that distort more than the pure signal. Like the speaker size power and enclosure, the environment you are listening to the sounds in. I suspect no one listens to sin waves for pleasure so what exactly do you want to do?

Then I assume that your needs are not that technical and a simple 256 byte look up table will do, or a 256 int lookup table.

No it is not.

Mike, thank you for pointing this out.
Well, me, - for example - I really love sine waves and the tuning of the frequencies is very important. It’s all in the tuning, I would say. I need the harmonic relationships to be very precise.
When I say I am not too technical I mean that it is not very easy for me to program a DDS lookup table, but it will worth the effort if that’s the price for precision.
I will use the sinewave drone to drive audio exciters and make vibrating surfaces.
I understand that the DAC and the amplifier is quite important to have good quality and I will ask for help to a friend of mine who is audio technician. Suggestions about the other components in the system are welcome, keeping in mind that I will only play a sum of sinewaves and not a hi-end audio file of a classical orchestra.

Antonio

Why won’t you say what you are trying to do?
It sounds to me like Chladni Patterns.
But if you want to keep this a secrete then you have to put some numbers on the words “very precise” as by itself it means nothing.

no secret at all, Mike, I just thought it’s not so interesting.
I am a sound artist and I want to build a series of sound sculptures. In this case I want to print a graphical notation of a just intonation chord like this one on a large metal plate and to make it audible. It’s not Chladny but similar. As you see all the pitches are carefully calculated and so I would like the sound to be. In terms of precision, I aim to a cent of herz approximation (might this be possible).
The electronics will be hidden in the frame, that’s why I need a small, easy to smuggle device.

Thanks for that it really helps.

It is possible but I don’t think it will be audible. Normal people struggle with a quarter interval, which as you know is 50 cents. I also think that 15 frequency components is more than you need, but then it is your project.

So I would use a lookup table with 512 entries of a two byte integers, that will take up 1K of memory. I would calculate this once when you switch the system on. Then for each sample on each wave simply take a pointer and take the sample from the look up table and then increment to pointer. It is this increment value / pointer that will be different for each sin wave you want to produce. The increment can be fractional, do this by having a 16 bit ( int ) pointer and increment and only using the most significant 9 bits as the pointer you use.
Now the problem is what are you going to use as an output? You will need an external A/D, I use the MCP4921 but this is only a 12 bit converter, I guess you might want a 16 bit one. Don’t use any of the home made resistor ladder ones they don’t work at this sort of resolution despite internet idiots claiming they do.

To get started then look at this project:-
http://interface.khm.de/index.php/lab/interfaces-advanced/arduino-realtime-audio-processing/index.html
You can do better than this for an Arduino but playing about with this will give you the idea of how these sort of thing works. You will probably end up with a high end spec Arduino as the Uno has limited memory and speed for this sort of thing.

Thank you for the hint, Mike. A lot of work to do here.
I agree, usually people do not notice the difference of a quarter note, but since my project focuses on microtonal tunings (more specifically to the so called “just intonation” system), it’s really that microtone that makes the difference. You won’t notice the difference if the pitch is single, but you will if you listen to two or more pitches together.
And I do not mean the musical cent, rather a hundredth of a Hertz, so that if I play a 440.0 Hz along with a 440.1 Hz sinewave I will hear one phase cancellation at exactly every 10 seconds.

Yes, the chord in the link is only 8 pitches, but I have more complex ones to work with.

Depends on the size of the lookup table and the interpolation used, I was just explaining that its very fast :slight_smile:

Yes those are called beats, but I suppose you know that. Very useful for relative guitar tuning using the “fifth fret” method.
I have listened to some micro tonal music a few years ago but couldn’t get too excited about it.

@MarkT Yes that is fine. It is a fast processor but it is not cheap. The new Raspberry Pi Pico at only £3.50 is fast enough to do that job and has 264kB of on-chip SRAM. While not having a floating point unit like the Teensy you mentioned, which is a very good system by the way, the Pico has and accelerated floating point compiler option.

Ah, thanks for reminding me, I had made a mental note to get one of these once the initial stampede had subsided…

Well I got my new Pico today, and after a bit of confusion following the instructions (the blink example needs pin 13 changing to pin 25 !), I got it running and did a quick comparison
with the Teensy4.0 - it seems to be over 100 times slower.

1024 point FFT fixed point Teensy4.0: 1.08ms
1024 point FFT float point Teensy4.0: 1.13ms
1024 point FFT fixed point Pico: 124ms
1024 point FFT float point Pico: 205ms