diff options
author | Alexey Yakovenko <wakeroid@gmail.com> | 2009-07-19 13:50:36 +0200 |
---|---|---|
committer | Alexey Yakovenko <wakeroid@gmail.com> | 2009-07-19 13:50:36 +0200 |
commit | e89e2345859798fa596e01bd9460a63c92785f49 (patch) | |
tree | bf1f0c36b9ded842a43e6fb09a764dce9ce0311b /cdumb.c | |
parent | b41446ad033a52ed24176f9ba01362e3648e97ee (diff) |
better format checking before adding to playlist,
more file types supported,
bad files are skipped when attempted to be played
Diffstat (limited to 'cdumb.c')
-rw-r--r-- | cdumb.c | 601 |
1 files changed, 584 insertions, 17 deletions
@@ -8,7 +8,7 @@ extern int sdl_player_freq; // hack! static int dumb_initialized; -static DUH *myduh; +static DUH *duh; static DUH_SIGRENDERER *renderer; //#define DUMB_RQ_ALIASING //#define DUMB_RQ_LINEAR @@ -17,60 +17,84 @@ static DUH_SIGRENDERER *renderer; extern int dumb_resampling_quality; extern int dumb_it_max_to_mix; -void +static void cdumb_free (void); -int +static int cdumb_startrenderer (void); +static DUH* +open_module(const char *fname, const char *ext, int *start_order, int *is_it, int *is_dos); + int cdumb_init (const char *fname, int track, float start, float end) { if (!dumb_initialized) { atexit (&dumb_exit); } dumb_register_stdfiles (); + + int start_order = 0; + int is_dos, is_it; + const char *ext = fname + strlen (fname) - 1; + while (*ext != '.' && ext > fname) { + ext--; + } + ext++; + duh = open_module(fname, ext, &start_order, &is_it, &is_dos ); + +// if (is_it) ReadIT(ptr, size, *m_info, !read_tag); +// else ReadDUH(duh, *m_info, !read_tag, is_dos); +// +// // subsong magic time +// g_cache.run( ptr, size, p_path, m_file->get_timestamp( p_abort ), m_subsong_info, p_abort ); + + +#if 0 const char *ext = fname + strlen (fname) - 1; while (*ext != '.' && ext > fname) { ext--; } ext++; if (!strcasecmp (ext, "mod")) { - myduh = dumb_load_mod_quick (fname, 0); + duh = dumb_load_mod_quick (fname, 0); } else if (!strcasecmp (ext, "s3m")) { - myduh = dumb_load_s3m_quick (fname); + duh = dumb_load_s3m_quick (fname); } else if (!strcasecmp (ext, "it")) { - myduh = dumb_load_it_quick (fname); + duh = dumb_load_it_quick (fname); } else if (!strcasecmp (ext, "xm")) { - myduh = dumb_load_xm_quick (fname); + duh = dumb_load_xm_quick (fname); } else { return -1; } - dumb_it_do_initial_runthrough (myduh); +#endif + dumb_it_do_initial_runthrough (duh); cdumb.info.bitsPerSample = 16; cdumb.info.channels = 2; cdumb.info.samplesPerSecond = sdl_player_freq; cdumb.info.position = 0; - cdumb.info.duration = duh_get_length (myduh)/65536.0f; + cdumb.info.duration = duh_get_length (duh)/65536.0f; printf ("duration: %f\n", cdumb.info.duration); - cdumb_startrenderer (); + if (cdumb_startrenderer () < 0) { + return -1; + } return 0; } -int +static int cdumb_startrenderer (void) { // reopen if (renderer) { duh_end_sigrenderer (renderer); renderer = NULL; } - renderer = duh_start_sigrenderer (myduh, 0, 2, 0); + renderer = duh_start_sigrenderer (duh, 0, 2, 0); if (!renderer) { cdumb_free (); return -1; @@ -81,17 +105,18 @@ cdumb_startrenderer (void) { dumb_it_set_resampling_quality (itsr, 2); dumb_it_set_xm_speed_zero_callback (itsr, &dumb_it_callback_terminate, NULL); dumb_it_set_global_volume_zero_callback (itsr, &dumb_it_callback_terminate, NULL); + return 0; } -void +static void cdumb_free (void) { if (renderer) { duh_end_sigrenderer (renderer); renderer = NULL; } - if (myduh) { - unload_duh (myduh); - myduh = NULL; + if (duh) { + unload_duh (duh); + duh = NULL; } } @@ -118,16 +143,558 @@ cdumb_seek (float time) { return 0; } +static const char * exts[]= +{ + "mod","mdz", + "s3m","s3z", + "stm","stz", + "it","itz", + "xm","xmz", + "ptm","ptz", + "mtm","mtz", + "669", + "psm", + "umx", + "am","j2b", + "dsm", + "amf", + NULL +}; + +// derived from mod.cpp of foo_dumb source code +static DUH * open_module(const char *fname, const char *ext, int *start_order, int *is_it, int *is_dos) +{ + DUH * duh = 0; + + *is_it = 0; + *is_dos = 1; + + char ptr[2000]; + FILE *fp = fopen (fname, "rb"); + if (!fp) { + return NULL; + } + int size = fread (ptr, 1, 2000, fp); + fclose (fp); + + DUMBFILE * f = dumbfile_open (fname); + if (!f) { + return NULL; + } + +// {{{ no umr yet +#if 0 + if (size >= 4 && + ptr[0] == 0xC1 && ptr[1] == 0x83 && + ptr[2] == 0x2A && ptr[3] == 0x9E) + { + umr_mem_reader memreader(ptr, size); + umr::upkg pkg; + if (pkg.open(&memreader)) + { + for (int i = 1, j = pkg.ocount(); i <= j; i++) + { + char * classname = pkg.oclassname(i); + if (classname && !strcmp(pkg.oclassname(i), "Music")) + { + char * type = pkg.otype(i); + if (!type) continue; + /* + if (!stricmp(type, "it")) + { + is_it = true; + ptr += memdata.offset = pkg.object_offset(i); + size = memdata.size = memdata.offset + pkg.object_size(i); + duh = dumb_read_it_quick(f); + break; + } + else if (!stricmp(type, "s3m")) + { + memdata.offset = pkg.object_offset(i); + memdata.size = memdata.offset + pkg.object_size(i); + duh = dumb_read_s3m_quick(f); + break; + } + else if (!stricmp(type, "xm")) + { + memdata.offset = pkg.object_offset(i); + memdata.size = memdata.offset + pkg.object_size(i); + duh = dumb_read_xm_quick(f); + break; + } + */ + // blah, type can't be trusted + if (!stricmp(type, "it") || !stricmp(type, "s3m") || !stricmp(type, "xm")) + { + ptr += memdata.offset = pkg.object_offset(i); + size = memdata.size = memdata.offset + pkg.object_size(i); + if (size >= 4 && ptr[0] == 'I' && ptr[1] == 'M' && ptr[2] == 'P' && ptr[3] == 'M') + { + is_it = true; + duh = dumb_read_it_quick(f); + } + else if (size >= 42 && ptr[38] == 'F' && ptr[39] == 'a' && ptr[40] == 's' && ptr[41] == 't') + { + duh = dumb_read_xm_quick(f); + } + else if (size >= 48 && ptr[44] == 'S' && ptr[45] == 'C' && ptr[46] == 'R' && ptr[47] == 'M') + { + duh = dumb_read_s3m_quick(f); + } + + break; + } + } + } + } + } + else +#endif +// end of umr code +// }}} + if (size >= 4 && + ptr[0] == 'I' && ptr[1] == 'M' && + ptr[2] == 'P' && ptr[3] == 'M') + { + *is_it = 1; + duh = dumb_read_it_quick(f); + } + else if (size >= 17 && !memcmp(ptr, "Extended Module: ", 17)) + { + duh = dumb_read_xm_quick(f); + } + else if (size >= 0x30 && + ptr[0x2C] == 'S' && ptr[0x2D] == 'C' && + ptr[0x2E] == 'R' && ptr[0x2F] == 'M') + { + duh = dumb_read_s3m_quick(f); + } + else if (size >= 1168 && + /*ptr[28] == 0x1A &&*/ ptr[29] == 2 && + ( ! strncasecmp( ( const char * ) ptr + 20, "!Scream!", 8 ) || + ! strncasecmp( ( const char * ) ptr + 20, "BMOD2STM", 8 ) || + ! strncasecmp( ( const char * ) ptr + 20, "WUZAMOD!", 8 ) ) ) + { + duh = dumb_read_stm_quick(f); + } + else if (size >= 2 && + ((ptr[0] == 0x69 && ptr[1] == 0x66) || + (ptr[0] == 0x4A && ptr[1] == 0x4E))) + { + duh = dumb_read_669_quick(f); + } + else if (size >= 0x30 && + ptr[0x2C] == 'P' && ptr[0x2D] == 'T' && + ptr[0x2E] == 'M' && ptr[0x2F] == 'F') + { + duh = dumb_read_ptm_quick(f); + } + else if (size >= 4 && + ptr[0] == 'P' && ptr[1] == 'S' && + ptr[2] == 'M' && ptr[3] == ' ') + { + duh = dumb_read_psm_quick(f, *start_order); + *start_order = 0; + } + else if (size >= 4 && + ptr[0] == 'P' && ptr[1] == 'S' && + ptr[2] == 'M' && ptr[3] == 254) + { + duh = dumb_read_old_psm_quick(f); + } + else if (size >= 3 && + ptr[0] == 'M' && ptr[1] == 'T' && + ptr[2] == 'M') + { + duh = dumb_read_mtm_quick(f); + } + else if ( size >= 4 && + ptr[0] == 'R' && ptr[1] == 'I' && + ptr[2] == 'F' && ptr[3] == 'F') + { + duh = dumb_read_riff_quick(f); + } + else if ( size >= 32 && + !memcmp( ptr, "ASYLUM Music Format", 19 ) && + !memcmp( ptr + 19, " V1.0", 5 ) ) + { + duh = dumb_read_asy_quick(f); + } + + if (!duh) + { + dumbfile_close(f); + f = dumbfile_open (fname); + *is_dos = 0; + duh = dumb_read_mod_quick (f, (!strcasecmp (ext, exts[0]) || !strcasecmp (ext, exts[1])) ? 0 : 1); + } + + if (f) { + dumbfile_close(f); + } + +// {{{ no volume ramping +#if 0 + // XXX test + if (duh) + { + int ramp_mode = 0; // none + if (ramp_mode) + { + DUMB_IT_SIGDATA * itsd = duh_get_it_sigdata(duh); + if (itsd) + { + if (ramp_mode > 2) + { + if ( ( itsd->flags & ( IT_WAS_AN_XM | IT_WAS_A_MOD ) ) == IT_WAS_AN_XM ) + ramp_mode = 2; + else + ramp_mode = 1; + } + for (int i = 0, j = itsd->n_samples; i < j; i++) + { + IT_SAMPLE * sample = &itsd->sample[i]; + if ( sample->flags & IT_SAMPLE_EXISTS && !( sample->flags & IT_SAMPLE_LOOP ) ) + { + double rate = 1. / double( sample->C5_speed ); + double length = double( sample->length ) * rate; + if ( length >= .1 ) + { + int k, l = sample->length; + if ( ramp_mode == 1 && ( ( rate * 16. ) < .01 ) ) + { + if (sample->flags & IT_SAMPLE_16BIT) + { + k = l - 15; + signed short * data = (signed short *) sample->data; + if (sample->flags & IT_SAMPLE_STEREO) + { + for (int shift = 1; k < l; k++, shift++) + { + data [k * 2] >>= shift; + data [k * 2 + 1] >>= shift; + } + } + else + { + for (int shift = 1; k < l; k++, shift++) + { + data [k] >>= shift; + } + } + } + else + { + k = l - 7; + signed char * data = (signed char *) sample->data; + if (sample->flags & IT_SAMPLE_STEREO) + { + for (int shift = 1; k < l; k++, shift++) + { + data [k * 2] >>= shift; + data [k * 2 + 1] >>= shift; + } + } + else + { + for (int shift = 1; k < l; k++, shift++) + { + data [k] >>= shift; + } + } + } + } + else + { + int m = int( .01 * double( sample->C5_speed ) + .5 ); + k = l - m; + if (sample->flags & IT_SAMPLE_16BIT) + { + signed short * data = (signed short *) sample->data; + if (sample->flags & IT_SAMPLE_STEREO) + { + for (; k < l; k++) + { + data [k * 2] = MulDiv( data [k * 2], l - k, m ); + data [k * 2 + 1] = MulDiv( data [k * 2 + 1], l - k, m ); + } + } + else + { + for (; k < l; k++) + { + data [k] = MulDiv( data [k], l - k, m ); + } + } + } + else + { + signed char * data = (signed char *) sample->data; + if (sample->flags & IT_SAMPLE_STEREO) + { + for (; k < l; k++) + { + data [k * 2] = MulDiv( data [k * 2], l - k, m ); + data [k * 2 + 1] = MulDiv( data [k * 2 + 1], l - k, m ); + } + } + else + { + for (; k < l; k++) + { + data [k] = MulDiv( data [k], l - k, m ); + } + } + } + } + } + } + } + } + } + } +#endif +// }}} + +// {{{ no autochip +#if 0 + if (duh && cfg_autochip) + { + int size_force = cfg_autochip_size_force; + int size_scan = cfg_autochip_size_scan; + int scan_threshold_8 = ((cfg_autochip_scan_threshold * 0x100) + 50) / 100; + int scan_threshold_16 = ((cfg_autochip_scan_threshold * 0x10000) + 50) / 100; + DUMB_IT_SIGDATA * itsd = duh_get_it_sigdata(duh); + + if (itsd) + { + for (int i = 0, j = itsd->n_samples; i < j; i++) + { + IT_SAMPLE * sample = &itsd->sample[i]; + if (sample->flags & IT_SAMPLE_EXISTS) + { + int channels = sample->flags & IT_SAMPLE_STEREO ? 2 : 1; + if (sample->length < size_force) sample->max_resampling_quality = 0; + else if (sample->length < size_scan) + { + if ((sample->flags & (IT_SAMPLE_LOOP|IT_SAMPLE_PINGPONG_LOOP)) == IT_SAMPLE_LOOP) + { + int loop_start = sample->loop_start * channels; + int loop_end = sample->loop_end * channels; + int s1, s2; + if (sample->flags & IT_SAMPLE_16BIT) + { + s1 = ((signed short *)sample->data)[loop_start]; + s2 = ((signed short *)sample->data)[loop_end - channels]; + if (abs(s1 - s2) > scan_threshold_16) + { + sample->max_resampling_quality = 0; + continue; + } + if (channels == 2) + { + s1 = ((signed short *)sample->data)[loop_start + 1]; + s2 = ((signed short *)sample->data)[loop_end - 1]; + if (abs(s1 - s2) > scan_threshold_16) + { + sample->max_resampling_quality = 0; + continue; + } + } + } + else + { + s1 = ((signed char *)sample->data)[loop_start]; + s2 = ((signed char *)sample->data)[loop_end - channels]; + if (abs(s1 - s2) > scan_threshold_8) + { + sample->max_resampling_quality = 0; + continue; + } + if (channels == 2) + { + s1 = ((signed char *)sample->data)[loop_start + 1]; + s2 = ((signed char *)sample->data)[loop_end - 1]; + if (abs(s1 - s2) > scan_threshold_8) + { + sample->max_resampling_quality = 0; + continue; + } + } + } + } + if ((sample->flags & (IT_SAMPLE_SUS_LOOP|IT_SAMPLE_PINGPONG_SUS_LOOP)) == IT_SAMPLE_SUS_LOOP) + { + int sus_loop_start = sample->sus_loop_start * channels; + int sus_loop_end = sample->sus_loop_end * channels; + int s1, s2; + if (sample->flags & IT_SAMPLE_16BIT) + { + s1 = ((signed short *)sample->data)[sus_loop_start]; + s2 = ((signed short *)sample->data)[sus_loop_end - channels]; + if (abs(s1 - s2) > scan_threshold_16) + { + sample->max_resampling_quality = 0; + continue; + } + if (channels == 2) + { + s1 = ((signed short *)sample->data)[sus_loop_start + 1]; + s2 = ((signed short *)sample->data)[sus_loop_end - 1]; + if (abs(s1 - s2) > scan_threshold_16) + { + sample->max_resampling_quality = 0; + continue; + } + } + } + else + { + s1 = ((signed char *)sample->data)[sus_loop_start]; + s2 = ((signed char *)sample->data)[sus_loop_end - channels]; + if (abs(s1 - s2) > scan_threshold_8) + { + sample->max_resampling_quality = 0; + continue; + } + if (channels == 2) + { + s1 = ((signed char *)sample->data)[sus_loop_start + 1]; + s2 = ((signed char *)sample->data)[sus_loop_end - 1]; + if (abs(s1 - s2) > scan_threshold_8) + { + sample->max_resampling_quality = 0; + continue; + } + } + } + } + + int k, l = sample->length * channels; + if (sample->flags & IT_SAMPLE_LOOP) l = sample->loop_end * channels; + if (sample->flags & IT_SAMPLE_16BIT) + { + for (k = channels; k < l; k += channels) + { + if (abs(((signed short *)sample->data)[k - channels] - ((signed short *)sample->data)[k]) > scan_threshold_16) + { + break; + } + } + if (k < l) + { + sample->max_resampling_quality = 0; + continue; + } + if (channels == 2) + { + for (k = 2 + 1; k < l; k += 2) + { + if (abs(((signed short *)sample->data)[k - 2] - ((signed short *)sample->data)[k]) > scan_threshold_16) + { + break; + } + } + } + if (k < l) + { + sample->max_resampling_quality = 0; + continue; + } + } + else + { + for (k = channels; k < l; k += channels) + { + if (abs(((signed char *)sample->data)[k - channels] - ((signed char *)sample->data)[k]) > scan_threshold_8) + { + break; + } + } + if (k < l) + { + sample->max_resampling_quality = 0; + continue; + } + if (channels == 2) + { + for (k = 2 + 1; k < l; k += 2) + { + if (abs(((signed char *)sample->data)[k - 2] - ((signed char *)sample->data)[k]) > scan_threshold_8) + { + break; + } + } + } + if (k < l) + { + sample->max_resampling_quality = 0; + continue; + } + } + } + } + } + } + } +#endif +// }}} + +// {{{ no trim +#if 0 + if ( duh && cfg_trim ) + { + if ( dumb_it_trim_silent_patterns( duh ) < 0 ) + { + unload_duh( duh ); + duh = 0; + } + } +#endif +// }}} + + return duh; +} + int cdumb_add (const char *fname) { + const char *ext = fname + strlen (fname) - 1; + while (*ext != '.' && ext > fname) { + ext--; + } + ext++; + int start_order = 0; + int is_it; + int is_dos; + dumb_register_stdfiles (); + DUH* duh = open_module(fname, ext, &start_order, &is_it, &is_dos); + if (!duh) { + return -1; + } + unload_duh (duh); + playItem_t *it = malloc (sizeof (playItem_t)); + memset (it, 0, sizeof (playItem_t)); + it->codec = &cdumb; + it->fname = strdup (fname); + it->tracknum = 0; + it->timestart = 0; + it->timeend = 0; + it->displayname = strdup (fname); + ps_append_item (it); + return 0; } +const char **cdumb_getexts (void) { + return exts; +} + codec_t cdumb = { .init = cdumb_init, .free = cdumb_free, .read = cdumb_read, .seek = cdumb_seek, - .add = cdumb_add + .add = cdumb_add, + .getexts = cdumb_getexts }; |