pschatzmann / arduino-audio-tools

Arduino Audio Tools (a powerful Audio library not only for Arduino)
GNU General Public License v3.0
1.52k stars 235 forks source link

Mixing two mp3 files on the AudioKit #268

Closed jwktje closed 2 years ago

jwktje commented 2 years ago

Hey Phil,

Firstly, again, massive compliments for this excellent library. Have had many fun making prototypes with it so far. However now I'm running into a challenge.

Ideally I would want my AudioKit to be able to have 2 streams of MP3 that I can control. To be more specific. I wanna be able to start an mp3 of recorded speech at the press of a button, and then while this speech is playing I want to be able to play a second short sound (essentially trigger a sound effect) with the press of another button.

I don't want the first sound to stop when the second sound is triggered. And I'd want to be able to trigger the second short sound at will while the first one is playing.

I tried making it work by adapting the InputMixer example but my code quickly became a copy-and-pasted mess that got me nowhere.

So do you know if this is even possible with your library, and if so; do you have some pointers to get me started or an example you could point me to?

Thanks a bunch in advance. I would also be glad to pay you for your time in helping me with this.

pschatzmann commented 2 years ago

You can not mix on the input side because only decoded PCM data can be mixed. So please try to use the OutputMixer class. Please note, there are some recent corrections but I am not sure if everything is working properly yet. If you decode mp3 make sure that the buffer size is specified big enough when calling begin: e.g. mixer.begin(4608);

A more efficient way to deal with this would be that you just play your short sound with a StreamCopy copyAll(). This will interrupt your original sound with the short sound only to continue it after the short sound has played...

jwktje commented 2 years ago

Sounds good. Would you have a basic example on how I would use the OutputMixer class? If not, I could try to do something myself but it's a lot to get my head around currently. So any help would be amazing

jwktje commented 2 years ago

Here is my super naive attempt to create a sketch, that doesn't even compile because my initialisation of the OutputMixer is wrong.

But am I even remotely approaching it right this way?

#define USE_SDFAT
#include "AudioFileSourceSD.h"
#include "AudioGeneratorMP3.h"
#include "AudioTools.h"
#include "AudioLibs/AudioKit.h"
#include "AudioCodecs/CodecMP3Helix.h"

SdSpiConfig sdcfg(PIN_AUDIO_KIT_SD_CARD_CS, DEDICATED_SPI, SD_SCK_MHZ(10) , &AUDIOKIT_SD_SPI);
AudioKitStream kit;
OutputMixer mixer(kit, 2);
StreamCopy copier_speech(out_speech, mixer);
StreamCopy copier_sfx(out_sfx, mixer);

AudioFileSourceSD *file_speech=nullptr;
AudioFileSourceSD *file_sfx=nullptr;
AudioGeneratorMP3 *mp3_speech=nullptr;
AudioGeneratorMP3 *mp3_sfx=nullptr;
AudioOutputWithCallback *out_speech=nullptr;
AudioOutputWithCallback *out_sfx=nullptr;

void setup() {
  //Logging
  AudioLogger::instance().begin(Serial, AudioLogger::Warning);

  //AudioKit
  auto cfg = kit.defaultConfig(TX_MODE);
  kit.setVolume(100);
  kit.begin(cfg);

  //Sources
  file_speech = new AudioFileSourceSD(); 
  file_sfx = new AudioFileSourceSD(); 
  mp3_speech = new AudioGeneratorMP3();
  mp3_sfx = new AudioGeneratorMP3();
  out_speech = new AudioOutputWithCallback(512,5);
  out_sfx = new AudioOutputWithCallback(512,5);

  //Files
  const char* filename_speech = "/speech.mp3";
  const char* filename_sfx = "/sfx.mp3";

  if (file_speech->open(filename_speech)) {
    mp3_speech->begin(file_speech, out_speech);
    Serial.printf("Playback of '%s' begins...\n", filename_speech);
  } else {
    Serial.printf("Can't find '%s'...\n", filename_speech);
  }

  if (file_sfx->open(filename_sfx)) {
    mp3_sfx->begin(file_sfx, out_sfx);
    Serial.printf("Playback of '%s' begins...\n", filename_sfx);
  } else {
    Serial.printf("Can't find '%s'...\n", filename_sfx);
  }

  //Start mixer
  mixer.begin();
}

void loop() {
  copier_speech.copy();
  copier_sfx.copy();
}
pschatzmann commented 2 years ago

I don't think there is enough memory to do 2 mp3 decodings. A simple example can be found here

jwktje commented 2 years ago

I tested this and there isn't enough memory. Closing this