Skip to content

Commit

Permalink
Merge pull request #19 from LunaTheFoxgirl/master
Browse files Browse the repository at this point in the history
Various tracker module features
  • Loading branch information
p0nce authored Nov 29, 2021
2 parents 526170d + af4bb2a commit de3c47f
Show file tree
Hide file tree
Showing 2 changed files with 167 additions and 0 deletions.
8 changes: 8 additions & 0 deletions source/audioformats/pocketmod.d
Original file line number Diff line number Diff line change
Expand Up @@ -892,6 +892,14 @@ int pocketmod_render(pocketmod_context *c, void *buffer, int buffer_size)
return samples_rendered * POCKETMOD_SAMPLE_SIZE;
}

void pocketmod_seek(pocketmod_context* c, ubyte pattern, ubyte row, ushort tick) {
// NOTE: This is untested.
c.line = row;
c.pattern = pattern;
c.tick = tick;
c.sample = 0;
}

int pocketmod_loop_count(pocketmod_context *c)
{
return c.loop_count;
Expand Down
159 changes: 159 additions & 0 deletions source/audioformats/stream.d
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,165 @@ public: // This is also part of the public API
return writeSamplesFloat(inData.ptr, cast(int)(inData.length / _numChannels));
}

/// Length. Returns the amount of patterns in the module
/// Formats that support this: MOD, XM
int countModulePatterns() {
assert(_io && (_io.read !is null) );
final switch(_format) with (AudioFileFormat)
{
case mp3:
case flac:
case ogg:
case opus:
case wav:
case unknown:
assert(false);
case mod:
return _modDecoder.num_patterns;
case xm:
return xm_get_number_of_patterns(_xmDecoder);
}
}

/// Length. Returns the amount of PLAYED patterns in the module
/// Formats that support this: MOD, XM
int getModuleLength() {
assert(_io && (_io.read !is null) );
final switch(_format) with (AudioFileFormat)
{
case mp3:
case flac:
case ogg:
case opus:
case wav:
case unknown:
assert(false);
case mod:
return _modDecoder.length;
case xm:
return xm_get_module_length(_xmDecoder);
}
}

/// Tell. Returns amount of rows in a pattern.
/// Formats that support this: MOD, XM
int rowsInPattern(int pattern) {
assert(_io && (_io.read !is null) );
final switch(_format) with (AudioFileFormat)
{
case mp3:
case flac:
case ogg:
case opus:
case wav:
case unknown:
assert(false);
case mod:
// According to http://lclevy.free.fr/mo3/mod.txt
// there's 64 lines (aka rows) per pattern.
// TODO: error checking, make sure no out of bounds happens.
return 64;
case xm:
// TODO: error checking, make sure no out of bounds happens.
return xm_get_number_of_rows(_xmDecoder, pattern);
}
}

/// Tell. Returns the current playing pattern id
/// Formats that support this: MOD, XM
int tellModulePattern() {
assert(_io && (_io.read !is null) );
final switch(_format) with (AudioFileFormat)
{
case mp3:
case flac:
case ogg:
case opus:
case wav:
case unknown:
assert(false);
case mod:
return _modDecoder.pattern;
case xm:
return _xmDecoder.current_table_index;
}
}

/// Tell. Returns the current playing row id
/// Formats that support this: MOD, XM
int tellModuleRow() {
assert(_io && (_io.read !is null) );
final switch(_format) with (AudioFileFormat)
{
case mp3:
case flac:
case ogg:
case opus:
case wav:
case unknown:
assert(false);
case mod:
return _modDecoder.line;
case xm:
return _xmDecoder.current_row;
}
}

/// Playback info. Returns the amount of samples remaining in the current playing pattern
/// Formats that support this: MOD
long samplesRemainingInPattern() {
assert(_io && (_io.read !is null) );
final switch(_format) with (AudioFileFormat)
{
case mp3:
case flac:
case ogg:
case opus:
case wav:
case unknown:
assert(false);
case mod:

// According to http://lclevy.free.fr/mo3/mod.txt
// there's 64 lines (aka rows) per pattern.
int rows = 64;

// NOTE: This is untested.
long samplesPerLine = cast(int)(cast(float)_modDecoder.ticks_per_line*_modDecoder.samples_per_tick);
return cast(long)(rows-_modDecoder.line)*samplesPerLine;

case xm:
return 0; // NOT IMPLEMENTED
}
}

/// Seeking. Subsequent reads start from pattern + row, 0 index
/// Only available for input streams.
/// Formats that support seeking per pattern/row: MOD, XM
bool seekPosition(int pattern, int row) {
assert(_io && (_io.read !is null) );
final switch(_format) with (AudioFileFormat)
{
case mp3:
case flac:
case ogg:
case opus:
case wav:
case unknown:
assert(false);
case mod:

// NOTE: This is untested.
pocketmod_seek(_modDecoder, pattern, row, 0);
return true;
case xm:

xm_seek(_xmDecoder, cast(ubyte)pattern, cast(ubyte)row, 0);
return true;

}
}

/// Seeking. Subsequent reads start from multi-channel frame index `frames`.
/// Only available for input streams.
/// Formats that support seeking: WAV, MP3, OGG, FLAC.
Expand Down

0 comments on commit de3c47f

Please sign in to comment.