Go Down

Topic: Run two speakers simultaneously (Read 3695 times) previous topic - next topic

Dagmar

Hi all,

Im trying to make some kind of simple portable karaoke machine. Therefor I want three speakers to make sound at the same time. (I know I named it two speakers, but I guess when you know how to build two, the third one should not be that hard, right?)   
I tried it with an if statement, that the speakers have the same statements, but it will first run the first one, and when it is done the second one.
Is there some kind of code which will say "do this and this simultaneously"?

My code at this point is (including the if statements & setup for LCD)

Code: [Select]
/*
int ledPin2;
int ledPin1;
int buzzerPin = 9;
int buzzerPin1 = 8;
int counter = 0;

const int fs = 46;
const int cs = 69;
const int e = 82;
const int fs1 = 93;
const int c = 65;
const int d = 73;
const int b = 62;
const int eh = 330;
const int fsh = 185;
const int fsh1 = 370;
long time;

// include the library code:
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);


const int beep(int note, int duration)
  {
  //Play tone on buzzerPin
  tone(buzzerPin, note, duration);
if(counter % 2 == 0)
  {
    digitalWrite(ledPin1, HIGH);
    delay(duration);
    digitalWrite(ledPin1, LOW);
  }
  else
  {
    digitalWrite(ledPin2, HIGH);
    delay(duration);
    digitalWrite(ledPin2, LOW);
  }
  //Stop tone on buzzerPin
  noTone(buzzerPin);

  delay(50);
    counter++;

  }
 
 
const int beep1(int note, int duration)
  {
  //Play tone on buzzerPin
  tone(buzzerPin1, note, duration);
if(counter % 2 == 0)
  {
    digitalWrite(ledPin1, HIGH);
    delay(duration);
    digitalWrite(ledPin1, LOW);
  }
  else
  {
    digitalWrite(ledPin2, HIGH);
    delay(duration);
    digitalWrite(ledPin2, LOW);
  }
  //Stop tone on buzzerPin
  noTone(buzzerPin1);

  delay(50);
    counter++;

  }


void setup() {
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  // Print a message to the LCD.
   pinMode(buzzerPin, OUTPUT);
   time=millis();
 
}

void loop() {
  // set the cursor to column 0, line 1
  // (note: line 1 is the second row, since counting begins with 0):
  lcd.setCursor(0, 0);
  lcd.print("She was more like");
    lcd.setCursor(0, 1);
  // print the number of seconds since reset:
  lcd.print("A beauty queen");
 
 
 
  if (millis()>10){
    //BASE
    beep(fs, 250);   beep(cs, 250);   beep(e, 250);   beep(fs1, 250);   beep(e, 250);  beep(cs, 250);   beep(b, 250);   beep(cs, 250);
  }
  if (millis()>10){
    //chords
     beep1(fsh, 300); delay(400); beep1(eh, 1000); delay(400); beep1(fsh1, 500); delay(300); beep1(eh, 1000); delay(400);
  }
   
}


I already found a code that makes the speakers work simultaneously, but I don't really know how it works. Also I tried the timing with this code, and that was also harder..
Anyways this is the code which I found:

Code: [Select]

int speakerOut = 9;
int speakerOut1 = 7;
int speakerOut2 = 8;
byte names[] = {'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C'}; 
int tones[] = {110, 69, 73, 1432, 1275, 1136, 1014, 956};
byte melody[] = "2d2a1f2c2d2a2d2c2f2d2a2c2d2a1f2c2d2a2a2g2p8p8p8p";
// count length: 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
//                                10                  20                  30
int count = 0;
int count2 = 0;
int count3 = 0;
int MAX_COUNT = 24;
int statePin = LOW;

void setup() {
  Serial.begin(9600);

}

void loop() {
  analogWrite(speakerOut, 0);   
   analogWrite(speakerOut1, 1);
    analogWrite(speakerOut2, 2);
  for (count = 0; count < MAX_COUNT; count++) {
    for (count3 = 0; count3 <= (melody[count*2] - 48) * 30; count3++) {
      for (count2=0;count2<8;count2++) {
        if (names[count2] == melody[count*2 + 1]) {     
          analogWrite(speakerOut,500);
          analogWrite(speakerOut1,500);analogWrite(speakerOut2,500);
          delayMicroseconds(tones[count2]);
          analogWrite(speakerOut, 0);
          analogWrite(speakerOut1, 0);
          analogWrite(speakerOut2,500);
          delayMicroseconds(tones[count2]);   
     }
        if (melody[count*2 + 1] == 'p') {
          // make a pause of a certain size
          analogWrite(speakerOut, 0);
          delayMicroseconds(500);
        }
      }
    }
  }
}

Thanks in advance!

Nick Gammon

Quote
Run two speakers simultaneously


...

Quote
Therefor I want three speakers to make sound at the same time ...


I like it!

Quote
Code: [Select]
  if (millis()>10){


This would be true most of the time wouldn't it?
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

PeterH


I want three speakers to make sound at the same time.


Do you mean you want to superimpose some beeps etc over the audio track?

Do you actually have two (or three) audio channels? (If so - why? Do you have three microphones?)
I only provide help via the forum - please do not contact me for private consultancy.

Dagmar

Quote
Do you actually have two (or three) audio channels? (If so - why? Do you have three microphones?)

Microphones? Did you mean speakers?
I want to work with the beeps the arduino can make. So there will be no "real audio" track (just the beeps like in the expample of play melody arduino has http://www.arduino.cc/en/Tutorial/PlayMelody). To make it sound like actual music I want to make a base line, a singing line and maybe some chords or something, make it recognizable.
For instance that it would play an C E G all at the same time from different speakers...
So there will be three outputs, I'm not really sure it they are then audio channels? (Do I use an audio channel?)

Quote
if (millis()>10){

This would be true most of the time wouldn't it?


Haha yes! I know, but I was hoping that my arduino would think "hey, these are the same, I should play them simultaneously". That did not work out..

dc42

I think you will find it hard to get sufficient frequency accuracy for more than one channel at a time on the Uno, because the Uno has only one 16-bit counter/timer. Also you'll be limited to square wave output. Why not use the Arduino to control a synthesiser chip? Something like http://hackaday.com/2011/12/17/midi-synth-arduino-shield/.
Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

GoForSmoke

Why not just feed 3 powered speakers the same 1 signal?

Nick Gammon on multitasking Arduinos:
1) http://gammon.com.au/blink
2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

PeterH


Microphones? Did you mean speakers?


No, I meant microphones.

The Arduino output is going to be a nasty harsh square wave and if that's all the speakers are producing then I can't imagine this system sounding at all pleasant - I guessed you were going to overlay these beeps over an audio track as some sort of prompt or timing hint. Given that you mentioned three speakers, I guessed that you would have three independent output channels. If they aren't going to be overlaid on separate channels, I couldn't see any point in producing separate outputs from the Arduino. I don't really understand why you would want more than one microphone and one output channel for karaoke but then I don't know how these things work and I guessed you might be trying to have multiple people singing at the same time or something like that.

So, what's the plan - are the three speakers actually playing different sounds?
I only provide help via the forum - please do not contact me for private consultancy.

klc519

hi! i am programming a melody and a harmony with the arduino, and i am trying to repeat the melody with a pause in between, but instead of pausing, the harmony plays a random note and then plays something other than I programmed. I tried making the melody all rests and left the harmony alone, but the harmony then played something really different than I programmed. why isn't the harmony working the way I want it to?

i've attached pictures of my code

cr0sh

Think about this - when you listen to a cheap, single speaker radio - how do you think all of those sounds are produced by one speaker? Therefore - why would you need multiple speakers to make polyphonic sound?

The basic answer is you don't (going the opposite direction - do you think you have more than one eardrum in each ear?).

Sound is formed by pressure changes in the air - which is why sound doesn't travel in a vacuum. Different sounds change the pressure in multiple ways - but those pressure changes "add up" to form one overall change in pressure.

In effect - you only hear a single "sound" all the time - but it is composed of multiple overlapping sounds summed together.

So - that's what you do to reproduce multiple sounds.

Each sound would be made by generating (in code) a waveform - a series of numbers (representing voltage levels) which represent a particular waveform (square, sinusoidal, triangle, etc).

Higher frequency sounds have numbers which change quicker (that is, the delta difference between any two sequential numbers is larger), while lower frequency sounds have numbers which change slower.

Louder sounds are those with larger overall "swings" in the waveform, while quieter sounds have smaller swings - around the "baseline" voltage level, which is generally 0 volts (but can be offset - usually to half the maximum value - so if you are using 0-5 volts, the baseline should be 2.5 volts).

So - you generate these values. Let's say you have two sounds of two different frequencies and waveform types. At any one point in time, you will have a pair of numbers. You only want a single number, though, to output as a voltage level. So - what do you do? Well, remember when I said sound waves get "summed" - because they all go through the same air? Well - that's what you do! Add them together!

There's your final number (if you have more than two sounds, just keep adding them together).

Now - generally the numbers are going to have a positive and negative swing to them. Let's say you are going for 8 bit audio (not terrible, but not great, either). That's 256 values, right? So - for your sound generation algorithm, you would want to swing the numbers between -127 and 128 (8 bit signed). When you add each of the individual numbers (for each waveform) together, because of the positive and negative values, things will add up ok.

But sometimes - your value will be larger than 128 - or smaller than -127! So what does this mean? Well - it means you have to "clamp" the values at these values. They "slam" up against these limits. If you looked at them on an oscilloscope, you would see this. This is known as "clipping" - and it sounds just as harsh as you might imagine. Its a form of distortion.

So - this number you now have - what do you do with it? Well - you need to get it out to the real world; one way is to use a Digital-to-Analog Converter (known in audio as a DAC). This takes your number (which you shift to be a number from 0-255 by adding 128 to the number) - converts it to 8-discrete bits, then runs it through a special bit of conversion hardware (a simple method is called a resistor ladder) - and out the end comes an analog voltage - which can then be further manipulated (typically by level shifting the voltage, as well as some filtering and amplification).

Congratulations - if you have come this far, you know the bare-bones basics of audio synthesis. Simple pseudocode would be something like:

Code: [Select]
w1 = generate_wave_sin(t, f1, v1); // t is time units, f1-f3 are frequencies, v1-v3 are volume levels
w2 = generate_wave_sqr(t, f2, v2);
w3 = generate_wave_tri(t, f3, v3);

// final soundwave generation
w = clamp(w1 + w2 + w3, -127, 128); // keep the waveform within bounds (clipping!)

w = w + 128; // shift to 0 - 255

output_to_DAC(w); // which will generate the actual sound


All of this has to happen very fast (2-4x faster than your highest frequency, IIRC) - but the Arduino has plenty of speed for this. In fact, it has an over-abundance. As an anecdote - my first computer ran at 0.789 MHz (yep - not even a full 1 MHz!) - and it had several music generation programs that could output 4-note polyphonic sound. This was all done with the CPU (because this particular computer didn't have a built-in synthesizer chip, unlike many of its contemporaries).

Note that you could build your own DAC as well - build a ladder resistor DAC (8 bits is most feasible) - and hook it to 8 pins of a single output port on the Arduino. Then use direct pin (port) manipulation to set the HIGH/LOW voltages on the resistors (you can't use digitalWrite() because it won't set the pins fast enough - and you will instead get "jitter" on the output lines to the DAC, which results in distorted sound).

Hope this helps somewhat - as you can see, while it seems easy on the surface, when you get down into the weeds, it really becomes much more complex (entire books on sound theory and synthesis have been written on the subject - if you really want to understand this, I suggest you invest some time into them).
I will not respond to Arduino help PM's from random forum users; if you have such a question, start a new topic thread.

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy