Sawtooth - A Chiptune Music Player : DevLog

I'm finally starting to work on my chiptune music player: Sawtooth

The premise is to use this c++ sound emulation library (game-music-emu) for 8bit and 16bit consoles. I'm hoping to arrive at an app that I can use primarily with the dock (once it ships).

Target audio formats include:

  • Atari
  • GameBoy
  • TurboGrafx / PCEngine
  • NES / Famicom
  • SNES / SuperFamicom
  • Genesis / Sega Master System

These sound files are relatively tiny compared to a MP3. For instance, the entirety of every sound in Super Mario Bros (NES 1983) is about 16KB.

I'm going for an OG iPod aesthetic.

I've got all kinds of ideas about playlists / tags / search as well as a bunch of little add-ons to make it more fun to use.

Once installed, the user would need to go find audio rips from their favorite games and load it onto the :playdate_black:

I spent the weekend learning some basics about Lua and the SDK and I have a working shell to navigate and turn some options on and off. There is a LOOONG way to go!

I'm in way over-my-head on figuring out how to link the lua to the C++ library at the moment, but I have some examples and I will get there! I'm looking forward to hearing it make it's first sounds one day soon! :loud_sound:

I'll try to post updates on my progress regularly...

Note: the screen transitions are WAY faster than what the simulator recording tool shows...(Actually, they take exactly 250ms animators are so cool!)



Progress report.

TLDR: linked 3rd party c++ library on device, reading files in c is straight forward but needs to be taken in smallish 4000 byte chunks when on device) (wrong, you need to alloc & malloc to free space on the stack)

I bumped into my fair share of sharp edges and minor setbacks the last few days trying to get my development environment linking the game-music-emu c++ library on device at runtime. Everything worked ok in the simulator, but no dice on the actual :playdate_agh:

I've never used CMakeLists before and learning the basics took me the better part of a day just to get the libraries to build and link.

I sent a desperation message to community member @MrBZapp and he graciously helped me through my CMakeLists.txt issues. (modify_target_for_playdate does something magic!)

Once I was successfully running on the device, I decided it was time to read some bytes off disk and open a file. For now, I have embedded a 40KB test NSF file into my pdx, so that's the file i'm going to read (and hopefully playback soon).

SDK API's that I've used today:

Once I read the byte array, I printed it all out to the console with pd->system->logToConsole() and compared with xxd dump from my terminal on my matches!

That's about it for a progress report, next up I'm going to send my bytes to the game music library and see if it can determine if it's a music file. :crossed_fingers:


I have hit roadblock after roadblock over the past week (or 9 days). BUT, I've overcome!

The C++ library I was attempting to use was blowing up on device and crashing as soon as I attempted to instantiate an emulator. I had a heck of a time trying to debug whatever was happening down in the c++ library. (it would be super cool if we could step through a debugger in c or c++ code)

Then I had an epiphany, I looked up RockBOX source (iPod alternative firmware) and found that they have a C library of the Game Music Engine. I've ripped out all of the c++ stuff from my project and replaced it with c code i've lifted from rockbox codecs.

ANNNDDD...It Works! (sound on!)

That playdate.UpButtonUp event is doing the following:

  1. Loading a .nsf file from disk
  2. Creating a NSF Emulator
  3. Starting up the emulator
  4. Playing through the song (track #40 - Jump!)
  5. unweaving the output buffer (left & right channel) and feeding them into a playdate soundsource via the Audio Callback Source (major help found in this thread)

So, Sawtooth lives! Now I have a ton of work to make it proper software but getting actual sound emulation done on device lifts my burgeoning Playdate C development spirits! (speaking of learning, I figured out from my previous post that I wasn't using alloc & malloc to clear space on the heap prior to loading a file....what a n00b. (this code snippet is poetry...thank you @shaun & @james))