Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
219 changes: 212 additions & 7 deletions addons/acodec/modaudio.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
* author: Matthew Leverton
*/


#define _FILE_OFFSET_BITS 64
#include "allegro5/allegro.h"
#include "allegro5/allegro_acodec.h"
Expand Down Expand Up @@ -176,10 +175,20 @@ static size_t modaudio_stream_update(ALLEGRO_AUDIO_STREAM *stream, void *data,
}

while (written < buf_size) {
long size_to_read = (buf_size - written) / sample_size;
long position = lib.duh_sigrenderer_get_position(df->sig);
bool loop = false;
if (stream->spl.loop != _ALLEGRO_PLAYMODE_STREAM_ONCE && df->loop_end != -1 &&
position + 65536 * size_to_read / 44100 >= df->loop_end) {
size_to_read = (df->loop_end - position) * 44100 / 65536;
if (size_to_read < 0)
size_to_read = 0;
loop = true;
}
written += lib.duh_render(df->sig, 16, 0, 1.0, 65536.0 / 44100.0,
(buf_size - written) / sample_size, &(((char *)data)[written])) * sample_size;
if (stream->spl.loop == _ALLEGRO_PLAYMODE_STREAM_ONCE) {
break;
size_to_read, &(((char *)data)[written])) * sample_size;
if (loop || (long)written < size_to_read * sample_size) {
break;
}
}

Expand Down Expand Up @@ -213,6 +222,10 @@ static bool modaudio_stream_seek(ALLEGRO_AUDIO_STREAM *stream, double time)
{
MOD_FILE *const df = stream->extra;

if (df->loop_end != -1 && (long)(time * 65336) > df->loop_end) {
return false;
}

lib.duh_end_sigrenderer(df->sig);
df->sig = lib.duh_start_sigrenderer(df->duh, 0, 2, time * 65536);

Expand Down Expand Up @@ -306,10 +319,15 @@ static ALLEGRO_AUDIO_STREAM *modaudio_stream_init(ALLEGRO_FILE* f,
mf->sig = sig;
mf->fh = NULL;
mf->length = lib.duh_get_length(duh) / 65536.0;
if (mf->length < 0)
if (mf->length < 0) {
mf->length = 0;
mf->loop_start = -1;
mf->loop_end = -1;
mf->loop_start = -1;
mf->loop_end = -1;
}
else {
mf->loop_start = 0;
mf->loop_end = (int)(mf->length * 65536.0);
}

stream->extra = mf;
stream->feeder = modaudio_stream_update;
Expand Down Expand Up @@ -471,6 +489,118 @@ static ALLEGRO_AUDIO_STREAM *load_dumb_audio_stream(const char *filename,
return stream;
}

static bool _al_identify_669(ALLEGRO_FILE *f)
{
uint8_t x[2];
if (al_fread(f, x, 2) < 2)
return false;
if (memcmp(x, "if", 2) == 0 || memcmp(x, "JN", 2) == 0)
return true;
return false;
}

static bool _al_identify_amf(ALLEGRO_FILE *f)
{
uint8_t x[3];
if (al_fread(f, x, 3) < 3)
return false;
if (memcmp(x, "AMF", 3) == 0)
return true;
return false;
}

static bool _al_identify_asy(ALLEGRO_FILE *f)
{
uint8_t x[24];
if (al_fread(f, x, 24) < 24)
return false;
if (memcmp(x, "ASYLUM Music Format V1.0", 24) == 0)
return true;
return false;
}

static bool _al_identify_mtm(ALLEGRO_FILE *f)
{
uint8_t x[3];
if (al_fread(f, x, 3) < 3)
return false;
if (memcmp(x, "MTM", 3) == 0)
return true;
return false;
}

static bool _al_identify_okt(ALLEGRO_FILE *f)
{
uint8_t x[8];
if (al_fread(f, x, 8) < 8)
return false;
if (memcmp(x, "OKTASONG", 8) == 0)
return true;
return false;
}

static bool _al_identify_psm(ALLEGRO_FILE *f)
{
uint8_t x[4];
if (al_fread(f, x, 4) < 4)
return false;
if (memcmp(x, "PSM\x00", 4) == 0 || memcmp(x, "PSM\xFE", 4) == 0)
return true;
return false;
}

static bool _al_identify_ptm(ALLEGRO_FILE *f)
{
uint8_t x[4];
if (!al_fseek(f, 0x2C, ALLEGRO_SEEK_CUR))
return false;
if (al_fread(f, x, 4) < 4)
return false;
if (memcmp(x, "DSMF", 4) == 0)
return true;
return false;
}

static bool _al_identify_riff(ALLEGRO_FILE *f)
{
static const char riff_fmts[][4] = {
"AM ", "AMFF", "DSMF"
};
uint8_t x[4];
if (al_fread(f, x, 4) < 4)
return false;
if (memcmp(x, "RIFF", 4) != 0)
return false;
if (!al_fseek(f, 4, ALLEGRO_SEEK_CUR))
return false;
if (al_fread(f, x, 4) < 4)
return false;
for (size_t i = 0; i < sizeof(riff_fmts) / 4; ++i) {
if (memcmp(x, riff_fmts[i], 4) == 0)
return true;
}
return false;
}

static bool _al_identify_stm(ALLEGRO_FILE *f)
{
static const char stm_fmts[][8] = {
"!Scream!", "BMOD2STM", "WUZAMOD!"
};
uint8_t x[10];
if (!al_fseek(f, 20, ALLEGRO_SEEK_CUR))
return false;
if (al_fread(f, x, 10) < 8)
return false;
if (x[9] != 2)
return false;
for (size_t i = 0; i < sizeof(stm_fmts) / 8; ++i) {
if (memcmp(x, stm_fmts[i], 8) == 0)
return true;
}
return false;
}

#else
/*
* For DUMB 0.9.3:
Expand Down Expand Up @@ -614,6 +744,64 @@ static ALLEGRO_AUDIO_STREAM *load_s3m_audio_stream(const char *filename,

#endif // DUMB_MAJOR_VERSION

static bool _al_identify_it(ALLEGRO_FILE *f)
{
uint8_t x[4];
if (al_fread(f, x, 4) < 4)
return false;
if (memcmp(x, "IMPM", 4) == 0)
return true;
return false;
}

static bool _al_identify_mod(ALLEGRO_FILE *f)
{
static const char mod_sigs[][4] = {
"M.K.", "M!K!", "M&K!", "N.T.",
"NSMS", "FLT4", "M\0\0\0", "8\0\0\0",
"FEST", "FLT8", "CD81", "OCTA",
"OKTA", "16CN", "32CN"
};
uint8_t x[4];
if (!al_fseek(f, 0x438, ALLEGRO_SEEK_CUR))
return false;
if (al_fread(f, x, 4) < 4)
return false;
for (size_t i = 0; i < sizeof(mod_sigs) / 4; ++i) {
if (memcmp(x, mod_sigs[i], 4) == 0)
return true;
}
if (memcmp(x + 2, "CH", 2) == 0 && isdigit(x[0]) && isdigit(x[1])) /* ##CH */
return true;
if (memcmp(x + 1, "CHN", 3) == 0 && isdigit(x[0])) /* #CHN */
return true;
if (memcmp(x, "TDZ", 3) == 0 && isdigit(x[3])) /* TDZ? */
return true;
return false;
}

static bool _al_identify_s3m(ALLEGRO_FILE *f)
{
uint8_t x[4];
if (!al_fseek(f, 0x2C, ALLEGRO_SEEK_CUR))
return false;
if (al_fread(f, x, 4) < 4)
return false;
if (memcmp(x, "SCRM", 4) == 0)
return true;
return false;
}

static bool _al_identify_xm(ALLEGRO_FILE *f)
{
uint8_t x[16];
if (al_fread(f, x, 16) < 16)
return false;
if (memcmp(x, "Extended Module:", 16) == 0)
return true;
return false;
}

bool _al_register_dumb_loaders(void)
{
bool ret = true;
Expand All @@ -626,30 +814,43 @@ bool _al_register_dumb_loaders(void)
*/
ret &= al_register_audio_stream_loader(".669", load_dumb_audio_stream);
ret &= al_register_audio_stream_loader_f(".669", load_dumb_audio_stream_f);
ret &= al_register_sample_identifier(".669", _al_identify_669);
ret &= al_register_audio_stream_loader(".amf", load_dumb_audio_stream);
ret &= al_register_audio_stream_loader_f(".amf", load_dumb_audio_stream_f);
ret &= al_register_sample_identifier(".amf", _al_identify_amf);
ret &= al_register_audio_stream_loader(".asy", load_dumb_audio_stream);
ret &= al_register_audio_stream_loader_f(".asy", load_dumb_audio_stream_f);
ret &= al_register_sample_identifier(".asy", _al_identify_asy);
ret &= al_register_audio_stream_loader(".it", load_dumb_audio_stream);
ret &= al_register_audio_stream_loader_f(".it", load_dumb_audio_stream_f);
ret &= al_register_sample_identifier(".it", _al_identify_it);
ret &= al_register_audio_stream_loader(".mod", load_dumb_audio_stream);
ret &= al_register_audio_stream_loader_f(".mod", load_dumb_audio_stream_f);
ret &= al_register_sample_identifier(".mod", _al_identify_mod);
ret &= al_register_audio_stream_loader(".mtm", load_dumb_audio_stream);
ret &= al_register_audio_stream_loader_f(".mtm", load_dumb_audio_stream_f);
ret &= al_register_sample_identifier(".mtm", _al_identify_mtm);
ret &= al_register_audio_stream_loader(".okt", load_dumb_audio_stream);
ret &= al_register_audio_stream_loader_f(".okt", load_dumb_audio_stream_f);
ret &= al_register_sample_identifier(".okt", _al_identify_okt);
ret &= al_register_audio_stream_loader(".psm", load_dumb_audio_stream);
ret &= al_register_audio_stream_loader_f(".psm", load_dumb_audio_stream_f);
ret &= al_register_sample_identifier(".psm", _al_identify_psm);
ret &= al_register_audio_stream_loader(".ptm", load_dumb_audio_stream);
ret &= al_register_audio_stream_loader_f(".ptm", load_dumb_audio_stream_f);
ret &= al_register_sample_identifier(".ptm", _al_identify_ptm);
ret &= al_register_audio_stream_loader(".riff", load_dumb_audio_stream);
ret &= al_register_audio_stream_loader_f(".riff", load_dumb_audio_stream_f);
ret &= al_register_sample_identifier(".riff", _al_identify_riff);
ret &= al_register_audio_stream_loader(".s3m", load_dumb_audio_stream);
ret &= al_register_audio_stream_loader_f(".s3m", load_dumb_audio_stream_f);
ret &= al_register_sample_identifier(".s3m", _al_identify_s3m);
ret &= al_register_audio_stream_loader(".stm", load_dumb_audio_stream);
ret &= al_register_audio_stream_loader_f(".stm", load_dumb_audio_stream_f);
ret &= al_register_sample_identifier(".stm", _al_identify_stm);
ret &= al_register_audio_stream_loader(".xm", load_dumb_audio_stream);
ret &= al_register_audio_stream_loader_f(".xm", load_dumb_audio_stream_f);
ret &= al_register_sample_identifier(".xm", _al_identify_xm);
#else
/*
* DUMB 0.9.3 supported only these 4 formats and had no *_any loader.
Expand All @@ -658,12 +859,16 @@ bool _al_register_dumb_loaders(void)
*/
ret &= al_register_audio_stream_loader(".xm", load_xm_audio_stream);
ret &= al_register_audio_stream_loader_f(".xm", load_xm_audio_stream_f);
ret &= al_register_sample_identifier(".xm", _al_identify_xm);
ret &= al_register_audio_stream_loader(".it", load_it_audio_stream);
ret &= al_register_audio_stream_loader_f(".it", load_it_audio_stream_f);
ret &= al_register_sample_identifier(".it", _al_identify_it);
ret &= al_register_audio_stream_loader(".mod", load_mod_audio_stream);
ret &= al_register_audio_stream_loader_f(".mod", load_mod_audio_stream_f);
ret &= al_register_sample_identifier(".mod", _al_identify_mod);
ret &= al_register_audio_stream_loader(".s3m", load_s3m_audio_stream);
ret &= al_register_audio_stream_loader_f(".s3m", load_s3m_audio_stream_f);
ret &= al_register_sample_identifier(".s3m", _al_identify_s3m);
#endif // DUMB_MAJOR_VERSION
return ret;
}
Expand Down
6 changes: 3 additions & 3 deletions docs/src/refman/utf8.txt
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ pointed to by the `info` parameter. The string will not have any other
storage allocated of its own, so if you allocate the `info` structure on the
stack then no explicit "free" operation is required.

The string is valid until the underlying C string disappears.
The result of string and info is valid until the underlying C string disappears.

Example:

Expand All @@ -245,7 +245,7 @@ Create a string that references the storage of an underlying buffer.
The size of the buffer is given in bytes. You can use it to reference only
part of a string or an arbitrary region of memory.

The string is valid while the underlying memory buffer is valid.
The result of string and info is valid while the underlying memory buffer is valid.

See also: [al_ref_cstr], [al_ref_ustr]

Expand All @@ -261,7 +261,7 @@ stack then no explicit "free" operation is required.

The referenced interval is \[`start_pos`, `end_pos`). Both are byte offsets.

The string is valid until the underlying string is modified or destroyed.
The result of string and info is valid until the underlying string is modified or destroyed.

If you need a range of code-points instead of bytes, use [al_ustr_offset]
to find the byte offsets.
Expand Down