#include #include #include #include // Simplified frame length calculation (MPEG1 Layer3 only) uint32_t calc_frame_len(uint32_t header) { const int bitrates[] = {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320}; const int samplerates[] = {44100, 48000, 32000}; int br_idx = (header >> 12) & 0xF; int sr_idx = (header >> 10) & 0x3; int padding = (header >> 9) & 0x1; int bitrate = bitrates[br_idx] * 1000; int samplerate = samplerates[sr_idx]; return 144 * bitrate / samplerate + padding; } int main(int argc, char** argv) { if(argc != 2) return fprintf(stderr, "Usage: %s \n", argv[0]), 1; FILE* fin = fopen(argv[1], "rb"); if(!fin) return perror("fopen"), 1; FILE* fout = NULL; long file_count = 0; uint32_t pos = 0; uint32_t header; uint8_t buf[4]; while(fread(buf, 1, 4, fin) == 4) { header = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; // Check for valid MP3 header: 0xFF 0xE? (sync + version) if(buf[0] == 0xFF && (buf[1] & 0xE0) == 0xE0) { uint32_t frame_len = calc_frame_len(header >> 8); if(frame_len > 0 && frame_len < (10*1024*1024)) { // Sanity check if(!fout) { char fname[128]; snprintf(fname, sizeof(fname), "output_%ld.mp3", file_count++); fout = fopen(fname, "wb"); if(!fout) { perror("fopen output"); break; } printf("Extracting %s\n", fname); } // Save header fwrite(buf, 1, 4, fout); // Save frame data for(uint32_t i = 4; i < frame_len; i++) { int c = fgetc(fin); if(c == EOF) break; fputc(c, fout); } pos = ftell(fin); continue; } } if(fout) { fclose(fout); fout = NULL; } // Rewind 3 bytes to allow overlapping frames fseek(fin, ++pos, SEEK_SET); } if(fout) fclose(fout); fclose(fin); return 0; }