MediaPlayer class

With the Arduino Wave Shield you can play audio files, controlled by the Arduino.

Arduino wave shield
Arduino wave shield

The Arduino Wave Shield is not easy to use and requires a lot of code. Therefore I have made an interface for it, the MediaPlayer class. The Wave Shield is now easy to use, like a CD player. You only have to install the libraries MediaPlayer and AF_Wave and add these lines to the code:

#include <MediaPlayer.h>
#include <util.h>
MediaPlayer mediaPlayer;

Now we can play WAV files by using functions as:

play(), stop(), pause(), resume()

The class is idiot proof, it is allowed to use any erroneous combination of these functions, such as stop() before using play(). You can use the MediaPlayerTest project to learn about all the opportunities of the MediaPlayer class.

Install procedure

Place these libraries in the Arduino library folder \Arduino-0015\hardware\libraries\:

MediaPlayer
AF_Wave

A library is just a folder with the C++ code (.cpp) and a header (.h) file. The object file (.o) will automatically be generated if it is missing. Note that I have tested the MediaPlayer class with the  AF_Wave library version from 18-02-09. For troubleshooting see HERE.

Test procedure

You can test the MediaPlayer class with the Arduino testproject MediaPlayerTest.

  • Put some WAV files (music) to the SD card. 
  • Start Arduino and open MediaPlayerTest.pde.
  • Change the WAV filenames in MediaPlayerTest to the song file names. 
  • Compile, ignore error messages and compile it again. The error messages should disappear now.
  • Run the MediaPlayerTest software on the Arduino and use the serial monitor to view what happens and listen to the music.

It is preferable to use the Atmega 328p, which has more memory. Else the Wave Shield may be unstable. But the Atmega 168 can still be used here. Do you have any questions, see the Arduino forum.

MediaPlayer test program

MediaPlayerTest.pde

This is your application.

#include <avr/pgmspace.h>
#include <util.h>
#include <MediaPlayer.h>
 
int onboardLed = 13; // digital
int frontLed = 9; // digital
MediaPlayer mediaPlayer; // create only one object, must be global
 
void loop()                     
{ //testAll();
  
  putstring("\nThese files are on the SD card:\n"); mediaPlayer.exploreSDcard(true);
 
  putstring("\nSD card file count =  ");  Serial.print(mediaPlayer.exploreSDcard());
  
  if(!mediaPlayer.play("Notexist")) putstring("\nFile not exist"); // result is false
 
  putstring("\nSD card filename of file no. 3 = "); Serial.print(mediaPlayer.fileName(3));
  
  putstring("\nPlay ANOUK1.WAV"); mediaPlayer.play("ANOUK1.WAV");
  delay(2000);
  
  putstring("\nPlay ILSE1.WAV without using stop()"); mediaPlayer.play("ILSE1.WAV");   
  while (mediaPlayer.isPlaying()) { putstring("."); delay(50);}
  
  putstring("\nPlay  KREZIP1.WAV"); mediaPlayer.play("KREZIP1.WAV"); 
  delay(2000);
  putstring("\nPause"); mediaPlayer.pause(); 
  if(mediaPlayer.onPause()) putstring("\nMediaPlayer on pause");
  delay(500); 
  putstring("\nResume"); mediaPlayer.resume();
  delay(2000);  
  putstring("\nStop"); mediaPlayer.stop(); 
 
  playComplete("ANOUK1.WAV"); 
         
  putstring("\nPlay all songs");
  for(int i=1; i<=mediaPlayer.exploreSDcard(); i++) playComplete(i); 
  printAvailableRAM(); 
}

TestAll.pde

void testAll()
{ testMediaPlayer1(); 
}
 
void testMediaPlayer1() // 776 bytes
{ putstring("\nTest mediaPlayer1");
  
  putstring("\nPlay BABY.WAV"); mediaPlayer.play("BABY.WAV");
  putstring("\nPlay BABY.WAV again"); mediaPlayer.play("BABY.WAV"); 
  delay(500);
  putstring("\nStop"); mediaPlayer.stop(); 
  putstring("\nStop again"); mediaPlayer.stop(); 
  putstring("\nPlay BABY.WAV"); mediaPlayer.play("BABY.WAV"); 
  delay(500);
  
  putstring("\nPlay DOG.WAV without stop"); mediaPlayer.play("DOG.WAV");   
  while (mediaPlayer.isPlaying()) { putstring("."); delay(50);}
  
  putstring("\nPlay  KREZIP1.WAV"); mediaPlayer.play("KREZIP1.WAV"); 
  delay(2000);
  putstring("\nPause"); mediaPlayer.pause(); 
  delay(500); 
  putstring("\nResume"); mediaPlayer.resume(); 
  delay(2000);
  putstring("\nPause"); mediaPlayer.pause(); 
 
  putstring("\nPlay YES.WAV during pause"); mediaPlayer.play("YES.WAV"); 
  delay(2000);
  putstring("\nStop"); mediaPlayer.stop(); 
  
  putstring("\nResume without play"); mediaPlayer.resume(); 
  putstring("\nPause without play"); mediaPlayer.pause(); 
  putstring("\nResume without play"); mediaPlayer.resume(); 
  putstring("\nStop without play"); mediaPlayer.stop(); 
  putstring("\nStop without play"); mediaPlayer.stop(); 
}

MediaPlayerTestFunctions.pde

void setup() // Run once, when the sketch starts
{ pinMode(onboardLed, OUTPUT); // Sets the digital pin as output
  pinMode(frontLed, OUTPUT); // Sets the digital pin as output
  Serial.begin(9600); 
}
 
void blinkLed()
{ for(byte i=0; i<3; i++)
  { digitalWrite(onboardLed, HIGH);  digitalWrite(frontLed, HIGH);      
    delay(200);                 
    digitalWrite(onboardLed, LOW); digitalWrite(frontLed, LOW);  
    delay(200);
  }
}  
 
void playComplete(char* fileName) 
{ putstring("\nPlay complete: ");   
  Serial.print(fileName);
  mediaPlayer.play(fileName);
  while (mediaPlayer.isPlaying()) 
  { putstring(".");
    delay(100);
  }
}
 
void playComplete(const int fileNumber) 
{ playComplete(mediaPlayer.fileName(fileNumber));
}
 
void printAvailableRAM() // 590 bytes
{ int size = 1024;
  byte *buf;
  while ((buf = (byte *) malloc(--size)) == NULL);
  free(buf);
  putstring("\nAvailable RAM: ");
  Serial.print(size);
}

MediaPlayer library

MediaPlayer.cpp

/*
This class is an interface for the Arduino Wave Shield
Designed by Albert van Dalen
Version 20-10-2011
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/
 
#include "MediaPlayer.h"
#include <avr/pgmspace.h>
#include "util.h"
#include "WProgram.h"
 
char globalTempFileName[13]; //  not nice but efficient
 
// Pins 2, 3, 4, 5 are used by the Arduino Wave Shield
 
MediaPlayer::MediaPlayer():
pausePosition(0)
{ openMemoryCard(); 
  card.reset_dir();
  setupWaveShieldPins();
}
 
MediaPlayer::~MediaPlayer()
{ stop();
}
 
void MediaPlayer::setupWaveShieldPins() 
{ pinMode(2, OUTPUT); 
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
}
 
bool MediaPlayer::play(char *fileName)
{ stop();
  file = card.open_file(fileName);   
  if (!file) 
  { putstring(" Couldn't open WAV file"); 
    return false;
  }  
  if (!waveFile.create(file)) 
  { putstring(" Not a valid WAV file"); 
    return false;
  }
  waveFile.play(); 
  return true;
}
 
void MediaPlayer::resume() 
{ if (!isPlaying() & (bool)file) // If not stopped
  { waveFile.seek(pausePosition);
    waveFile.play();
  }
}
 
void MediaPlayer::stop()
{ if (isPlaying()) waveFile.stop(); 
  if (file) file = closeFile(file); 
  card.reset_dir(); // if not done after card.get_next_name_in_dir() do it here 
  pausePosition = 0;
}
 
void MediaPlayer::pause()
{ if (isPlaying()) 
  { pausePosition = waveFile.getSize() - waveFile.remainingBytesInChunk; 
    waveFile.stop();
  }
}
 
File MediaPlayer::closeFile(const File file) // This should be done in AF_Wave.cpp
{ card.close_file(file);
  return 0;
}
 
void MediaPlayer::openMemoryCard()
{ if (!card.init_card()) 
  { putstring_nl("Card init failed"); 
    return;
  }
  if (!card.open_partition()) 
  { putstring_nl("No partition"); 
    return;
  }
  if (!card.open_filesys()) 
  { putstring_nl("Couldn't open filesys"); 
    return;
  }
 if (!card.open_rootdir()) 
  { putstring_nl("Couldn't open dir"); 
    return;
  }
}
 
bool MediaPlayer::isPlaying()
{ return waveFile.isplaying;
}

MediaPlayer.h

#ifndef MEDIAPLAYER_H
#define MEDIAPLAYER_H
 
/*
This class is an interface for the Arduino Wave Shield
Designed by Albert van Dalen
Version 20-10-2011
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/
 
#include <AF_Wave.h>
#include "wave.h"
 
class MediaPlayer
public:
  MediaPlayer();
  ~MediaPlayer();
  bool play(char *fileName);
  void resume(); 
  void stop();
  void pause();
  bool isPlaying();
  bool onPause();
  int exploreSDcard(const bool print=0);
  char* fileName(const int fileNumber);
  
private:
  File closeFile(const File file);
  void openMemoryCard();
  void setupWaveShieldPins();
 
  AF_Wave card;
  File file; // struct fat16_file_struct*
  Wavefile waveFile;
  uint32_t pausePosition;    
};
 
#endif

 

 

 

Do you have any comments? Please let me know.
Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.