/* 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; }
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; }
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; }