Ardvoice and playtune - incompatible?

I’m using the ardvoice library by @igvina and it’s been going well but in a different part of the game I’d like to use the playtune library for some music.

The problem is if you call playVoice before you call playTune, then playTune won’t work. If you call playTune first, it will work until you call playVoice.

It seems that something in the playVoice function is not releasing, overwriting or otherwise messing with the initialization (timers I’m assuming), needed by playTune.
PlayTune.ino-arduboy.hex (30.2 KB)

Press A for voice and B for tune

I’ve already tried all different combinations of stopVoice and stopTune and all that, but doesn’t seem to work. Here is some example code that illustrates the problem:

#include <Arduboy2.h>
#include <ArdVoice.h>
#include <ArduboyPlaytune.h>
#include "sounds.h"

Arduboy2 arduboy;
ArdVoice ardvoice;
ArduboyPlaytune tunes(arduboy.audio.enabled);

void setup()
{
  arduboy.begin();
      tunes.initChannel(PIN_SPEAKER_1);
    tunes.initChannel(PIN_SPEAKER_2);
}

void loop()
{
  if (arduboy.pressed(A_BUTTON) ) {
    ardvoice.playVoice(voice);
  }
  if ( arduboy.pressed(B_BUTTON)) {
    tunes.playScore(score);
  }
}

This is pretty deep into the library for me to understand, but any help would be appreciated, it’s kind of the last thing I need to finish my latest game!

ArduboyPlayTune uses timers 1 and 3, and Ardvoice uses timer 4, so there isn’t a timer conflict. I suspect it has to do with both libraries using the same pins (the speaker pins) for output.

If you only generate sound using one library at a time, it could possibly work. However, you may need to make sure the pins are properly (re)configured for the library you want to use after using the other one.

Each library assumes the pin configurations haven’t been touched after initialisation. Therefore, you may need to add code to get the pins set properly for a given library whenever you used the other library last.

I’m sorry I don’t have time at the moment to look into this in detail.

1 Like

Off the top of my head (without actually looking closely at the code, so I could be wrong), I believe ArduboyPlayTune uses the pins as general I/O, whereas Ardvoice has the timer control the pins directly using PWM.

I figured I would need to do something to remove the timers from the pins, or reinitialize them to playtune but…

But yeah, I was hoping you might have some ideas. The next step for me is to step through the code and try to make sense of what is being called in playVoice that is breaking playTunes.

Oh, and yes I’m trying to just play one and then the other. I don’t need them to work at the same time.

So I read through this a few times and I can’t for the life of me actually see where it is writing to any pins? - I guess this is done through direct memory access of the timers and masks, but that’s way beyond my knowledge.

Oh, @MLXXXp I think you are right, it seems the ardVoice takes direct control of the pins even when it is “muted” it is actually “playing” a silent sound… i.e. holding the signal low?

I figured this would stop that?

void  ArdVoice::stopVoice(){
  OCR4A = 127;
  TIMSK4 = 0;   
  sample1 = 0xFF;
}

I’ve commented out everything else, this is indeed the offending bit of code:

    TCCR4A = 0b01000010;    // Fast-PWM 8-bit
    TCCR4B = 0b00000001;    // 62500Hz
	

    // It is faster, but generates an annoying noise/buzz
    //TCCR4B = 0b00000010;    // 62500Hz / 4
	
    OCR4C  = 0xFF;          // Resolution to 8-bit (TOP=0xFF)
    OCR4A  = 0x80;
    OCR4A = 127;

Is there a way to “unset” this?

Yes, there is! You can (like a noob) print out the values that work to the screen. Then, you can manually reinit them by hand when calling the playtune function like so:

    TCCR4A=2;
    TCCR4B=7;
    OCR4C=255;
    OCR4A=0;

Sweet!

The only last thing is you have to make it so ardvoice always inits.

1 Like