Playdate MOD player

Version 1.34

Table of Contents

Quickstart

Add modplayer.lua to your sources and import

import "modplayer"
Load your favorite song
modplayer.loadSong("game-music.mod")
Call update every frame to make noise
function playdate.update
    modplayer.update()
    ...
end
Control playback
modplayer.playSong()
...
modplayer.stopSong()

See API reference for more detailed information on how things work.

Features

File formats

Playdate MOD player only supports ProTracker .mod modules and its most common 4-channel extended versions. Versions with more than 4 channels or packed modules are not supported.

Effects

Here's an exhaustive list of MOD effects and their support status.

Effect Support Description
0xy yes Arpeggio
1xx yes Portamento up
2xx yes Portamento down
3xx yes Tone portamento
4xy yes Vibrato
5xy yes Volume slide + Tone portamento.
6xy yes Volume slide + Vibrato.
7xy yes Tremolo
8xx yes Set panning
9xx yes Sample offset
Axx yes Volume slide
Bxx yes Position jump
Cxx yes Set volume
Dxx yes Pattern break
E0x -- Set filter
E1x yes Fine portamento up
E2x yes Fine portamento down
E3x -- Glissando control
E4x -- Set vibrato waveform. Not supported, always sine
E5x yes Set finetune.
E60 -- Pattern loop start
E6x -- Pattern loop
E7x -- Set tremolo waveform. Not supported, always sine
E8x yes Set panning. 8xx is more accurate version of the same effect
E9x yes Retrigger sample
EAx yes Fine volume up
EBx yes Fine volume up
ECx yes Note cut
EDx yes Note delay
EEx yes Pattern delay
EFx -- Invert loop
Fxx yes Set speed / tempo

Samples

Feature Supported Description
volume yes Sample specific volume
finetune yes Pitch finetune
repeatStart yes Repeat start position
repeatLength yes Repeat section length (end - start)
data yes Embedded sample data

Performance

The player is relatively easy on the CPU, but the complexity and speed of the song can affect performance.

Here's data from a minimal test with 5x resampled instruments.

Loading times

Loading times depend on the used resampling as well as the size of the instrument samples. You can generally expect a song to load in 10-60 seconds when resampling on the device, and 1-3 seconds when using prerendered samples.

Design Considerations

API Reference

File operations

functionmodplayer.loadSong(path, [progressCallback], [loadMetadata])

Loads a module from a file.

Parameters

  • stringpath

    Path to file.

  • functionprogressCallback(progress)

    This function is called multiple times during loading to report progress. You should also call coroutine.yield() in the callback to prevent the device from freezing.

    Example:

    local function logProgress(progress)
        print(tostring(progress * 100.0) .. "%")
        coroutine.yield()
    end
        
    modplayer.loadSong("song.mod", progressCallback)

  • booleanloadMetadata

    When true, metadata like note names, are also resolved during loading.

functionmodplayer.unloadSong()

Unloads the current module from memory.

Player status

booleanmodplayer.isPlaying

True when the song is playing.

booleanmodplayer.readyToPlay

True when a module has been successfully loaded.

stringmodplayer.version

Library version.

Playback control

functionmodplayer.update()

Updates playback. This has to be called once per update.

function playdate.update()
    modplayer.update()
end

functionmodplayer.playSong()

Starts playing the song. If playback is paused, this will resume playing.

functionmodplayer.getVolume()number

Gets master volume (0.0 - 1.0).

functionmodplayer.setVolume(volume)

Sets master volume.

Parameters

  • numbervolume

    New master volume (0.0 - 1.0).

functionmodplayer.getChannelMuted()boolean

Returns true if the channel is muted.

Parameters

  • numberchannel

    Channel number (1 - 4).

functionmodplayer.setChannelMuted(volume)

Mutes or unmutes a channel.

Parameters

  • numberchannel

    Channel number (1 - 4).

  • booleanmute

    Mute the channel?

functionmodplayer.setPosition(orderNumber)

Set current playback position in pattern table.

Parameters

  • integerorderNumber

    Pattern order id.

tablemodplayer.playbackInfo

Playback details.

Fields

  • integercurrentPatternCurrent pattern number
  • integercurrentRowCurrent row number
  • integercurrentOrderCurrent position in pattern order table

Module details

tablemodplayer.metadata

Song metadata.

Fields

  • integeridInternal identifier. Can be used to track song change
  • stringfilenameFilename
  • stringnameSong name
  • integerchannelCountChannel count
  • integertempoTempo in BPM.
  • integerspeedSpeed in ticks per row.
  • integerinstrumentCountInstrument count
  • integerpatternCountPattern count
  • integerorderCountPattern order table length
  • tableorderPattern order table
functionmodplayer.getPattern(patternNumber)

Gets a pattern with id.

Parameters

  • integerpatternNumber

    Pattern id.

Configuration

functionmodplayer.setTimingMode(mode)

Sets playback timing mode.

Parameters

  • stringmodeTiming mode
    • "clock"Advance every 20 ms
    • "crank"Advance only when the crank is rotated
functionmodplayer.configureResampling(scale, interpolation)

Configures load-time resampling. Higher settings result in better sound quality, but considerably increase loading times.

Parameters

  • numberscaleSampling rate multiplier (1x, 2x...). Default value is 1.
  • stringinterpolationInterpolation algorithm. Default value is "amiga".
    • "none"No interpolation
    • "linear"Running average
    • "amiga"Amiga 500 interpolation
functionmodplayer.configureCacheDirectory(path)

Overrides the cache directory. You can use this to include prerendered samples in yout game.

Parameters

  • stringpathPath ending with /

License

Playdate MOD player is licensed under CC0.