Published

LinkIt ONE MP3 Player

Use your LinkIt ONE as a portable MP3 player.

IntermediateFull instructions provided825
LinkIt ONE MP3 Player

Things used in this project

Hardware components

Earphones
×1
MicroSD card
×1

Hand tools and fabrication machines

A PC
LinkIt One SDK only available for Windows at time of writing
A micro-USB cable
the same as used with most other system-on-a-chip devices or Android phones

Story

Read more

Code

Code

C/C++
//This program loads and plays music from the sd card.
#include<LSD.h>
#include<LStorage.h>
#include<LAudio.h>

//Helper Vector Class:
//As an alternative, there is a nice C++ STL port at https://github.com/maniacbug/StandardCplusplus

// Minimal class to replace std::vector
template<typename Data>
class Vector {
  size_t d_size; // Stores no. of actually stored objects
  size_t d_capacity; // Stores allocated capacity
  Data *d_data; // Stores data
  public:
  Vector() : d_size(0), d_capacity(0), d_data(0) {}; // Default constructor
  Vector(Vector const &other) : d_size(other.d_size), d_capacity(other.d_capacity), d_data(0) { d_data = (Data *)malloc(d_capacity*sizeof(Data)); memcpy(d_data, other.d_data, d_size*sizeof(Data)); }; // Copy constuctor
  ~Vector() { free(d_data); }; // Destructor
  Vector &operator=(Vector const &other) { free(d_data); d_size = other.d_size; d_capacity = other.d_capacity; d_data = (Data *)malloc(d_capacity*sizeof(Data)); memcpy(d_data, other.d_data, d_size*sizeof(Data)); return *this; }; // Needed for memory management
  void push_back(Data const &x) { if (d_capacity == d_size) resize(); d_data[d_size++] = x; }; // Adds new value. If needed, allocates more space
  size_t size() const { return d_size; }; // Size getter
  Data const &operator[](size_t idx) const { return d_data[idx]; }; // Const getter
  Data &operator[](size_t idx) { return d_data[idx]; }; // Changeable getter
  private:
  void resize() { d_capacity = d_capacity ? d_capacity*2 : 1; Data *newdata = (Data *)malloc(d_capacity*sizeof(Data)); memcpy(newdata, d_data, d_size * sizeof(Data)); free(d_data); d_data = newdata; };// Allocates double the old space
};


//Rest of Code:
int debuggingNum = 0; //A value other than 0 prints extra messages.
int testTime = 5;

Vector<LFile> musicFiles;
Vector<int> validIndices;
int musicIndex = 0;
int musicVolume = 2; //Ranges from 0 to 6 inclusive.

//A helper function to shuffle the contents of validIndices
//with the nice constraint that no song is played twice in a row.
//This assumes it is called after/as the last song is played.
void shuffleIndices(){
  if(validIndices.size() > 2){
    int swapIndex;
    int swapVal;
    //Choose a first song (make sure it's not the last one played)
    swapIndex = random(validIndices.size()-1); //Excludes last value
    swapVal = validIndices[swapIndex];
    validIndices[swapIndex] = validIndices[0];
    validIndices[0] = swapVal;
    for(int i = 1; i < validIndices.size()-1; i++){
      swapIndex = random(validIndices.size() - i) + i;
      swapVal = validIndices[swapIndex];
      validIndices[swapIndex] = validIndices[i];
      validIndices[i] = swapVal;
    }
  }
}

void setup() {
  Serial.begin(9600);
  randomSeed(analogRead(0)); //If pin 0 is unconnected, random analog noise will change the initial random value.

  Serial.print("Initializing\n");
  LAudio.begin();
  LSD.begin();
  LAudio.setVolume(musicVolume);

  //Open the root directory and list files.
  LFile rootDir = LSD.open("/", FILE_READ);
  if(debuggingNum && rootDir){
    Serial.println("Root Directory Successfully Opened:");
    Serial.println(rootDir.name());
  }

  while(LFile nextFile = rootDir.openNextFile()){
    musicFiles.push_back(nextFile);
  }

  //Test the files to determine which ones are playable:
  for(int i = 0; i < musicFiles.size(); i++){
    LAudio.playFile(storageSD, musicFiles[i].name());
    delay(testTime);
    LAudio.stop();
    if(LAudio.getStatus() == AudioStop){
      validIndices.push_back(i);
    }
  }

  shuffleIndices();

  if(validIndices.size() > 0){
    LAudio.playFile(storageSD, musicFiles[validIndices[musicIndex]].name());
    musicIndex = (musicIndex+1)%validIndices.size();
  }
}

void loop() {
  // put your main code here, to run repeatedly:
  if(debuggingNum){
    Serial.print("# Files in vector ");
    Serial.println(musicFiles.size());
    Serial.print("Num Valid Files: ");
    Serial.println(validIndices.size());
  }

  //Check to see if anything is playing. If not, attempt to play the next file in musicFiles
  AudioStatus audioStatus = LAudio.getStatus();
  if(debuggingNum){
    Serial.print("Audio Status: ");
    Serial.println(audioStatus);
  }
  if(audioStatus == AudioEndOfFile){
    LAudio.playFile(storageSD, musicFiles[validIndices[musicIndex]].name());
    Serial.print("Started Track: ");
    Serial.println(musicFiles[validIndices[musicIndex]].name());
    musicIndex = (musicIndex+1)%validIndices.size();
    if(musicIndex==0){
      shuffleIndices();
    }
  }
}

Credits

Comments

Add projectSign up / Login