rMP3 Audio with Synchronized Lyrics

Here is an example Arduino sketch that utilizes both the playback and SD card functions of the rMP3.

The sketch plays a song, and displays lyrics.

The lyrics are read from a standard LRC file, which you either already have, or you can easily download (MiniLyrics is a great app for lyrics). LRC files have a time stamp and a lyric per each line. The time stamps are synchronized using a 1/100th second timer (Timer2) on the Arduino.

The Adobe Flash Plugin is needed to display this content.


Sketch

Here is the source code:

rMP3_Lyrics.pde
#include <NewSoftSerial.h>
#include <RogueMP3.h>
#include <RogueSD.h>
#include <avr/io.h>
#include <avr/interrupt.h>
 
NewSoftSerial rmp3_s(6,7);
 
RogueSD filecommands(rmp3_s);
RogueMP3 rmp3(rmp3_s);
 
volatile uint32_t __h__;
 
const char P_song[] PROGMEM = "/Daft Punk - Technologic.mp3";
const char P_lyricfile[] PROGMEM = "/Daft Punk - Technologic.lrc";
 
#define LRCHANDLE 1
#define MAX_LYRIC_LINE 96
 
char lyricline[MAX_LYRIC_LINE];
 
int32_t getnumber(char **str, uint8_t base)
{
  uint8_t c, neg = 0;
  uint32_t val;
 
  val = 0;
  c = **str;
 
  if(c == '-')
  {
    neg = 1;
    (*str)++;
    c = **str;
  }
 
  while(((c >= 'A') && (c <= 'Z'))
      || ((c >= 'a') && (c <= 'z'))
      || ((c >= '0') && (c <= '9')))
  {
    if(c >= 'a') c -= 0x57;              // c = c - 'a' + 0x0a, c = c - ('a' - 0x0a)
    else if(c >= 'A') c -= 0x37;         // c = c - 'A' + 0x0A
    else c -= '0';
    if(c >= base) break;
 
    val *= base;
    val += c;
    (*str)++;
    c = **str;
  }
  return neg ? -val : val;
}
 
 
boolean open_lyricfile(const char *lrcfile)
{
  if (filecommands.open_P(LRCHANDLE, P_lyricfile, OPEN_READ) > 0)
    return true;
  else
    return false;
}
 
 
// return value:
// < 0 EOF
// 0 bad read, no data - skip
// > 0 good read
int8_t read_lyric(uint32_t *nexttime, char **nextlyric)
{
  char *p;
  char *f;
  uint32_t time, time_fraction;
 
  if (filecommands.readln(LRCHANDLE, MAX_LYRIC_LINE, lyricline) >= 0)
  {
    // parse values
    // format: [mm:ss.xxx] lyric text
    // mm: minutes
    // ss.xxx: seconds and fractions of seconds
    // xxx is optional, and can be 2 or 3 decimal places
 
    p = lyricline;
 
    if (*p == '[')
    {
      // good start
      // get minutes
      time = getnumber(&(++p), 10) * 60 * 100;
 
      if (*p == ':')
      {
        // get seconds
 
        time += getnumber(&(++p), 10) * 100;
 
        if (*p == '.')
        {
          // we have optional fractions of seconds
          f = ++p;  // for later (number of decimal places)
          time_fraction = getnumber(&p, 10);
 
          if ((p - f) == 2)
          {
            time += time_fraction;
          }
          else if ((p - f) == 3)
          {
            time += time_fraction/10;
          }
          else
          {
            // what the heck?
            return 0;
          }
 
          // we now have the time in hundredths of seconds in "time"
        }
 
        if (*p == ']')
        {
          // got closing
          // drop any spaces between
          while (*(++p) == ' ');
          *nextlyric = p;
          *nexttime = time;
          return 1;
        }
        else
        {
          // what the heck? no . or ] - whacky stuff
          return 0;
        }
      }
      else
      {
        // missing : and seconds... strange
        return 0;
      }
    }
    else
    {
      // bail out, no [ at the start
      return 0;
    }
  }
  else
  {
    // EOF
    return -1;
  }
}
 
 
 
void setup()
{
  Serial.begin(9600);
  rmp3_s.begin(9600);
 
  rmp3.sync();
  filecommands.sync();
 
  TCCR2A = 0b0000010;
  OCR2A = (F_CPU/1024/100)-1;
  TIMSK2 = 0b0000010;
  TCCR2B = 0b0000111; // ck/1024 prescalar
}
 
 
ISR(TIMER2_COMPA_vect)
{
  __h__++;
}
 
 
 
void loop()
{
  // POC - single run on a single file
 
  uint32_t starttime, nexttime; 
  char *nextlyric;
  boolean playing;
  int8_t lyricstatus;
 
  // nexttime = milliseconds into playback to set pattern
 
  // start
  playing = (rmp3.playfile_P(P_song) == 0) ? true : false;
 
  if (playing)
  {
    if (open_lyricfile(P_lyricfile))
    {
      starttime = __h__;
 
      lyricstatus = 1;
 
      while (playing && lyricstatus >= 0)
      {
        lyricstatus = read_lyric(&nexttime, &nextlyric);
 
        // if lyricstatus == 0, we just skip - it's a bad line or info line
        if (lyricstatus > 0)
        {
          Serial.print("Waiting for: ");
          Serial.print(nexttime, DEC);
 
          // just wait here until we hit the next time (if we do!)
//          while ((millis() - starttime) < (nexttime + t_offset))
          // millis() is seriously hobbled - let's use our own
          while((__h__ - starttime) < nexttime)
          {
            // if we are still playing
            if (rmp3.getplaybackstatus() == 'P')
            {
              // do whatever
            }
            else
            {
              // get outta here!
              playing = false;
              Serial.println(); Serial.println("Playback stopped!");
              break;
            }
          }
 
          // ok, hit pattern time - set the pattern
          if (playing)
          {
            Serial.print(" - ");
            Serial.println(nextlyric);
          }
        }
        else if (lyricstatus < 0)
        {
          // no more lyrics!!
          filecommands.close(LRCHANDLE);
          Serial.println("Out of lyrics!");
        }
        // otherwise, just get the next lyric
      }
    }
    else
    {
      // couldn't open lyrics file
      Serial.println("Couldn't open lyrics file.");
    }
  }
  else
  {
    // couldn't play the song
    Serial.println("Couldn't play the song");
  }
 
  // DONE... for now.
  Serial.println("DONE");
  for (;;);
}

If you need it, here is the settings file (either UMP3.CFG or RMP3.CFG, depending on which module your using):

RMP3.CFG
D0
You could leave a comment if you were logged in.
  • Bookmark at
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at del.icio.us
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at Digg
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at Google
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at StumbleUpon
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at Technorati
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at Facebook
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at Twitter
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at Slashdot
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at Yahoo! Bookmarks
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at Furl
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at Reddit
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at Ask
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at BlinkList
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at blogmarks
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at Ma.gnolia
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at Netscape
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at ppnow
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at Rojo
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at Shadows
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at Simpy
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at Socializer
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at Spurl
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at Tailrank
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at Live Bookmarks
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at Wists
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at Yahoo! Myweb
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at BobrDobr
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at Memori
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at Faves
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at Favorites
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at Newsvine
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at myAOL
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at Fark
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at RawSugar
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at LinkaGoGo
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at Mister Wong
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at Wink
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at BackFlip
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at Diigo
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at Segnalo
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at Netvouz
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at DropJack
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at Feed Me Links
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at funP
  • Bookmark "rMP3 Audio with Synchronized Lyrics" at HEMiDEMi
code/rmp3lyrics.txt · Last modified: 2009/12/05 15:40 by bhagman
Valid CSS Recent changes RSS feed Valid XHTML 1.0