/* * tcmp3cut.c * * Copyright (C) Thomas Oestreich - June 2001 * * This file is part of transcode, a video stream processing tool * * transcode is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * transcode is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU Make; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include "transcode.h" #include "framebuffer.h" #include "aud_scan.h" #include #define EXE "tcmp3cut" int verbose=TC_QUIET; #define CHUNK_SIZE 4096 static int min=0, max=0; /* ------------------------------------------------------------ * * print a usage/version message * * ------------------------------------------------------------*/ void version(void) { printf("%s (%s v%s) (C) 2003 Tilmann Bitterberg\n", EXE, PACKAGE, VERSION); } static void usage(int status) { version(); fprintf(stderr,"\nUsage: %s [options]\n", EXE); fprintf(stderr," -i file input file name\n"); fprintf(stderr," -o base output file name base\n"); fprintf(stderr," -e r[,b[,c]] MP3 audio stream parameter [%d,%d,%d]\n", RATE, BITS, CHANNELS); fprintf(stderr," -t c1[,c2[,.]] cut points in milliseconds\n"); fprintf(stderr," -d mode verbosity mode\n"); fprintf(stderr," -v print version\n"); exit(status); } /* ------------------------------------------------------------ * * scan stream * * ------------------------------------------------------------*/ #define MAX_SONGS 50 int main(int argc, char *argv[]) { int fd=-1; FILE *out=NULL; int n=0, ch; char *name=NULL, *offset=NULL, *base=NULL; char outfile[1024]; int cursong=0; int bytes_read; uint64_t total=0; int a_rate=RATE, a_bits=BITS, chan=CHANNELS; int songs[MAX_SONGS]; int numsongs=0; int on=1; char buffer[CHUNK_SIZE]; uint32_t i=0; if (argc<2) usage(EXIT_SUCCESS); while ((ch = getopt(argc, argv, "o:e:i:t:d:v?h")) != -1) { switch (ch) { case 'd': if(optarg[0]=='-') usage(EXIT_FAILURE); verbose = atoi(optarg); break; case 'e': if(optarg[0]=='-') usage(EXIT_FAILURE); if (3 != sscanf(optarg,"%d,%d,%d", &a_rate, &a_bits, &chan)) fprintf(stderr, "invalid pcm parameter set for option -e"); if(a_rate > RATE || a_rate <= 0) { fprintf(stderr, "invalid pcm parameter 'rate' for option -e"); usage(EXIT_FAILURE); } if(!(a_bits == 16 || a_bits == 8)) { fprintf(stderr, "invalid pcm parameter 'bits' for option -e"); usage(EXIT_FAILURE); } if(!(chan == 0 || chan == 1 || chan == 2)) { fprintf(stderr, "invalid pcm parameter 'channels' for option -e"); usage(EXIT_FAILURE); } break; case 'i': if(optarg[0]=='-') usage(EXIT_FAILURE); name = optarg; break; case 't': if(optarg[0]=='-') usage(EXIT_FAILURE); offset = optarg; i=0; songs[i]=atoi(offset); while ((offset = strchr(offset,','))) { offset++; i++; songs[i]=atoi(offset); } numsongs=i+1; break; case 'o': if(optarg[0]=='-') usage(EXIT_FAILURE); base = optarg; break; case 'v': version(); exit(0); break; case 'h': usage(EXIT_SUCCESS); default: usage(EXIT_FAILURE); } } printf("Got %d songs:\n", numsongs); for (n=0; n 0) { fwrite (header, 4, 1,out); ms += (framesize*8)/(bitrate); break; } pos++; lseek(fd, pos, SEEK_SET); } printf("POS %lld\n", (long long)pos); // Example for _1_ mp3 chunk // // fps = 25 // framesize = 480 bytes // bitrate = 160 kbit/s == 20 kbytes/s == 20480 bytes/s == 819.20 bytes / frame // // 480 bytes = 480/20480 s/bytes = .0234 s = 23.4 ms // // ms = (framesize*1000*8)/(bitrate*1000); // why 1000 and not 1024? // correct? yes! verified with "cat file.mp3|mpg123 -w /dev/null -v -" -- tibit while (on) { if ( (bytes_read = read(fd, buffer, framesize-4)) != framesize-4) { on = 0; } else { total += bytes_read; fwrite (buffer, bytes_read, 1,out); while ((total += read(fd, header, 4))) { //printf("%x %x %x %x\n", header[0]&0xff, header[1]&0xff, header[2]&0xff, header[3]&0xff); if ( (framesize = tc_get_mp3_header (header, &chans, &srate, &bitrate)) < 0) { fprintf(stderr, "[%s] corrupt mp3 file?\n", EXE); on = 0; break; } else { /* printf("Found new header (%d) (framesize = %d) chan(%d) srate(%d) bitrate(%d)\n", chunks, framesize, chans, srate, bitrate); */ ms += (framesize*8)/(bitrate); // close/open if (ms>=songs[cursong]) { fclose(out); cursong++; if (cursong>numsongs) break; tc_snprintf(outfile, sizeof(outfile), "%s-%04d.mp3", base, cursong); if ( (out = fopen(outfile, "w")) == NULL) { perror ("fopen() output"); return -1; } } fwrite (header, 4, 1,out); ++chunks; break; } } } } fclose(out); close(fd); return(0); } fprintf(stderr, "[%s] unable to handle codec/filetype\n", EXE); exit(1); } /*************************************************************************/ /* * Local variables: * c-file-style: "stroustrup" * c-file-offsets: ((case-label . *) (statement-case-intro . *)) * indent-tabs-mode: nil * End: * * vim: expandtab shiftwidth=4: */