// $Id: cropsong.cc 6 2006-03-13 02:00:20Z flaterco $ // // Adaptively crop silence from beginning and end of songs, replacing // the original files. // // g++ -O2 -Wall -s -o cropsong cropsong.cc #include #include #include #include #include #include #include // Return length in seconds. double lengthofwav (char *fname) { struct stat s; assert (stat (fname, &s) == 0); assert (s.st_size > 44); // wav files from sox and normalize have 44 bytes of header. // 1 second = 44100 samples * 2 channels * 16 bits = 176400 bytes. return (double)(s.st_size - 44) / 176400.0; } // Adaptively trim silence from start and end of song. Some songs // have silent bits in the middle, so they require a longer interval // for detecting the end. // Toofar: if change in length exceeds toofar seconds, then you have // screwed up. #define toofar 20 void trim (char *from) { char cmd[1000]; double interval=0.1, tolen=0.0; double fromlen = lengthofwav(from); printf ("Cropping %s\n %02lu:%05.2f orig length\n", from, (unsigned long)(fromlen/60), fmod(fromlen,60.0)); do { printf (" Trimming with interval %3.1f\n", interval); sprintf (cmd, "sox %s delme.wav silence 1 0:0:0.01 -50d 1 0:0:%3.1f -60d", from, interval); system (cmd); tolen = lengthofwav("delme.wav"); printf (" %02lu:%05.2f trimmed length", (unsigned long)(tolen/60), fmod(tolen,60.0)); if (tolen < fromlen - toofar) { printf (" -- OOPS"); interval *= 2; } printf ("\n"); } while (tolen < fromlen - toofar); if (rename ("delme.wav", from)) { perror ("delme.wav"); exit (-1); } } int main (int argc, char **argv) { if (argc < 2) { fprintf (stderr, "Usage: cropsong song song...\n"); fprintf (stderr, "Original files are replaced.\n"); } for (int i=1; i