diff --git a/docs/rh-log.txt b/docs/rh-log.txt index ca11c5ba1..68a1872d9 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,10 @@ +December 19, 2008 +- Fixed: OggMod passes the raw sample data to OggEnc for stereo samples, so + the resultant Vorbis stream is not actually stereo but mono with the right + channel after the left. The two need to be interleaved just like + uncompressed samples are. +- Removed the pattern length limit in the XM reader. + December 18, 2008 - Decal changes as per Xaser's suggestions: Smaller decal for PhoenixFX2, CrossbowFX2 and MaceFX4 were missing decals, and HornRodFX2 gets a whole diff --git a/dumb/src/it/readxm.c b/dumb/src/it/readxm.c index 347c37fea..13633339f 100644 --- a/dumb/src/it/readxm.c +++ b/dumb/src/it/readxm.c @@ -27,8 +27,6 @@ #include #include -#define MAX_COLUMN_MEMORY (1024*5) - extern short *DUMBCALLBACK dumb_decode_vorbis(int outlen, const void *oggstream, int sizebytes); /** TODO: @@ -178,7 +176,7 @@ static void it_xm_convert_volume(int volume, IT_ENTRY *entry) -static int it_xm_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, int n_channels, unsigned char *buffer, int version) +static int it_xm_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, int n_channels, unsigned char **bufferptr, int *buffersize, int version) { int size; int pos; @@ -186,6 +184,7 @@ static int it_xm_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, int n_channels, int row; int effect, effectvalue; IT_ENTRY *entry; + unsigned char *buffer; /* pattern header size */ if (dumbfile_igetl(f) != ( version == 0x0102 ? 0x08 : 0x09 ) ) { @@ -212,8 +211,16 @@ static int it_xm_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, int n_channels, if (size == 0) return 0; - if (size > MAX_COLUMN_MEMORY * n_channels) { - TRACE("XM error: pattern data size > %d bytes\n", MAX_COLUMN_MEMORY * n_channels); + if (size > *buffersize) { + if (*bufferptr != NULL) { + free(*bufferptr); + } + *bufferptr = malloc(size); + *buffersize = size; + } + buffer = *bufferptr; + if (buffer == NULL) { + TRACE("XM error: out of memory reading pattern\n"); return -1; } @@ -613,6 +620,7 @@ static int it_xm_read_sample_data(IT_SAMPLE *sample, unsigned char roguebytes, D int32 i; int n_channels; int32 datasizebytes; + void *ibuffer; if (!(sample->flags & IT_SAMPLE_EXISTS)) return dumbfile_skip(f, roguebytes); @@ -648,6 +656,7 @@ static int it_xm_read_sample_data(IT_SAMPLE *sample, unsigned char roguebytes, D if (!(sample->flags & IT_SAMPLE_16BIT)) { + /* Because it'll be 16-bit when we're done with it. */ outlen <<= 1; } @@ -663,7 +672,30 @@ static int it_xm_read_sample_data(IT_SAMPLE *sample, unsigned char roguebytes, D sample->loop_start <<= 1; sample->loop_end <<= 1; } + it_xm_fixup_sample_points(sample); + /* Stereo samples are still passed to OggEnc as mono sounds, just like + * uncompressed samples, so we need to interleave them now. */ + ibuffer = malloc(sample->length << 2); + if (ibuffer == NULL) + { + /* No memory => ignore stereo bits at the end */ + sample->flags &= ~IT_SAMPLE_STEREO; + } + else + { + for (i = 0; i < sample->length; ++i) + { + ((short *)ibuffer)[i*2] = ((short *)sample->data)[i]; + ((short *)ibuffer)[i*2+1] = ((short *)sample->data)[i + sample->length]; + } + for (i = 0; i < sample->length; ++i) + { + ((short *)ibuffer)[i*2+1] -= ((short *)ibuffer)[sample->length*2 - 1]; + } + free(sample->data); + sample->data = ibuffer; + } return 0; } /* Decode failed, so assume it's normal sample data that just so @@ -680,8 +712,8 @@ static int it_xm_read_sample_data(IT_SAMPLE *sample, unsigned char roguebytes, D /* Stereo samples are a ModPlug extension, so to keep compatibility with * players that don't know about it (and FastTracker 2 itself), the two * channels are not stored interleaved but rather, one after the other. */ - void *ibuffer = malloc(sample->length << ((sample->flags & IT_SAMPLE_16BIT) ? 2 : 1)); int old_r = 0; + ibuffer = malloc(sample->length << ((sample->flags & IT_SAMPLE_16BIT) ? 2 : 1)); if (ibuffer == NULL) { /* No memory => ignore stereo bits at the end */ @@ -859,13 +891,10 @@ static DUMB_IT_SIGDATA *it_xm_load_sigdata(DUMBFILE *f, int * version) sigdata->pattern[i].entry = NULL; { - unsigned char *buffer = malloc(MAX_COLUMN_MEMORY * n_channels); /* 256 rows * 5 bytes */ - if (!buffer) { - _dumb_it_unload_sigdata(sigdata); - return NULL; - } + unsigned char *buffer = NULL; + int buffersize = 0; for (i = 0; i < sigdata->n_patterns; i++) { - if (it_xm_read_pattern(&sigdata->pattern[i], f, n_channels, buffer, * version) != 0) { + if (it_xm_read_pattern(&sigdata->pattern[i], f, n_channels, &buffer, &buffersize, * version) != 0) { free(buffer); _dumb_it_unload_sigdata(sigdata); return NULL; @@ -1054,14 +1083,10 @@ static DUMB_IT_SIGDATA *it_xm_load_sigdata(DUMBFILE *f, int * version) sigdata->pattern[i].entry = NULL; { - unsigned char *buffer = malloc(MAX_COLUMN_MEMORY * n_channels); /* 256 rows * 5 bytes */ - if (!buffer) { - free(roguebytes); - _dumb_it_unload_sigdata(sigdata); - return NULL; - } + unsigned char *buffer = NULL; + int buffersize = 0; for (i = 0; i < sigdata->n_patterns; i++) { - if (it_xm_read_pattern(&sigdata->pattern[i], f, n_channels, buffer, * version) != 0) { + if (it_xm_read_pattern(&sigdata->pattern[i], f, n_channels, &buffer, &buffersize, * version) != 0) { free(buffer); free(roguebytes); _dumb_it_unload_sigdata(sigdata);