rlm@0: /* Trims silence off beginning of SPC file. rlm@0: Requires the accurate DSP; won't compile with the fast DSP. rlm@0: Please note that the algorithm could be improved; this is just rlm@0: a simple example showing the idea. rlm@0: rlm@0: Usage: trim_spc [test.spc [trimmed.spc]] rlm@0: */ rlm@0: rlm@0: #include "snes_spc/spc.h" rlm@0: rlm@0: #include "demo_util.h" /* error(), load_file() */ rlm@0: rlm@0: /* Change to 1 to have it trim to next key on event rather than trim silence */ rlm@0: enum { use_kon_check = 0 }; rlm@0: rlm@0: /* True if all count samples from in are silent (or very close to it) */ rlm@0: int is_silent( short const* in, int count ); rlm@0: rlm@0: int main( int argc, char** argv ) rlm@0: { rlm@0: /* Load file into memory */ rlm@0: long spc_size; rlm@0: void* spc = load_file( (argc > 1) ? argv [1] : "test.spc", &spc_size ); rlm@0: rlm@0: /* Load into emulator */ rlm@0: SNES_SPC* snes_spc = spc_new(); rlm@0: if ( !snes_spc ) error( "Out of memory" ); rlm@0: error( spc_load_spc( snes_spc, spc, spc_size ) ); rlm@0: rlm@0: /* Expand SPC data so there's enough room for emulator to save to. rlm@0: We simply overwrite the emulator data in the old SPC file rather rlm@0: than creating new SPC data. This preserves the text tags from rlm@0: the old file. */ rlm@0: if ( spc_size < spc_file_size ) rlm@0: { rlm@0: spc_size = spc_file_size; rlm@0: spc = realloc( spc, spc_size ); /* leaks memory if allocation fails */ rlm@0: if ( !spc ) error( "Out of memory" ); rlm@0: } rlm@0: rlm@0: /* Keep saving SPC, then playing a little more. Once SPC becomes non-silent, rlm@0: write the SPC data saved just before this. */ rlm@0: { rlm@0: long samples_trimmed = 0; rlm@0: while ( 1 ) rlm@0: { rlm@0: #define BUF_SIZE 1024 rlm@0: short buf [BUF_SIZE]; rlm@0: rlm@0: if ( samples_trimmed > 10 * spc_sample_rate * 2 ) rlm@0: error( "Excess silence found" ); rlm@0: rlm@0: spc_clear_echo( snes_spc ); rlm@0: spc_save_spc( snes_spc, spc ); rlm@0: rlm@0: /* Fill buffer */ rlm@0: error( spc_play( snes_spc, BUF_SIZE, buf ) ); rlm@0: samples_trimmed += BUF_SIZE; rlm@0: rlm@0: /* See if SPC became non-silent */ rlm@0: if ( use_kon_check ? spc_check_kon( snes_spc ) : !is_silent( buf, BUF_SIZE ) ) rlm@0: break; rlm@0: } rlm@0: rlm@0: printf( "Trimmed %.1f seconds\n", (double) samples_trimmed / spc_sample_rate / 2 ); rlm@0: } rlm@0: rlm@0: spc_delete( snes_spc ); rlm@0: write_file( (argc > 2) ? argv [2] : "trimmed.spc", spc, spc_size ); rlm@0: rlm@0: return 0; rlm@0: } rlm@0: rlm@0: int is_silent( short const* in, int count ) rlm@0: { rlm@0: unsigned const threshold = 0x10; rlm@0: while ( count-- ) rlm@0: { rlm@0: if ( (unsigned) (*in++ + threshold / 2) > threshold ) rlm@0: return 0; rlm@0: } rlm@0: return 1; rlm@0: }