MOD/S3M/XM/IT music files (by JarkkoPFC)

Jarkko : Few people have been asking for the source code of my Arduino music player, so I created this GitHub project. The player is able to play MOD/S3M/XM/IT music files that are stored in the MCU program memory and has been developed so that it can run within very limited memory and performance constraints while still producing decent sound. I originally developed the player for Arduino Uno, which has only 2KB of RAM, 32KB of flash memory and 8-bit MCU running at 16MHz. Below is a video showing the player in action (running on Teensy 4 + Audio Shield)

Succesfully tested by r043v on gamebuino.

hi,

i used successfully pmf player on the gamebuino meta, https://github.com/JarkkoPFC/arduino-music-player

not using official library and using fastled for music visualization

here is a bin > http://www.mirari.fr/sZ0t :notes:

1 Like

ATM all I can get is noise :slight_smile:

I have loaded the pfm_player.ino

have added :

#include <Gamebuino-Meta.h>
gb.begin(); in setup
while (!gb.update()); in loop

It compile successfully but the GB plays noise.

1 Like

yes it’s interfere with official lib

here is a minimal template :

#define ARDUINO_ARCH_SAMD 1
#include <SPI.h>

#include "pmf_player.h"

#define TFT_CS    (30u)
#define TFT_DC    (31u)
#define SD_CS   (26u)
#define NEOPIX_PIN  (38u)
#define BAT_PIN   (A5)
#define BTN_CS (25)

#include "FastLED.h"

#define NUM_LEDS 8
CRGB leds[NUM_LEDS];

static const uint8_t PROGMEM s_pmf_file[]={
#include "music.h"
};

static pmf_player s_player;

/* callback de gestion des leds */
static void example_visualization(void *player_)
{
  const pmf_player *player=(const pmf_player*)player_;
  unsigned num_channels=min(8, player->num_playback_channels());
  int c = 0, m = player->num_playback_channels();
  for(unsigned i=0; i<8; ++i)
  { if( c == m ) c=0;

    pmf_channel_info chl=player->channel_info(c);

    if( chl.note_hit ){
      int note = chl.base_note;
      if( note > 48 ){ note -= 48; note*=3; if( note > 255 ) note = 255; }
      leds[i]=CHSV( note, 255, chl.volume*4);
    } else leds[i].nscale8( 234 );
    c++;
  }
}

void setup_example_visualization(pmf_player &player_){
  player_.set_tick_callback(&example_visualization, &player_);
}

/* gestion des boutons */
volatile uint32_t *setBtnPin = &PORT_IOBUS->Group[g_APinDescription[BTN_CS].ulPort].OUTSET.reg;
volatile uint32_t *clrBtnPin = &PORT_IOBUS->Group[g_APinDescription[BTN_CS].ulPort].OUTCLR.reg;
const uint32_t  btnPinMASK = (1ul << g_APinDescription[BTN_CS].ulPin);

#define btnPinHi (*setBtnPin = btnPinMASK)
#define btnPinLo (*clrBtnPin = btnPinMASK)

#pragma pack(push, 1)
union btn {
  uint8_t raw;
  struct {
   uint8_t down:1;
   uint8_t left:1;
   uint8_t right:1;
   uint8_t up:1;
   uint8_t a:1;
   uint8_t b:1;
   uint8_t menu:1;
   uint8_t home:1;
  };
};
#pragma pack(pop)

struct buttons {
  union btn current;
  union btn last;
} buttons;

void initButtons(void){
  pinMode(BTN_CS, OUTPUT);
  btnPinHi;
}

void readButtons(void){
  SPI.beginTransaction(SPISettings(12000000, MSBFIRST, SPI_MODE0));
  btnPinLo;
  delayMicroseconds(1);
  buttons.last.raw = buttons.current.raw;
  buttons.current.raw = SPI.transfer(1);
  btnPinHi;
  SPI.endTransaction();
}

/* /boutons */

void setup()
{
  WDT->CTRL.bit.ENABLE = 0;

  s_player.load(s_pmf_file);

  FastLED.addLeds<NEOPIXEL, NEOPIX_PIN>(leds, NUM_LEDS);

  initButtons();

  setup_example_visualization(s_player);

  s_player.start(22050);
}

void loop()
{ s_player.update(); // keep updating the audio buffer...

  FastLED.show();

  readButtons();

  if( !buttons.current.home && buttons.last.home )
    ((void(*)(void))(*((uint32_t*)0x3FF4)))();
}
1 Like

didn’t you said you succeed on the Meta ?
I’m not an expert but looks like the code is for the Gamebuino 1.

Edit : ok I made it play a track by removing all the fastled stuff.
The sound is pretty good !!!

yes sound is really accurate !
also the player allow dedicated channels to also mix your own samples on demand :slight_smile:

fastled is a really awesome piece of code, you just need import it into arduino ide, that’s a valuable addon to the song replay :- )

Ok, going to install that.

And is it possible to play those musics in our gamebuino games ?

as it’s incompatible you have two choice to use official lib :

  • trace into the code and check what’s append
  • do not use gb.begin and copy the function without sound init part

(but real question may be why use official lib ?)

(sinon je suis aussi français :stuck_out_tongue: )

I thinlk you have overestimated my gamebuino’s knowledge ! :wink:

Tu as un exemple de code qui intègre le son dans un petit jeu avec des sprites par exemple ?
(Un truc tout con comme l’animation de Mario de Steph ou autre, juste pour avoir tout sous le coude dans ce post qui risque de servir à beaucoup)

non, coté graphique je n’ai pas encore de solution viable,
il y à une multitude de lib contrôlant le lcd mais aucune vraiment complète avec un fast spi couplé au dma

je dois m’y repencher mais je n’ai plus touché à tout ceci depuis plusieurs mois.
(et le port usb de ma meta est hs, donc chiant de passer par la sd)

quoi qu’il en soit, en désactivant le son dans gb.begin (lignes 234 à 244) et la ligne 387 de gb.update (plus le code des leds qui raye les yeux) ça devrait fonctionner avec la lib classique

Merci à toi pour ses précisions.