Play Pause Skip Buttons rmp3 help

Hello,

It has been a while since I have last been here, and have my project running. I have made an mp3 player that analyzes music for frequency and causes a motor to vibrate depending on the frequency that is player, so you can "feel" the music. The project can be seen here http://jennifercrossley.com

I am now trying to get the project to the next step, and need to to be able to "play/pause" and skip track. The white buttons on the device are supposed to be doing this. I have what I think to be the correct code, and have it in my code where I think it should be, I just don't know if it is correct, and how I should wire the hardware buttons to my arduino?

#include <RogueMP3.h>
#include <SoftwareSerial.h>
#include <RogueSD.h>

SoftwareSerial rmp3_s(6, 7);

RogueSD filecommands(rmp3_s);
RogueMP3 rmp3(rmp3_s);

int numberOfSongs;
int lastSong;

#define numberOfBands 6
uint16_t bandfreqs[] = { 300, 1000, 9000 };
//uint8_t outputPin[] = { 2, 3, 4 };
uint8_t outputPin[] = { 11, 12, 13 };

uint16_t numfiles = 0;
 
#define MP3PATH "/mp3/"
// you need to put the two double quotes ("") in the middle below,
// because the Arduino IDE looks for unclosed comments.
#define MP3FILTER "/mp3/""*.mp3"

#define THRESHOLD 1

//#define songname "/gold.mp3"


void checkFrequencies(void)
{
  // prepare for up to 23 bands
  uint8_t v[23];

  rmp3.getspectrumanalyzer(v);

  for (uint8_t i=0; i<numberOfBands; i++)
  {
    if (v[i] > THRESHOLD)
      digitalWrite(outputPin[i], HIGH);
    else
      digitalWrite(outputPin[i], LOW);
  }
}

void playNextSong()
{
  uint8_t i;
  char filename[80];
  char path[96];
  int nextSong = 0;

  if (numberOfSongs > 0)
  {
    // Select our next song randomly
    if (numberOfSongs > 2)
    {
      do
        nextSong = random(numberOfSongs);
      while (nextSong == lastSong);
    }
    else if (numberOfSongs == 2)
    {
      // we only have two songs
      if (lastSong == 0)
        nextSong = 1;
      else
        nextSong = 0;
    }

    // now, get our file name from file list

    filecommands.opendir(MP3PATH);

    for (i = 0; i <= nextSong; i++)
    {
      filecommands.readdir(filename, "*.mp3");
    }

    strcpy(path, MP3PATH);
    strcat(path, "/");
    strcat(path, filename);

    rmp3.playfile(path);

    Serial.print("Playing: ");
    Serial.println(path);

    lastSong = nextSong;
  }
  else
  {
    Serial.println("No files to play.");
  }
}


void setup(void)
{
  Serial.begin(9600);
  Serial.println("Started");

  rmp3_s.begin(9600);

  for (uint8_t i = 0; i < numberOfBands; i++)
    pinMode(outputPin[i], OUTPUT);

  Serial.println("Starting sync");
  rmp3.sync();
  Serial.println("Done sync");
    rmp3.stop();
      filecommands.sync();
}



//void playTrack(void)
//{
//  char mp3path[128];
// 
//  numfiles = filecommands.filecount(MP3FILTER);
// 
//  Serial.print("MP3 count: ");
//  Serial.println(numfiles, DEC);
// 
//  // play a file (random)
//  strcpy(mp3path, MP3PATH);
//  filecommands.entrytofilename(mp3path + strlen(mp3path), 127, MP3FILTER, random(0, numfiles));
// 
//  Serial.println(mp3path);
//  rmp3.playfile(mp3path);
// 
//  rmp3.setspectrumanalyzer(bandfreqs, 10);
// 
//  Serial.println("Playing");
//}

int8_t isPlaying(void)
{
  return (rmp3.getplaybackstatus() == 'P' ? 1 : 0);
}


void loop(void)
{
  //if (!isPlaying())
    //playTrack();

  checkFrequencies();
  uint8_t i;
  char filename[80];
  char path[96];
  int nextSong = 0;
  
  filecommands.opendir(MP3PATH);
{
      filecommands.readdir(filename, "*.mp3");
    }

  strcpy(path, MP3PATH);
  strcat(path, "/");
  strcat(path, "*.mp3");  // we have to do this because the IDE thinks that "/*" needs to be terminated everywhere

  numberOfSongs = filecommands.filecount(path);

  lastSong = -1;
  
  char c;
 // uint8_t i;
  int16_t newtime;

  playbackinfo playinfo;

  char status = 'S';
  uint8_t playing = 1;
  uint8_t volume = 20;
  uint8_t boostOn = false;

  volume = rmp3.getvolume();  // this only gets the left volume
  
  playNextSong();

  while(1)
  {
    while(!Serial.available())
    {
      // we should do fancy stuff like flash lights on our Xmas tree here!
      // got lots of time!
      delay(200);

      status = rmp3.getplaybackstatus();
      playinfo = rmp3.getplaybackinfo();

      if (status == 'S' && playing)
        playNextSong();
    }
    
    // OOH!! got a character!
    c = Serial.read();

    switch(c)
    {
      case 'p':
        // pause
        if(status == 'D')
        {
          // fade in
          rmp3.playpause();
          rmp3.fade(volume, 400);
        }
        else if(status == 'P')
        {
          // fade out
          rmp3.fade(100, 400);
          rmp3.playpause();
        }
        else
        {
          // start playing
          playNextSong();
          playing = 1;
        }
        break;
      case 's':
        rmp3.stop();
        playing = 0;
        break;
      case 'n':
        playNextSong();
        playing = 1;
        break;

      case 'e':
        if(boostOn)
        {
          rmp3.setboost(0);
          boostOn = false;
        }
        else
        {
          rmp3.setboost(8, 6, 7, 3);
          boostOn = true;
        }
        break;
      
      case 'a':
        // jump back 5 seconds
        newtime = playinfo.position - 5;
        if (newtime < 0) newtime = 0;
        rmp3.jump(newtime);
        break;

      case 'd':
        // jump forward 5 seconds
        rmp3.jump(playinfo.position + 5);
        break;
        
      case 'k':
        if(volume < 254) volume++;
        if(status != 'D') rmp3.setvolume(volume);
        break;

      case 'i':
        if(volume > 0) volume--;
        if(status != 'D') rmp3.setvolume(volume);
        break;

    }
  }
}

I have commented out parts that I dont think are necessary, but I am not sure.

Any guidance on how to go from here would be greatly appreciated.

Thank you

Jennifer

Hello
The text was translated because I do not speak English well.
Unfortunately, I can not help you in your question, but you can
can be help.
I have a ump3 is I can not run the command:
filecommands.entrytofilename (mp3path + strlen (mp3path), 127, MP3FILTER,
random (0, numfiles));
I have always an error: code -1.
Do you happen to make it work, if so how?
Thank you
Gregory

Hi Jennifer,

A quick look revealed

  • a bug wrt numberOfBands = 6 while the arrays that are associated with it - uint8_t outputPin[] = { 11, 12, 13 }; - only has 3 values

and setup() contains:

for (uint8_t i = 0; i < numberOfBands; i++)
pinMode(outputPin*, OUTPUT);*
so for some values pinMode (0,OUTPUT) will be called
-------
Choosing the nextsong can be easier
```
*void playNextSong()
{
 uint8_t i;
 char filename[80];
 char path[96];
 int nextSong = 0;

if (numberOfSongs == 0)
 {
   Serial.println("No files to play.");
   return;
 }

nextSong = random(numberOfSongs);
 if (nextSong == lastSong)
 {
   nextsong = (nextsong+1)%numberOfSongs;
 }

filecommands.opendir(MP3PATH);

for (i = 0; i <= nextSong; i++)
 {
   filecommands.readdir(filename, "*.mp3");
 }

strcpy(path, MP3PATH);
 strcat(path, "/");
 strcat(path, filename);

rmp3.playfile(path);

Serial.print("Playing: ");
 Serial.println(path);

lastSong = nextSong;
}*
```
-----------
strcpy(path, MP3PATH); << MP3PATH ends with a / so next line should not be needed ...

  • strcat(path, "/");*
  • strcat(path, filename);*
    ---------------
    Furthermore there is a lot of code that should be moved to setup() as it will give the same values every time.
    e.g
  • strcpy(path, MP3PATH);*
  • strcat(path, "/");*
    _ strcat(path, ".mp3"); // we have to do this because the IDE thinks that "/" needs to be terminated everywhere_
  • numberOfSongs = filecommands.filecount(path);*
    and maybe checkFrequencies();
    The big while(1) in loop() can be refactored out I think. refactoring is rewriting the code without adding functionality only make it clearer.
    ----------------
    [ some nonsense removed ]
    Do you have a link to the used libraries?
    Rob

HI Jennifer,

intriged by the application I spend some time tinkering with your sketch. I can't compile it as I dont have the shield or the libs
-- update --> Found the libs, now it compiles under IDE 0022. But still don't have the shield ....

What I did:

  • added comments
  • moved most vars to global
  • moved initialization code from loop() to setup()
  • moved lots of code from the loop() to separate functions
  • added code for three buttons PIN 3,4,5

These three button must be connected to GND on one side and to their pin on the other side (can be tested just with a wire)

Give it a try

#include <RogueMP3.h>
#include <SoftwareSerial.h>
#include <RogueSD.h>


#define MP3PATH "/mp3/"
// you need to put the two double quotes ("") in the middle below,
// because the Arduino IDE looks for unclosed comments.
#define MP3FILTER "/mp3/""*.mp3"

// EQUALIZER 
#define MAXBANDS 23
#define THRESHOLD 1 


// PINNUMBERS FOR BUTTONS
#define NEXTPIN   3
#define PAUSEPIN  4
#define STOPPIN   5


// MP3SHIELD VARS
SoftwareSerial rmp3_s(6, 7);
RogueSD filecommands((Stream&)rmp3_s);
RogueMP3 rmp3((Stream&)rmp3_s);


// EQUALIZER VARS
// TODO size of arrays ???? <<<<<<<<<<<<<<<
#define numberOfBands 6
uint16_t bandfreqs[] = { 
  300, 1000, 9000 };
uint8_t outputPin[] = { 
  11, 12, 13 };


// SONG ADMIN VARS
int numberOfSongs = 0;
int lastSong = -1;
int nextSong = 0;


// FILENAME 
char filename[80];
char path[96];


// STATUS VARS
char status = 'S';
uint8_t playing = 1;
uint8_t volume = 20;
uint8_t boostOn = false;
playbackinfo playinfo;


///////////////////////////////////////////////////////////////////////////////////
//
// SETUP 
//
void setup(void)
{
  // COMMUNICATION
  Serial.begin(9600);
  Serial.println("Started");

  rmp3_s.begin(9600);

  // EQUALIZER
  for (uint8_t i = 0; i < numberOfBands; i++)
  {
    pinMode(outputPin[i], OUTPUT);
  }

 // BUTTONS
  pinMode(NEXTPIN, INPUT);
  pinMode(PAUSEPIN  , INPUT);
  pinMode(STOPPIN   , INPUT);
  digitalWrite(NEXTPIN, HIGH);
  digitalWrite(PAUSEPIN  , HIGH);
  digitalWrite(STOPPIN   , HIGH);
  
  Serial.println("Starting sync");
  rmp3.sync();
  Serial.println("Done sync");
  rmp3.stop();
  filecommands.sync();

  // INIT
  checkFrequencies();

  filecommands.opendir(MP3PATH);
  {
    filecommands.readdir(filename, "*.mp3");
  }
  numberOfSongs = filecommands.filecount(MP3FILTER);

  volume = rmp3.getvolume();  // this only gets the left volume

    // ALLWAYS START PLAYING
  playNextSong();
}

///////////////////////////////////////////////////////////////////////////////////
//
// LOOP (endless until power down ... 
//
void loop(void)
{
  // CHECK FOR SERIAL COMMANDS
  if (Serial.available() > 0)
  {
    char c = Serial.read();
    switch(c)
    {
    case 'p': 
      pause(); 	
      break;
    case 's': 
      stop();	
      break;
    case 'n': 
      next();	
      break;
    case 'e': 
      boost();	
      break;
    case 'a': 
      jump(-5);	
      break;
    case 'd': 
      jump(+5); 
      break;
    case 'k': 
      setVolume(+1); 
      break;
    case 'i': 
      setVolume(-1); 
      break;
    }
  }

  // CHECK FOR BUTTONS
  if (digitalRead(NEXTPIN) == LOW) next();
  if (digitalRead(PAUSEPIN) == LOW) pause();
  if (digitalRead(STOPPIN) == LOW) stop();


  // we should do fancy stuff like flash lights on our Xmas tree here!
  // got lots of time!
  // playinfo = rmp3.getplaybackinfo();


  // if song ended play next one
  status = rmp3.getplaybackstatus();
  if (status == 'S' && playing)
  {
    playNextSong();
  }
}


///////////////////////////////////////////////////////////////////////////////////
//
// TACTILE EQUALIZER I/O
// 
void checkFrequencies(void)
{
  uint8_t v[MAXBANDS];
  rmp3.getspectrumanalyzer(v);
  for (uint8_t i=0; i<numberOfBands; i++)
  {
    if (v[i] > THRESHOLD)
      digitalWrite(outputPin[i], HIGH);
    else
      digitalWrite(outputPin[i], LOW);
  }
}


///////////////////////////////////////////////////////////////////////////////////
//
// MP3 FUNCTIONS
//

void playNextSong()
{
  if (numberOfSongs == 0)
  {
    Serial.println("No files to play.");
    return;
  }

  // randomize
  nextSong = random(numberOfSongs);
  if (nextSong == lastSong)
  {
    nextSong = (nextSong + 1) % numberOfSongs;
  }
  lastSong = nextSong;

  // now, get filename from list
  filecommands.opendir(MP3PATH);
  for (int i = 0; i <= nextSong; i++)
  {
    filecommands.readdir(filename, "*.mp3");
  }
  strcpy(path, MP3PATH);
  strcat(path, filename);

  // and play
  rmp3.playfile(path);

  Serial.print("Playing: ");
  Serial.println(path);
}

int8_t isPlaying(void)
{
  return (rmp3.getplaybackstatus() == 'P' ? 1 : 0);
}

void setVolume(int v)
{
  volume = volume + v;
  volume = constrain(volume, 0, 254);
  if(status != 'D') rmp3.setvolume(volume);
}

void jump(int sec)
{
  uint16_t newtime = max(0, playinfo.position + sec);
  rmp3.jump(newtime);
}

void boost()
{
  if(boostOn)
  {
    rmp3.setboost(0);
    boostOn = false;
    return;
  }
  rmp3.setboost(8, 6, 7, 3);
  boostOn = true;
}

void next()
{
  playNextSong();
  playing = 1;
}

void stop()
{
  rmp3.stop();
  playing = 0;
}

void pause()
{
  status = rmp3.getplaybackstatus();
  if (status == 'D')
  {
    // fade in
    rmp3.playpause();
    rmp3.fade(volume, 400);
    return;
  }
  if (status == 'P')
  {
    // fade out
    rmp3.fade(100, 400);
    rmp3.playpause();
    return;
  }
  // start playing
  playNextSong();
  playing = 1;
}