6

for a project, I am trying to generate a sound by directly accessing a loudspeaker. I can send a one-bit signal to the speaker and I know how to generate simple sounds by controlling the frequency (due to the rectangular pattern of my curve, it sounds very artificial, but that does not matter).

I would like to do chords, too, though. It must be possible to generate those. What is the general idea behind doing polyphonic sounds with a simple speaker?

So how do I need to go about this if I can only control this one bit stream? Thanks in advance.

UPDATE: I now have four signals, freq(3) down to freq(0) that all carry a frequency. For each of them, I have a signal SE (for "sound enable"), which tells me whether that signal is currently active. I achieve that by a simple "AND", so that every signal is always zero if the corresponding SE signal is zero and that it mirrors the actual frequency when SE is set to one.

So, the remaining problem: How do I connect the four signals? Connecting them with "OR" is probably not good, because with four signals the output will almost always be one. Any suggestions?

  • This is actually a fairly interesting task considering most music these days is in 16-32bit - do keep us posted! –  Jul 15 '11 at 17:53
  • This is something I know nothing about, but googling "dyad frequency 1 bit" (dyad = two notes) I came across some potenitally relevant material and a possible second angle of attack "john chowning fm algorithm" –  Jul 15 '11 at 21:18
  • @horatio: Any links? –  Jul 15 '11 at 22:13
  • So how exactly do you create your signals – all by software, with arbitrary bit sequences? What are the highest possible sample rates? – leftaroundabout Jul 16 '11 at 16:30
  • @leftaroundabout: I'm using a Spartan 3 board, programmed with VHDL. –  Jul 16 '11 at 17:56
  • Ok, just I don't know enough about the programming of this to answer profoundly. Does it essentially work by toggling one bit in some global variable every time you want to change the state of the output (that's the way it was done in the only microcontroller I have ever programmed) or do you have an actual output stream with some given sample rate? – leftaroundabout Jul 16 '11 at 18:36
  • It's not as easy as you described, but I can have some (limited, as I'm limited) control over the output. Manipulating the frequency is almost no problem... –  Jul 16 '11 at 22:24
  • It's comforting to hear that you do have "some" control over the output... but how does it work then, if not by directly manipulating the output state bit, or the stream of these bits? If the output just oscillates by itself and you can only control its frequency, it will be quite a lot more difficult; still possible, but only if you can synchronize the frequency modulation to the oscillator itself. — Or can you use multiple outputs with different frequencies, and do the mixing with external components? That might be the best way. – leftaroundabout Jul 17 '11 at 11:13
  • Right now it looks like I will have a few (probably four) frequencies coming in, which I then have to mix. I am fairly sure I can do pretty much everything with them, I just need to figure out how ;) –  Jul 17 '11 at 12:40
  • I updated the question. Any comments? –  Jul 18 '11 at 15:04
  • You'll need to add the values. Let's call the four channels a, b, c, and d. Each of them can be 0 or 1. Mixing them together is simply (a+b+c+d+2)>>2 (adding 2 to round to closest integer, which will be 0 or 1). Another way of saying this is that if at least two of the inputs are 1, then the output should be 1. You could do that using binary logic, a lookup table (which would fit into 16 bits) or simply by adding and shifting. –  Jul 22 '11 at 18:36
  • @Martin: What happens in moments where I only use two or one of the signals? –  Jul 23 '11 at 10:23
  • @Franz: Instead of shifting by 2 (i.e. divide by 4) you'd have to divide by the number of active channels. –  Jul 23 '11 at 18:47

2 Answers2

4

You might want to look at some of the theory behind additive synthesis - this Wikipedia article simplifies some of it. It is definitely do-able.

Of course, using a single bit (ie speaker at position 0 or position 1) will add in some interesting harmonics which will vary depending on the maximum rate of change of your speaker cone and the maximum rate of change of your signal)

As it happens I couldn't find much in the way of examples, however there is this project which may be what you are after.

Rory Alsop
  • 6,044
  • 4
  • 18
  • 36
4

Thanks for an interesting question! This kept me awake for a while.

It is definitely possible to generate chords even if all you have is a one-bit signal to the speaker. Many games for the ZX Spectrum (3.5 MHz, 8 bit CPU, 1 bit speaker) did this in the 80's.

There are a few techniques I can think of:

  1. Just generate (sine, square etc.) waves of different frequencies and add their values together. After adding them, downconvert to 1 bit. It becomes distorted but not always as bad as you might think.

  2. Add dither (noise) to the samples before downconverting to 1 bit. It makes the quantization noise less audible, but generates other noise. In theory, the dither noise should be more pleasing to the ears than the quantization noise, but it's a matter of taste. When you're downconverting to 1 bit, all theory goes out the window. :-)

  3. Arpeggiate. That is play the notes of the chords in quick succession. 20 milliseconds per note gives the perfect 80's feel to it.

I experimented with those techniques. Here's the result: http://public.librador.com/onebit.wav. Here I used the noise as a percussion effect.

I used a sampling frequency of 22050 Hz. The higher the frequency the better you can make it sound, but it uses more CPU of course. If have a fast CPU you should be able to raise the sampling frequency so much that the dithering noise won't be audible, and then you should be able to generate what is practically 8 bit sounds or more.

  • Well, my waves are not sinus waves (they're rectangular, basically) and it is not easy to do. I am not using a computer, but rather a Spartan 3 board. Shall I simply connect the two frequencies with a bit-wise OR? –  Jul 16 '11 at 11:10
  • @Franz: you could maybe implement a simple dithering by switching between an AND and an OR of both signals very quickly and randomly. – leftaroundabout Jul 16 '11 at 16:35
  • @Franz Sure, you can sum up square waves instead of sine waves. I tried both and I couldn't hear much of a difference, as the end result is a square wave in any case. But much of the nice sound I got was when I altered the relative amplitudes of the audio channels (different decay speeds for each channel gives a nice effect). Adding two binary digits and right shifting is the same as a logical AND, i.e. (a+b)>>1 == (a&b). –  Jul 16 '11 at 22:18
  • Link to http://www.librador.com/data/onebit.wav yields 404 not found. – Stéphane Gourichon Jul 14 '18 at 19:26
  • 1
    Thanks @StéphaneGourichon. Fixed. The link is now http://public.librador.com/onebit.wav – Martin Vilcans Aug 08 '18 at 17:21