/* dumb_read_riff_quick(): reads a RIFF file into a DUH struct, returning a * pointer to the DUH struct. When you have finished with it, you must pass * the pointer to unload_duh() so that the memory can be freed. */ DUH *dumb_read_riff_quick( DUMBFILE * f ) { DUH * duh; struct riff * stream; long size; size = dumbfile_get_size(f); stream = riff_parse( f, 0, size, 1 ); if ( ! stream ) stream = riff_parse( f, 0, size, 0 ); if ( ! stream ) return 0; if ( stream->type == DUMB_ID( 'A', 'M', ' ', ' ' ) ) duh = dumb_read_riff_am( f, stream ); else if ( stream->type == DUMB_ID( 'A', 'M', 'F', 'F' ) ) duh = dumb_read_riff_amff( f, stream ); else if ( stream->type == DUMB_ID( 'D', 'S', 'M', 'F' ) ) duh = dumb_read_riff_dsmf( f, stream ); else duh = 0; riff_free( stream ); return duh; }
/* dumb_read_riff_quick(): reads a RIFF file into a DUH struct, returning a * pointer to the DUH struct. When you have finished with it, you must pass * the pointer to unload_duh() so that the memory can be freed. */ DUH *dumb_read_riff_quick( DUMBFILE * f ) { DUH * duh; struct riff * stream; { unsigned char * buffer = 0; unsigned size = 0; unsigned read; do { buffer = realloc( buffer, 32768 + size ); if ( ! buffer ) return 0; read = dumbfile_getnc( buffer + size, 32768, f ); if ( read < 0 ) { free( buffer ); return 0; } size += read; } while ( read == 32768 ); stream = riff_parse( buffer, size, 1 ); if ( ! stream ) stream = riff_parse( buffer, size, 0 ); free( buffer ); } if ( ! stream ) return 0; if ( stream->type == DUMB_ID( 'A', 'M', ' ', ' ' ) ) duh = dumb_read_riff_am( stream ); else if ( stream->type == DUMB_ID( 'A', 'M', 'F', 'F' ) ) duh = dumb_read_riff_amff( stream ); else if ( stream->type == DUMB_ID( 'D', 'S', 'M', 'F' ) ) duh = dumb_read_riff_dsmf( stream ); else duh = 0; riff_free( stream ); return duh; }
void riff_free( struct riff * stream ) { if ( stream ) { if ( stream->chunks ) { unsigned i; for ( i = 0; i < stream->chunk_count; ++i ) { struct riff_chunk * chunk = stream->chunks + i; if ( chunk->type == DUMB_ID('R','I','F','F') ) riff_free( ( struct riff * ) chunk->data ); else free( chunk->data ); } free( stream->chunks ); } free( stream ); } }
static DUMB_IT_SIGDATA *it_okt_load_sigdata(DUMBFILE *f) { DUMB_IT_SIGDATA *sigdata; unsigned n_channels; unsigned i, j, k, l; IFF_CHUNKED *mod; const IFF_CHUNK *chunk; char signature[8]; if (dumbfile_getnc(signature, 8, f) < 8 || memcmp(signature, "OKTASONG", 8)) { return NULL; } mod = dumbfile_read_okt(f); if (!mod) return NULL; sigdata = (DUMB_IT_SIGDATA *) malloc(sizeof(*sigdata)); if (!sigdata) { free_okt(mod); return NULL; } sigdata->name[0] = 0; chunk = get_chunk_by_type(mod, DUMB_ID('S','P','E','E'), 0); if (!chunk || chunk->size < 2) { free(sigdata); free_okt(mod); return NULL; } sigdata->speed = (chunk->data[0] << 8) | chunk->data[1]; chunk = get_chunk_by_type(mod, DUMB_ID('S','A','M','P'), 0); if (!chunk || chunk->size < 32) { free(sigdata); free_okt(mod); return NULL; } sigdata->n_samples = chunk->size / 32; chunk = get_chunk_by_type(mod, DUMB_ID('C','M','O','D'), 0); if (!chunk || chunk->size < 8) { free(sigdata); free_okt(mod); return NULL; } n_channels = 0; for (i = 0; i < 4; i++) { j = (chunk->data[i * 2] << 8) | chunk->data[i * 2 + 1]; if (!j) n_channels++; else if (j == 1) n_channels += 2; } if (!n_channels) { free(sigdata); free_okt(mod); return NULL; } sigdata->n_pchannels = n_channels; sigdata->sample = (IT_SAMPLE *) malloc(sigdata->n_samples * sizeof(*sigdata->sample)); if (!sigdata->sample) { free(sigdata); free_okt(mod); return NULL; } sigdata->song_message = NULL; sigdata->order = NULL; sigdata->instrument = NULL; sigdata->pattern = NULL; sigdata->midi = NULL; sigdata->checkpoint = NULL; sigdata->n_instruments = 0; for (i = 0; i < (unsigned)sigdata->n_samples; i++) sigdata->sample[i].data = NULL; chunk = get_chunk_by_type(mod, DUMB_ID('S','A','M','P'), 0); for (i = 0; i < (unsigned)sigdata->n_samples; i++) { it_okt_read_sample_header(&sigdata->sample[i], chunk->data + 32 * i); } sigdata->restart_position = 0; chunk = get_chunk_by_type(mod, DUMB_ID('P','L','E','N'), 0); if (!chunk || chunk->size < 2) { _dumb_it_unload_sigdata(sigdata); free_okt(mod); return NULL; } sigdata->n_orders = (chunk->data[0] << 8) | chunk->data[1]; // what if this is > 128? if (sigdata->n_orders <= 0 || sigdata->n_orders > 128) { _dumb_it_unload_sigdata(sigdata); free_okt(mod); return NULL; } chunk = get_chunk_by_type(mod, DUMB_ID('P','A','T','T'), 0); if (!chunk || chunk->size < (unsigned)sigdata->n_orders) { _dumb_it_unload_sigdata(sigdata); free_okt(mod); return NULL; } sigdata->order = (unsigned char *) malloc(sigdata->n_orders); if (!sigdata->order) { _dumb_it_unload_sigdata(sigdata); free_okt(mod); return NULL; } memcpy(sigdata->order, chunk->data, sigdata->n_orders); /* Work out how many patterns there are. */ chunk = get_chunk_by_type(mod, DUMB_ID('S','L','E','N'), 0); if (!chunk || chunk->size < 2) { _dumb_it_unload_sigdata(sigdata); free_okt(mod); return NULL; } sigdata->n_patterns = (chunk->data[0] << 8) | chunk->data[1]; j = get_chunk_count(mod, DUMB_ID('P','B','O','D')); if (sigdata->n_patterns > (int)j) sigdata->n_patterns = (int)j; if (!sigdata->n_patterns) { _dumb_it_unload_sigdata(sigdata); free_okt(mod); return NULL; } sigdata->pattern = (IT_PATTERN *) malloc(sigdata->n_patterns * sizeof(*sigdata->pattern)); if (!sigdata->pattern) { _dumb_it_unload_sigdata(sigdata); free_okt(mod); return NULL; } for (i = 0; i < (unsigned)sigdata->n_patterns; i++) sigdata->pattern[i].entry = NULL; /* Read in the patterns */ for (i = 0; i < (unsigned)sigdata->n_patterns; i++) { chunk = get_chunk_by_type(mod, DUMB_ID('P','B','O','D'), i); if (it_okt_read_pattern(&sigdata->pattern[i], chunk->data, chunk->size, n_channels) != 0) { _dumb_it_unload_sigdata(sigdata); free_okt(mod); return NULL; } } /* And finally, the sample data */ k = get_chunk_count(mod, DUMB_ID('S','B','O','D')); for (i = 0, j = 0; i < (unsigned)sigdata->n_samples && j < k; i++) { if (sigdata->sample[i].flags & IT_SAMPLE_EXISTS) { chunk = get_chunk_by_type(mod, DUMB_ID('S','B','O','D'), j); if (it_okt_read_sample_data(&sigdata->sample[i], (const char *)chunk->data, chunk->size)) { _dumb_it_unload_sigdata(sigdata); free_okt(mod); return NULL; } j++; } } for (; i < (unsigned)sigdata->n_samples; i++) { sigdata->sample[i].flags = 0; } chunk = get_chunk_by_type(mod, DUMB_ID('C','M','O','D'), 0); for (i = 0, j = 0; i < n_channels && j < 4; j++) { k = (chunk->data[j * 2] << 8) | chunk->data[j * 2 + 1]; l = (j == 1 || j == 2) ? 48 : 16; if (k == 0) { sigdata->channel_pan[i++] = l; } else if (k == 1) { sigdata->channel_pan[i++] = l; sigdata->channel_pan[i++] = l; } } free_okt(mod); /* Now let's initialise the remaining variables, and we're done! */ sigdata->flags = IT_WAS_AN_OKT | IT_WAS_AN_XM | IT_WAS_A_MOD | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX | IT_STEREO; sigdata->global_volume = 128; sigdata->mixing_volume = 48; /* We want 50 ticks per second; 50/6 row advances per second; * 50*10=500 row advances per minute; 500/4=125 beats per minute. */ sigdata->tempo = 125; sigdata->pan_separation = 128; memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS); memset(sigdata->channel_pan + n_channels, 32, DUMB_IT_N_CHANNELS - n_channels); _dumb_it_fix_invalid_orders(sigdata); return sigdata; }
static DUMB_IT_SIGDATA *it_riff_dsmf_load_sigdata( DUMBFILE * f, struct riff * stream ) { DUMB_IT_SIGDATA *sigdata; int n, o, found; if ( ! stream ) goto error; if ( stream->type != DUMB_ID( 'D', 'S', 'M', 'F' ) ) goto error; sigdata = malloc(sizeof(*sigdata)); if ( ! sigdata ) goto error; sigdata->n_patterns = 0; sigdata->n_samples = 0; sigdata->name[0] = 0; found = 0; for ( n = 0; (unsigned)n < stream->chunk_count; ++n ) { struct riff_chunk * c = stream->chunks + n; switch( c->type ) { case DUMB_ID( 'S' ,'O' ,'N' ,'G' ): /* initialization data */ if ( ( found ) || ( c->size < 192 ) ) goto error_sd; found = 1; break; case DUMB_ID( 'P', 'A', 'T', 'T' ): ++ sigdata->n_patterns; break; case DUMB_ID( 'I', 'N', 'S', 'T' ): ++ sigdata->n_samples; break; } } if ( !found || !sigdata->n_samples || !sigdata->n_patterns ) goto error_sd; if ( sigdata->n_samples > 255 || sigdata->n_patterns > 255 ) goto error_sd; sigdata->song_message = NULL; sigdata->order = NULL; sigdata->instrument = NULL; sigdata->sample = NULL; sigdata->pattern = NULL; sigdata->midi = NULL; sigdata->checkpoint = NULL; sigdata->mixing_volume = 48; sigdata->pan_separation = 128; sigdata->n_instruments = 0; sigdata->n_orders = 0; sigdata->restart_position = 0; memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS); for (n = 0; n < DUMB_IT_N_CHANNELS; n += 4) { int sep = 32 * dumb_it_default_panning_separation / 100; sigdata->channel_pan[n ] = 32 - sep; sigdata->channel_pan[n+1] = 32 + sep; sigdata->channel_pan[n+2] = 32 + sep; sigdata->channel_pan[n+3] = 32 - sep; } for ( n = 0; (unsigned)n < stream->chunk_count; ++n ) { struct riff_chunk * c = stream->chunks + n; switch ( c->type ) { case DUMB_ID( 'S', 'O', 'N', 'G' ): if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_usd; dumbfile_getnc( (char *) sigdata->name, 28, f ); sigdata->name[ 28 ] = 0; sigdata->flags = IT_STEREO | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX; dumbfile_skip( f, 36 - 28 ); sigdata->n_orders = dumbfile_igetw( f ); //sigdata->n_samples = ptr[ 38 ] | ( ptr[ 39 ] << 8 ); // whatever //sigdata->n_patterns = ptr[ 40 ] | ( ptr[ 41 ] << 8 ); dumbfile_skip( f, 42 - 38 ); sigdata->n_pchannels = dumbfile_igetw( f ); sigdata->global_volume = dumbfile_getc( f ); sigdata->mixing_volume = dumbfile_getc( f ); sigdata->speed = dumbfile_getc( f ); sigdata->tempo = dumbfile_getc( f ); for ( o = 0; o < 16; ++o ) { sigdata->channel_pan[ o ] = dumbfile_getc( f ) / 2; } sigdata->order = malloc( 128 ); if ( ! sigdata->order ) goto error_usd; dumbfile_getnc( (char *) sigdata->order, 128, f ); break; } } sigdata->pattern = malloc( sigdata->n_patterns * sizeof( *sigdata->pattern ) ); if ( ! sigdata->pattern ) goto error_usd; for ( n = 0; n < sigdata->n_patterns; ++n ) sigdata->pattern[ n ].entry = NULL; sigdata->sample = malloc( sigdata->n_samples * sizeof( *sigdata->sample ) ); if ( ! sigdata->sample ) goto error_usd; for ( n = 0; n < sigdata->n_samples; ++n ) { IT_SAMPLE * sample = sigdata->sample + n; sample->data = NULL; } sigdata->n_samples = 0; sigdata->n_patterns = 0; for ( n = 0; (unsigned)n < stream->chunk_count; ++n ) { struct riff_chunk * c = stream->chunks + n; switch ( c->type ) { case DUMB_ID( 'P', 'A', 'T', 'T' ): if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_usd; if ( it_riff_dsmf_process_pattern( sigdata->pattern + sigdata->n_patterns, f, c->size ) ) goto error_usd; ++ sigdata->n_patterns; break; case DUMB_ID( 'I', 'N', 'S', 'T' ): if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_usd; if ( it_riff_dsmf_process_sample( sigdata->sample + sigdata->n_samples, f, c->size ) ) goto error_usd; ++ sigdata->n_samples; break; } } _dumb_it_fix_invalid_orders( sigdata ); return sigdata; error_usd: _dumb_it_unload_sigdata( sigdata ); goto error; error_sd: free( sigdata ); error: return NULL; }
static int it_s3m_read_sample_header(IT_SAMPLE *sample, long *offset, unsigned char *pack, int cwtv, DUMBFILE *f) { unsigned char type; int flags; type = dumbfile_getc(f); dumbfile_getnc((char *)sample->filename, 12, f); sample->filename[12] = 0; if (type > 1) { /** WARNING: no adlib support */ dumbfile_skip(f, 3 + 12 + 1 + 1 + 2 + 2 + 2 + 12); dumbfile_getnc((char *)sample->name, 28, f); sample->name[28] = 0; dumbfile_skip(f, 4); sample->flags &= ~IT_SAMPLE_EXISTS; return dumbfile_error(f); } *offset = dumbfile_getc(f) << 20; *offset += dumbfile_igetw(f) << 4; sample->length = dumbfile_igetl(f); sample->loop_start = dumbfile_igetl(f); sample->loop_end = dumbfile_igetl(f); sample->default_volume = dumbfile_getc(f); dumbfile_skip(f, 1); flags = dumbfile_getc(f); if (flags < 0 || (flags != 0 && flags != 4)) /* Sample is packed apparently (or error reading from file). We don't * know how to read packed samples. */ return -1; *pack = flags; flags = dumbfile_getc(f); sample->C5_speed = dumbfile_igetl(f) << 1; /* Skip four unused bytes and three internal variables. */ dumbfile_skip(f, 4 + 2 + 2 + 4); dumbfile_getnc((char *)sample->name, 28, f); sample->name[28] = 0; if (type == 0 || sample->length <= 0) { /* Looks like no-existy. Anyway, there's for sure no 'SCRS' ... */ sample->flags &= ~IT_SAMPLE_EXISTS; return dumbfile_error(f); } if (dumbfile_mgetl(f) != DUMB_ID('S', 'C', 'R', 'S')) return -1; sample->global_volume = 64; sample->flags = IT_SAMPLE_EXISTS; if (flags & 1) sample->flags |= IT_SAMPLE_LOOP; /* The ST3 TECH.DOC is unclear on this, but IMAGO Orpheus is not. Piece of * crap. */ if (flags & 2) { sample->flags |= IT_SAMPLE_STEREO; if ((cwtv & 0xF000) == 0x2000) { sample->length >>= 1; sample->loop_start >>= 1; sample->loop_end >>= 1; }
struct riff *riff_parse(DUMBFILE *f, long offset, long size, unsigned proper) { unsigned stream_size; struct riff *stream; if (size < 8) return 0; if (dumbfile_seek(f, offset, DFS_SEEK_SET)) return 0; if (dumbfile_mgetl(f) != DUMB_ID('R', 'I', 'F', 'F')) return 0; stream_size = (int)dumbfile_igetl(f); if (stream_size + 8 > size) return 0; if (stream_size < 4) return 0; stream = (struct riff *)malloc(sizeof(struct riff)); if (!stream) return 0; stream->type = (int)dumbfile_mgetl(f); stream->chunk_count = 0; stream->chunks = 0; stream_size -= 4; while (stream_size && !dumbfile_error(f)) { struct riff_chunk *chunk; if (stream_size < 8) break; stream->chunks = (struct riff_chunk *)realloc( stream->chunks, (stream->chunk_count + 1) * sizeof(struct riff_chunk)); if (!stream->chunks) break; chunk = stream->chunks + stream->chunk_count; chunk->type = (int)dumbfile_mgetl(f); chunk->size = (int)dumbfile_igetl(f); chunk->offset = dumbfile_pos(f); stream_size -= 8; if (stream_size < chunk->size) break; if (chunk->type == DUMB_ID('R', 'I', 'F', 'F')) { chunk->nested = riff_parse(f, chunk->offset - 8, chunk->size + 8, proper); if (!chunk->nested) break; } else { chunk->nested = 0; } dumbfile_seek(f, chunk->offset + chunk->size, DFS_SEEK_SET); stream_size -= chunk->size; if (proper && (chunk->size & 1)) { dumbfile_skip(f, 1); --stream_size; } ++stream->chunk_count; } if (stream_size) { riff_free(stream); stream = 0; } return stream; }
static DUMB_IT_SIGDATA *it_riff_dsmf_load_sigdata( struct riff * stream ) { DUMB_IT_SIGDATA *sigdata; int n, o, found; unsigned char * ptr; if ( ! stream ) goto error; if ( stream->type != DUMB_ID( 'D', 'S', 'M', 'F' ) ) goto error; sigdata = malloc(sizeof(*sigdata)); if ( ! sigdata ) goto error; sigdata->n_patterns = 0; sigdata->n_samples = 0; sigdata->name[0] = 0; found = 0; for ( n = 0; (unsigned int)n < stream->chunk_count; ++n ) { struct riff_chunk * c = stream->chunks + n; switch( c->type ) { case DUMB_ID( 'S' ,'O' ,'N' ,'G' ): /* initialization data */ if ( ( found ) || ( c->size < 192 ) ) goto error_sd; found = 1; break; case DUMB_ID( 'P', 'A', 'T', 'T' ): ++ sigdata->n_patterns; break; case DUMB_ID( 'I', 'N', 'S', 'T' ): ++ sigdata->n_samples; break; } } if ( !found || !sigdata->n_samples || !sigdata->n_patterns ) goto error_sd; if ( sigdata->n_samples > 255 || sigdata->n_patterns > 255 ) goto error_sd; sigdata->song_message = NULL; sigdata->order = NULL; sigdata->instrument = NULL; sigdata->sample = NULL; sigdata->pattern = NULL; sigdata->midi = NULL; sigdata->checkpoint = NULL; sigdata->mixing_volume = 48; sigdata->pan_separation = 128; sigdata->n_instruments = 0; sigdata->n_orders = 0; sigdata->restart_position = 0; memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS); for (n = 0; n < DUMB_IT_N_CHANNELS; n += 4) { sigdata->channel_pan[n ] = 16; sigdata->channel_pan[n+1] = 48; sigdata->channel_pan[n+2] = 48; sigdata->channel_pan[n+3] = 16; } for ( n = 0; (unsigned int)n < stream->chunk_count; ++n ) { struct riff_chunk * c = stream->chunks + n; switch ( c->type ) { case DUMB_ID( 'S', 'O', 'N', 'G' ): ptr = ( unsigned char * ) c->data; memcpy( sigdata->name, c->data, 28 ); sigdata->name[ 28 ] = 0; sigdata->flags = IT_WAS_AN_XM | IT_WAS_A_MOD | IT_STEREO | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX; sigdata->n_orders = ptr[ 36 ] | ( ptr[ 37 ] << 8 ); //sigdata->n_samples = ptr[ 38 ] | ( ptr[ 39 ] << 8 ); // whatever //sigdata->n_patterns = ptr[ 40 ] | ( ptr[ 41 ] << 8 ); sigdata->n_pchannels = ptr[ 42 ] | ( ptr[ 43 ] << 8 ); sigdata->global_volume = ptr[ 44 ]; sigdata->mixing_volume = ptr[ 45 ]; sigdata->speed = ptr[ 46 ]; sigdata->tempo = ptr[ 47 ]; for ( o = 0; o < 16; ++o ) { sigdata->channel_pan[ o ] = ptr[ 48 + o ] / 2; } sigdata->order = malloc( 128 ); if ( ! sigdata->order ) goto error_usd; memcpy( sigdata->order, ptr + 64, 128 ); break; } } sigdata->pattern = malloc( sigdata->n_patterns * sizeof( *sigdata->pattern ) ); if ( ! sigdata->pattern ) goto error_usd; for ( n = 0; n < sigdata->n_patterns; ++n ) sigdata->pattern[ n ].entry = NULL; sigdata->sample = malloc( sigdata->n_samples * sizeof( *sigdata->sample ) ); if ( ! sigdata->sample ) goto error_usd; for ( n = 0; n < sigdata->n_samples; ++n ) { IT_SAMPLE * sample = sigdata->sample + n; sample->data = NULL; } sigdata->n_samples = 0; sigdata->n_patterns = 0; for ( n = 0; (unsigned int)n < stream->chunk_count; ++n ) { struct riff_chunk * c = stream->chunks + n; switch ( c->type ) { case DUMB_ID( 'P', 'A', 'T', 'T' ): if ( it_riff_dsmf_process_pattern( sigdata->pattern + sigdata->n_patterns, ( unsigned char * ) c->data, c->size ) ) goto error_usd; ++ sigdata->n_patterns; break; case DUMB_ID( 'I', 'N', 'S', 'T' ): if ( it_riff_dsmf_process_sample( sigdata->sample + sigdata->n_samples, ( unsigned char * ) c->data, c->size ) ) goto error_usd; ++ sigdata->n_samples; break; } } _dumb_it_fix_invalid_orders( sigdata ); return sigdata; error_usd: _dumb_it_unload_sigdata( sigdata ); goto error; error_sd: free( sigdata ); error: return NULL; }
static int it_s3m_read_sample_header(IT_SAMPLE *sample, long *offset, DUMBFILE *f) { unsigned char type; int flags; type = dumbfile_getc(f); if (type > 1) { /** WARNING: no adlib support */ } dumbfile_getnc(sample->filename, 13, f); sample->filename[13] = 0; *offset = dumbfile_igetw(f) << 4; sample->length = dumbfile_igetl(f); sample->loop_start = dumbfile_igetl(f); sample->loop_end = dumbfile_igetl(f); sample->default_volume = dumbfile_getc(f); dumbfile_skip(f, 1); if (dumbfile_getc(f) != 0) /* Sample is packed apparently (or error reading from file). We don't * know how to read packed samples. */ return -1; flags = dumbfile_getc(f); sample->C5_speed = dumbfile_igetl(f) << 1; /* Skip four unused bytes and three internal variables. */ dumbfile_skip(f, 4+2+2+4); dumbfile_getnc(sample->name, 28, f); sample->name[28] = 0; if (type == 0) { /* Looks like no-existy. Anyway, there's for sure no 'SCRS' ... */ sample->flags &= ~IT_SAMPLE_EXISTS; return dumbfile_error(f); } if (dumbfile_mgetl(f) != DUMB_ID('S','C','R','S')) return -1; sample->global_volume = 64; sample->flags = IT_SAMPLE_EXISTS; if (flags & 1) sample->flags |= IT_SAMPLE_LOOP; if (flags & 2) sample->flags |= IT_SAMPLE_STEREO; if (flags & 4) sample->flags |= IT_SAMPLE_16BIT; sample->default_pan = 0; // 0 = don't use, or 160 = centre? if (sample->length <= 0) sample->flags &= ~IT_SAMPLE_EXISTS; else if (sample->flags & IT_SAMPLE_LOOP) { if ((unsigned int)sample->loop_end > (unsigned int)sample->length) sample->flags &= ~IT_SAMPLE_LOOP; else if ((unsigned int)sample->loop_start >= (unsigned int)sample->loop_end) sample->flags &= ~IT_SAMPLE_LOOP; else /* ScreamTracker seems not to save what comes after the loop end * point, but rather to assume it is a duplicate of what comes at * the loop start point. I am not completely sure of this though. * It is easy to evade; simply truncate the sample. */ sample->length = sample->loop_end; } //Do we need to set all these? sample->vibrato_speed = 0; sample->vibrato_depth = 0; sample->vibrato_rate = 0; sample->vibrato_waveform = IT_VIBRATO_SINE; return dumbfile_error(f); }
struct riff * riff_parse( unsigned char * ptr, unsigned size, unsigned proper ) { unsigned stream_size; struct riff * stream; if ( size < 8 ) return 0; if ( ptr[0] != 'R' || ptr[1] != 'I' || ptr[2] != 'F' || ptr[3] != 'F' ) return 0; stream_size = ptr[4] | ( ptr[5] << 8 ) | ( ptr[6] << 16 ) | ( ptr[7] << 24 ); if ( stream_size + 8 > size ) return 0; if ( stream_size < 4 ) return 0; stream = malloc( sizeof( struct riff ) ); if ( ! stream ) return 0; stream->type = ( ptr[8] << 24 ) | ( ptr[9] << 16 ) | ( ptr[10] << 8 ) | ptr[11]; stream->chunk_count = 0; stream->chunks = 0; ptr += 12; stream_size -= 4; while ( stream_size ) { struct riff_chunk * chunk; if ( stream_size < 8 ) break; stream->chunks = realloc( stream->chunks, ( stream->chunk_count + 1 ) * sizeof( struct riff_chunk ) ); if ( ! stream->chunks ) break; chunk = stream->chunks + stream->chunk_count; chunk->type = ( ptr[0] << 24 ) | ( ptr[1] << 16 ) | ( ptr[2] << 8 ) | ptr[3]; chunk->size = ptr[4] | ( ptr[5] << 8 ) | ( ptr[6] << 16 ) | ( ptr[7] << 24 ); ptr += 8; stream_size -= 8; if ( stream_size < chunk->size ) break; if ( chunk->type == DUMB_ID('R','I','F','F') ) { chunk->data = riff_parse( ptr - 8, chunk->size + 8, proper ); if ( ! chunk->data ) break; } else { chunk->data = malloc( chunk->size ); if ( ! chunk->data ) break; memcpy( chunk->data, ptr, chunk->size ); } ptr += chunk->size; stream_size -= chunk->size; if ( proper && ( chunk->size & 1 ) ) { ++ ptr; -- stream_size; } ++stream->chunk_count; } if ( stream_size ) { riff_free( stream ); stream = 0; } return stream; }