Pages: [1] 2   Go Down
Author Topic: Interface class for the Arduino Wave Shield  (Read 4424 times)
0 Members and 1 Guest are viewing this topic.
Maastricht Netherlands
Offline Offline
Newbie
*
Karma: 0
Posts: 34
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Using the Arduino Wave Shield (http://www.ladyada.net/make/waveshield) was not easy and requires writing too much code. Therefore I have made an interface for it, the MediaPlayer class. The class is very easy to use.

You only have to add the MediaPlayer class to your project and add these three lines:
#include "util.h"
#include "MediaPlayer.h"
MediaPlayer mediaPlayer;

Now we can play WAV files by using functions as:
play(), stop(), pause(), resume() etc.
The class is idiot proof, it is allowed to use any erroneous combination of these functions, such as stop() before using play(). Use the MediaPlayerTest project to learn about all the opportunities of the MediaPlayer class.

This is optional: the function blinkLed() requires on the wave shield card the onboard LED LED2, resistor R10 (470 ohm) and a wire between pin WP2 and digital I/O pin 6.

Procedure:
Create a folder with the name “MediaPlayerTest” and add the 4 files to it. Start Arduino and open MediaPlayerTest.pde.
Put some WAV files (songs) on the SD card. Change the 3 filenames in MediaPlayerTest to your song names. Upload to the Arduino and use the serial monitor to view (and listen) what happens.

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, please put a reply!

File MediaPlayerTest.pde, THIS IS YOUR APPLICATION:
Code:
#include <avr/pgmspace.h>
#include "util.h"
#include "MediaPlayer.h"

int onboardLed = 13; // digital
MediaPlayer mediaPlayer; // create only one object, must be global

void loop()                    
{ blinkLed();
  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

  char fileName[13];
  putstring("\nSD card filename of file no. 3 = ");
  mediaPlayer.fileName(3, fileName); // get the filename
  Serial.print(fileName);
  
  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);
}

File MediaPlayer.pde, don't change
Code:
// This class is an interface for the Arduino Wave Shield
// 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;
}

bool MediaPlayer::onPause()
{ return !isPlaying() & (bool)pausePosition;
}

int MediaPlayer::exploreSDcard(const bool print)
{ int fileCount=0;
  char fileName[13];
  card.reset_dir();
  while(card.get_next_name_in_dir(fileName))
  { fileCount++;
    if(print)
    { Serial.print(fileCount);
      putstring(". ");
      Serial.println(fileName);
    }
  }
  card.reset_dir();
  return fileCount;
}

void MediaPlayer::fileName(const int fileNumber, char* _fileName)
{ int fileCount=1;
  char fileName[13];
  card.reset_dir();  
  while(card.get_next_name_in_dir(fileName))
  { if(fileCount++==fileNumber) break;
    else fileName[0]=0;
  }
  card.reset_dir();  
  strncpy(_fileName, fileName, 12); // fill the string argument
  _fileName[12] = 0;    
}


File MediaPlayer.h, don't change
Code:
#ifndef MEDIAPLAYER_H
#define MEDIAPLAYER_H

#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);
  void fileName(const int fileNumber, char* _fileName);
  
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

File MediaPlayerTestFunctions.pde
Code:
void setup() // Run once, when the sketch starts
{ pinMode(onboardLed, OUTPUT); // Sets the digital pin as output
  Serial.begin(9600);
}

void blinkLed()
{ for(byte i=0; i<3; i++)
  { digitalWrite(onboardLed, HIGH);        
    delay(200);                
    digitalWrite(onboardLed, 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)
{ char fileName[13];
  mediaPlayer.fileName(fileNumber, fileName);
  playComplete(fileName);
}

« Last Edit: January 30, 2009, 10:08:38 am by avandalen » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 5
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

THANK YOU!!! This is extremely helpful.
Logged

Maastricht Netherlands
Offline Offline
Newbie
*
Karma: 0
Posts: 34
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

New version: 1.2.
This version is a little more efficient, it saves 222 bytes of code.
The function mediaPlayer.fileName() is improved.

File MediaPlayerTest.pde, THIS IS YOUR APPLICATION:
Code:
#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()                    
{ blinkLed();
  
  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)); // now easier
  
  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();
}

File MediaPlayer.pde, don't change
Code:
// This class is an interface for the Arduino Wave Shield
// 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;
}

bool MediaPlayer::onPause()
{ return !isPlaying() & (bool)pausePosition;
}

int MediaPlayer::exploreSDcard(const bool print) // 104 bytes, was 156
{ int fileCount=0;
  card.reset_dir();
  while(card.get_next_name_in_dir(globalTempFileName))
  { fileCount++;
    if(print)
    { Serial.print(fileCount);
      putstring(". ");
      Serial.println(globalTempFileName);
    }
  }
  card.reset_dir();
  return fileCount;
}

char* MediaPlayer::fileName(const int fileNumber) // 82 bytes, was 158
{ int fileCount=1;
  card.reset_dir();  
  while(card.get_next_name_in_dir(globalTempFileName))
  { if(fileCount++==fileNumber) break;
    else globalTempFileName[0]=0;
  }
  card.reset_dir();  
  return globalTempFileName;
}

File MediaPlayer.h, don't change
Code:
#ifndef MEDIAPLAYER_H
#define MEDIAPLAYER_H

#include <AF_Wave.h>
#include "wave.h"

char globalTempFileName[13]; //  not nice but efficient

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

File MediaPlayerTestFunctions.pde
Code:
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);
}
Logged

Lisbon . Portugal
Offline Offline
Jr. Member
**
Karma: 0
Posts: 63
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Oh boy this class is absolutely amazing! Great work!!
Thank you for the effort and for sharing!

I just have a question though, when you say to use a jumper wire between WP2 and digital9, what do you mean by WP2.. where is it ?   :smiley
« Last Edit: February 21, 2009, 02:22:27 pm by guibot » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 1
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I was working with your 1.2 version.  I tried in both Arduino 15 and 13 and neither worked.  Here were the errors I was getting in MediaPlayer.pde:

Code:
error: 'MediaPlayer' has not been declared In function 'int MediaPlayer()':
 At global scope:
 In function 'bool play(char*)':
 At global scope:
 In function 'void resume()':
 At global scope:
 In function 'void stop()':
 At global scope:
 In function 'void pause()':
 At global scope:
 In function 'void openMemoryCard()':
 At global scope:
 In function 'bool isPlaying()':
 At global scope:
 In function 'bool onPause()':
 At global scope:
 In function 'int exploreSDcard(bool)':
 At global scope:
 In function 'char* fileName(int)':
 At global scope:
 In function 'void loop()':
 In function 'void playComplete(char*)':
 In function 'void playComplete(int)':

If I then add #include "MediaPlayer.h" to MediaPlayer.pde I get the following error:

Code:
n member function 'bool MediaPlayer::play(char*)':
error: 'putstring' was not declared in this scope In member function 'void MediaPlayer::openMemoryCard()':
 In member function 'int MediaPlayer::exploreSDcard(bool)':

I'm very new to this and I'm stumped.  I really like the idea of easy to understand class because all I want to do is stop/pause/start based on a timer I input.

Thanks
« Last Edit: April 04, 2009, 05:45:55 pm by jmmoses » Logged

Michigan
Offline Offline
Newbie
*
Karma: 1
Posts: 33
IR Combat
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I get the same error on the 0015 /dueminalove.

I have not been able to get this to compile, but can get the default library demos to work.  
Logged

IR Combat laser tag developer/inventor

0
Offline Offline
Newbie
*
Karma: 0
Posts: 2
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I get an error when I try to compile the my sketch. I just added the following into a working sketch:

#include "util.h"
#include "MediaPlayer.h"
MediaPlayer mediaPlayer;

I try to compile it and I get this error:

hardware\libraries\AF_Wave/util.h:1: error: 'uint8_t' has not been declared


Another questions, are the pins used by the waveshield the default pins Ladyada uses or have you chamged them?
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 2
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Never mind got it Working... smiley-grin
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 3
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi I'm really new physical computing and for that fact programming. I was wondering where I could get these files to make the sketch work properly:
util.h
pgmspace.h
AF_Wave.h
wave.h
They are called in the other sketches but I can't find them in the Arduino hardware library folder and there aren't sketches for them here.

Thanks,

RobertC
Logged

London
Offline Offline
Faraday Member
**
Karma: 8
Posts: 6240
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

the library for the wave shield is here: http://www.ladyada.net/media/wavshield/AFWave_18-02-09.zip
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 15
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Has anyone made an interface like this for the WaveHC library?
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi there,

I am facing a little problem with the code and would just like to ask if anyone might be able to help me on this?

I loaded the Arduino Uno with the cose for the MediaPlayer and also made the necessary preparation/steps to load my SD card with 3 audio .wav files.

However, I am receiving this feedback whenever I try to compile the code in Arduino:

MediaPlayerTest.cpp:2:18: error: util.h: No such file or directory
MediaPlayerTest.cpp:3:25: error: MediaPlayer.h: No such file or directory
MediaPlayerTest:6: error: 'MediaPlayer' does not name a type
MediaPlayerTest.cpp: In function 'void loop()':
MediaPlayerTest:9: error: 'blinkLed' was not declared in this scope
MediaPlayerTest:11: error: 'putstring' was not declared in this scope
MediaPlayerTest:11: error: 'mediaPlayer' was not declared in this scope
MediaPlayerTest:34: error: 'playComplete' was not declared in this scope
MediaPlayerTest:38: error: 'printAvailableRAM' was not declared in this scope


Any idea how to rectify this problem?

Your advice would really help.


Thanks,
CNEC
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I did create the MediaPlayer.h file though but it still does not seem to work. As for Util.h, is there a specific code for that too?


Thanks.
Logged

Philadelphia, PA
Offline Offline
Newbie
*
Karma: 0
Posts: 18
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey Everyone!

I am fairly new to physical computing and kind of stumped so hopefully someone can help me out.

I found this post and the code in it seems to be what I have been looking for in order to get my wave shield to function the way I want, the only problem is I cannot get this code working.

I followed the steps outlined, but when I try to upload the code to my arduino I get the following errors:

'MediaPlayer' does not name a type

MediaPlayerTest.cpp:3:25: error: MediaPlayer.h: No such file or directory
MediaPlayerTest:6: error: 'MediaPlayer' does not name a type
MediaPlayerTest.cpp: In function 'void setup()':
MediaPlayerTest:15: error: a function-definition is not allowed here before '{' token
MediaPlayer_h:31: error: expected `}' at end of input


Can anyone tell me why this might be happening? Any help will be greatly appreciated.

Thanks!
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 553
Posts: 46298
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
MediaPlayerTest.cpp:3:25: error: [glow]MediaPlayer.h: No such file[/glow] or directory
I think the highlighted portion really says it all.

The compiler can't find the header file, which means that you put it in the wrong place.
Logged

Pages: [1] 2   Go Up
Jump to: