How to load and use a patch or plugin with VS1053 breakout

For other supported Arduino products from Adafruit: Shields, accessories, etc.

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
jtlechem
 
Posts: 6
Joined: Mon May 09, 2022 7:46 pm

How to load and use a patch or plugin with VS1053 breakout

Post by jtlechem »

Background
I'm using the VS1053 codec breakout with my Arduino Uno.
(https://www.adafruit.com/product/1381)

I have things set up according the Adafruit's overview/startup guide
(https://learn.adafruit.com/adafruit-vs1 ... g-recorder)

And using the Adafruit VS1053 Library for Arduino.
(https://github.com/adafruit/Adafruit_VS1053_Library)

I have an example script working to play an audio file (player_simple.ino), but I need to use one of the patch files from vlsi (https://www.vlsi.fi/en/support/software ... tches.html).
I want to use the pitch/tempo shifter patch, which is sort of explained in this document from vlsi, section 1.10: https://www.vlsi.fi/fileadmin/software/ ... atches.pdf


Question
How do you properly load a plugin / apply a patch? and then after that, how do you use that patch in your .ino script?
I am fairly new to this type of coding and in this language.

The Adafruit VS1053 Library has a couple of functions that look useful - applyPatch() and loadPlugin() - but I don't understand what they do or what inputs they need.
I tried using loadPlugin() like this:

Code: Select all

#include <SPI.h>
#include <Adafruit_VS1053.h>
#include <SD.h>
void setup() {
     //other setup code not included for simplicity
     // load plugin/patch file
     if (! musicPlayer.loadPlugin("pitch.plg")) {
          Serial.println("Couldn't load plugin!");
          while (1);
  }
}
void loop() {
    // unkown code to change the tempo
}
There don't seem to be any errors with loadPlugin(), but I really have no way to tell if it loaded or what that code is doing.
As for utilizing the plugin, per the vlsi documentation, I tried writing to the SCI to enable the pitch/tempo shifter like this:

Code: Select all

  // Enable pitch/tempo shifter.
  // see https://www.vlsi.fi/fileadmin/software/VS10XX/vs1053b-patches.pdf
  // and https://github.com/adafruit/Adafruit_VS1053_Library/blob/master/Adafruit_VS1053.h
  // write pitch/tempo to AICTRL0, and write 0x51 to AIADDR
  // musicPlayer.sciWrite(uint8_t addr, uint16_t data);
  musicPlayer.sciWrite(VS1053_SCI_AICTRL0, -16384);
  musicPlayer.sciWrite(VS1053_SCI_AIADDR, 0x51);
but this just stops any audio from playing and the script doesn't seem to read anything after sciWrite(VS1053_SCI_AIADDR, 0x51);




This is the original example script called "player_simle.ino" for playing an audio file off the SD card:

Code: Select all

/*************************************************** 
  This is an example for the Adafruit VS1053 Codec Breakout

  Designed specifically to work with the Adafruit VS1053 Codec Breakout 
  ----> https://www.adafruit.com/products/1381

  Adafruit invests time and resources providing this open source code, 
  please support Adafruit and open-source hardware by purchasing 
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.  
  BSD license, all text above must be included in any redistribution
 ****************************************************/

// include SPI, MP3 and SD libraries
#include <SPI.h>
#include <Adafruit_VS1053.h>
#include <SD.h>

// define the pins used
//#define CLK 13       // SPI Clock, shared with SD card
//#define MISO 12      // Input data, from VS1053/SD card
//#define MOSI 11      // Output data, to VS1053/SD card
// Connect CLK, MISO and MOSI to hardware SPI pins. 
// See http://arduino.cc/en/Reference/SPI "Connections"

// These are the pins used for the breakout example
#define BREAKOUT_RESET  9      // VS1053 reset pin (output)
#define BREAKOUT_CS     10     // VS1053 chip select pin (output)
#define BREAKOUT_DCS    8      // VS1053 Data/command select pin (output)
// These are the pins used for the music maker shield
#define SHIELD_RESET  -1      // VS1053 reset pin (unused!)
#define SHIELD_CS     7      // VS1053 chip select pin (output)
#define SHIELD_DCS    6      // VS1053 Data/command select pin (output)

// These are common pins between breakout and shield
#define CARDCS 4     // Card chip select pin
// DREQ should be an Int pin, see http://arduino.cc/en/Reference/attachInterrupt
#define DREQ 3       // VS1053 Data request, ideally an Interrupt pin

Adafruit_VS1053_FilePlayer musicPlayer = 
  // create breakout-example object!
  Adafruit_VS1053_FilePlayer(BREAKOUT_RESET, BREAKOUT_CS, BREAKOUT_DCS, DREQ, CARDCS);
  // create shield-example object!
  //Adafruit_VS1053_FilePlayer(SHIELD_RESET, SHIELD_CS, SHIELD_DCS, DREQ, CARDCS);
  
void setup() {
  Serial.begin(9600);
  Serial.println("Adafruit VS1053 Simple Test");

  if (! musicPlayer.begin()) { // initialise the music player
     Serial.println(F("Couldn't find VS1053, do you have the right pins defined?"));
     while (1);
  }
  Serial.println(F("VS1053 found"));
  
   if (!SD.begin(CARDCS)) {
    Serial.println(F("SD failed, or not present"));
    while (1);  // don't do anything more
  }

  // list files
  printDirectory(SD.open("/"), 0);
  
  // Set volume for left, right channels. lower numbers == louder volume!
  musicPlayer.setVolume(20,20);

  // Timer interrupts are not suggested, better to use DREQ interrupt!
  //musicPlayer.useInterrupt(VS1053_FILEPLAYER_TIMER0_INT); // timer int

  // If DREQ is on an interrupt pin (on uno, #2 or #3) we can do background
  // audio playing
  musicPlayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT);  // DREQ int
  
  // Play one file, don't return until complete
  Serial.println(F("Playing track 001"));
  musicPlayer.playFullFile("/track001.mp3");
  // Play another file in the background, REQUIRES interrupts!
  Serial.println(F("Playing track 002"));
  musicPlayer.startPlayingFile("/track002.mp3");
}

void loop() {
  // File is playing in the background
  if (musicPlayer.stopped()) {
    Serial.println("Done playing music");
    while (1) {
      delay(10);  // we're done! do nothing...
    }
  }
  if (Serial.available()) {
    char c = Serial.read();
    
    // if we get an 's' on the serial console, stop!
    if (c == 's') {
      musicPlayer.stopPlaying();
    }
    
    // if we get an 'p' on the serial console, pause/unpause!
    if (c == 'p') {
      if (! musicPlayer.paused()) {
        Serial.println("Paused");
        musicPlayer.pausePlaying(true);
      } else { 
        Serial.println("Resumed");
        musicPlayer.pausePlaying(false);
      }
    }
  }

  delay(100);
}


/// File listing helper
void printDirectory(File dir, int numTabs) {
   while(true) {
     
     File entry =  dir.openNextFile();
     if (! entry) {
       // no more files
       //Serial.println("**nomorefiles**");
       break;
     }
     for (uint8_t i=0; i<numTabs; i++) {
       Serial.print('\t');
     }
     Serial.print(entry.name());
     if (entry.isDirectory()) {
       Serial.println("/");
       printDirectory(entry, numTabs+1);
     } else {
       // files have sizes, directories do not
       Serial.print("\t\t");
       Serial.println(entry.size(), DEC);
     }
     entry.close();
   }
}


User avatar
adafruit_support_mike
 
Posts: 67391
Joined: Thu Feb 11, 2010 2:51 pm

Re: How to load and use a patch or plugin with VS1053 breako

Post by adafruit_support_mike »

The patch file isn't part of the script the microcontroller runs, it lives on the SD card with the audio tracks.

The .loadPlugin() function takes the name of the plugin file and copies the information from the SD card to the VS1053's memory array. We don't know of any specific tests to show whether a plugin loaded correctly or not, since the only one we use is the OGG recorder.

Are you power cycling the VS1053 before running the code that loads the plugin?

User avatar
jtlechem
 
Posts: 6
Joined: Mon May 09, 2022 7:46 pm

Re: How to load and use a patch or plugin with VS1053 breako

Post by jtlechem »

Thanks for the reply here, I appreciate it. I believe the vs1053 is power cycling since it's powered from the Arduino's 5V pin. But I guess that power cycles only when uploading a new script or plugging in the arduino's power.

So that makes sense that the loadPlugin() function is working from the SD card to write the patch to the vs1053 (looks like it writes through the SCI with sciWrite().

I re-read my question and I think the second part of it was phrased poorly. Here's what I meant: After loadPlugin() runs (it doesn't seem to throw any errors), how do I use the new functionality that the plugin is supposed to enable?
For example, I'm using the pitch/tempo shifter patch. So I load in VLSI's file called "vs1053b-patches-pitch.plg" (linked in original post) then how do I adjust the tempo? It's a total blank to me for what my script needs to read next to tell the vs1053 to adjust tempo.

Code: Select all

#include <SPI.h>
#include <Adafruit_VS1053.h>
#include <SD.h>
void setup() {
     //.....other setup code not included for simplicity
     
     // load plugin/patch file
     if (! musicPlayer.loadPlugin("pitch.plg")) {
          Serial.println("Couldn't load plugin!");
          while (1);
  }                          // this bit works, or at least doesn't throw errors
}
void loop() {
    // ....unkown code to change the tempo
}

User avatar
adafruit_support_mike
 
Posts: 67391
Joined: Thu Feb 11, 2010 2:51 pm

Re: How to load and use a patch or plugin with VS1053 breako

Post by adafruit_support_mike »

jtlechem wrote:how do I use the new functionality that the plugin is supposed to enable?
I don't know. It will probably depend on the way the patch is written.

Look for documentation for the patch, or check with its creator to see what information they have.

User avatar
jtlechem
 
Posts: 6
Joined: Mon May 09, 2022 7:46 pm

Re: How to load and use a patch or plugin with VS1053 breako

Post by jtlechem »

The maker of the vs1053 chip is VLSI Solution, they said that the loadPlugin() function from the Adafruit VS1053 Library is meant for loading SPI boot images, not .plg files. This is indicated by the function looking for "P&H"

This is the loadPlugin() function:

Code: Select all

uint16_t Adafruit_VS1053::loadPlugin(char *plugname) {

  File plugin = SD.open(plugname);
  if (!plugin) {
    Serial.println("Couldn't open the plugin file");
    Serial.println(plugin);
    return 0xFFFF;
  }

  if ((plugin.read() != 'P') || (plugin.read() != '&') ||
      (plugin.read() != 'H'))
    return 0xFFFF;

  uint16_t type;

  // Serial.print("Patch size: "); Serial.println(patchsize);
  while ((type = plugin.read()) >= 0) {
    uint16_t offsets[] = {0x8000UL, 0x0, 0x4000UL};
    uint16_t addr, len;

    // Serial.print("type: "); Serial.println(type, HEX);

    if (type >= 4) {
      plugin.close();
      return 0xFFFF;
    }

    len = plugin.read();
    len <<= 8;
    len |= plugin.read() & ~1;
    addr = plugin.read();
    addr <<= 8;
    addr |= plugin.read();
    // Serial.print("len: "); Serial.print(len);
    // Serial.print(" addr: $"); Serial.println(addr, HEX);

    if (type == 3) {
      // execute rec!
      plugin.close();
      return addr;
    }

    // set address
    sciWrite(VS1053_REG_WRAMADDR, addr + offsets[type]);
    // write data
    do {
      uint16_t data;
      data = plugin.read();
      data <<= 8;
      data |= plugin.read();
      sciWrite(VS1053_REG_WRAM, data);
    } while ((len -= 2));
  }

  plugin.close();
  return 0xFFFF;
}
Additionally, they said that the error check seems to be reversed. See their note on that in their reply to this same topic in the VSDSP forum: http://www.vsdsp-forum.com/phpbb/viewto ... 366#p15366

I'll try using instead the applyPatch() function from the Adafruit VS1053 Library

User avatar
adafruit_support_mike
 
Posts: 67391
Joined: Thu Feb 11, 2010 2:51 pm

Re: How to load and use a patch or plugin with VS1053 breako

Post by adafruit_support_mike »

I’ll pass that along to the folks who handle the VS1053 library, thanks!

User avatar
scottmil
 
Posts: 24
Joined: Fri Apr 16, 2021 6:18 pm

Re: How to load and use a patch or plugin with VS1053 breakout

Post by scottmil »

I have the same question. I am using the Music Maker Featherwing with a ESP32 Huzzah Feather to code a web radio, but currently the Music Maker VS1053 will only play MP3 web streams, not AAC streams. I am hoping a patch to the VS1053 will fix this.

User avatar
scottmil
 
Posts: 24
Joined: Fri Apr 16, 2021 6:18 pm

Re: How to load and use a patch or plugin with VS1053 breakout

Post by scottmil »

Unfortunately, my Music Maker Feather 3W will no longer output audio after I attempted to patch the VS1053 using the attached code fragment and patch file vs1053b-patches.plg. A I believe I may have corrupted the Music Maker VS1053 firmware, is there a way to reset the Music Maker to factory defaults? :-(

Code: Select all


...........
#include "SD.h"
#include "FS.h"
#include "SPI.h"

-----Initialize Adafruit_VS1053 player....

....Initialize SD.....

//Generic patch file: vs1053b-patches.plg

bool patchVS1053(const char* path) { 

  FS fs = SD;
   
  if (SD.exists(path)) {
     Serial.printf("Reading file: %s\n", path);

     File file = fs.open(path);
     if(!file){
       Serial.println("Failed to open file for reading");
       return false;
     }

     uint16_t size = file.size();
     uint8_t patch[size];

     Serial.print("Read from file: ");
     while(file.available()){
       Serial.write(file.read());
     }
     file.close();
     
     //Apply patch to VS1053 via Adafruit API
     player.applyPatch(reinterpret_cast<uint16_t*>(patch), size/2);
     return true;
     
  } else {
    Serial.println("Patch file does not exist.");
    return false;
  }
} 

Locked
Please be positive and constructive with your questions and comments.

Return to “Other Arduino products from Adafruit”