1 /*
2  *  tcmp3cut.c
3  *
4  *  Copyright (C) Thomas Oestreich - June 2001
5  *
6  *  This file is part of transcode, a video stream processing tool
7  *
8  *  transcode is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2, or (at your option)
11  *  any later version.
12  *
13  *  transcode is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with GNU Make; see the file COPYING.  If not, write to
20  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21  *
22  */
23 
24 #include "transcode.h"
25 #include "framebuffer.h"
26 #include "aud_scan.h"
27 
28 #include <sys/errno.h>
29 
30 
31 #define EXE "tcmp3cut"
32 
33 int verbose=TC_QUIET;
34 
35 #define CHUNK_SIZE 4096
36 
37 static int min=0, max=0;
38 
39 
40 
41 /* ------------------------------------------------------------
42  *
43  * print a usage/version message
44  *
45  * ------------------------------------------------------------*/
46 
version(void)47 void version(void)
48 {
49     printf("%s (%s v%s) (C) 2003 Tilmann Bitterberg\n", EXE, PACKAGE, VERSION);
50 }
51 
usage(int status)52 static void usage(int status)
53 {
54   version();
55 
56   fprintf(stderr,"\nUsage: %s [options]\n", EXE);
57 
58   fprintf(stderr,"    -i file           input file name\n");
59   fprintf(stderr,"    -o base           output file name base\n");
60   fprintf(stderr,"    -e r[,b[,c]]      MP3 audio stream parameter [%d,%d,%d]\n", RATE, BITS, CHANNELS);
61   fprintf(stderr,"    -t c1[,c2[,.]]    cut points in milliseconds\n");
62   fprintf(stderr,"    -d mode           verbosity mode\n");
63   fprintf(stderr,"    -v                print version\n");
64 
65   exit(status);
66 
67 }
68 
69 
70 /* ------------------------------------------------------------
71  *
72  * scan stream
73  *
74  * ------------------------------------------------------------*/
75 
76 #define MAX_SONGS 50
77 
main(int argc,char * argv[])78 int main(int argc, char *argv[])
79 {
80 
81 
82   int fd=-1;
83   FILE *out=NULL;
84 
85   int n=0, ch;
86   char *name=NULL, *offset=NULL, *base=NULL;
87   char outfile[1024];
88   int cursong=0;
89 
90   int bytes_read;
91 
92   uint64_t total=0;
93 
94   int a_rate=RATE, a_bits=BITS, chan=CHANNELS;
95   int songs[MAX_SONGS];
96   int numsongs=0;
97 
98   int on=1;
99 
100   char buffer[CHUNK_SIZE];
101 
102   uint32_t i=0;
103 
104   if (argc<2)
105       usage(EXIT_SUCCESS);
106 
107   while ((ch = getopt(argc, argv, "o:e:i:t:d:v?h")) != -1) {
108 
109     switch (ch) {
110     case 'd':
111 
112       if(optarg[0]=='-') usage(EXIT_FAILURE);
113       verbose = atoi(optarg);
114 
115       break;
116 
117     case 'e':
118 
119       if(optarg[0]=='-') usage(EXIT_FAILURE);
120 
121       if (3 != sscanf(optarg,"%d,%d,%d", &a_rate, &a_bits, &chan)) fprintf(stderr, "invalid pcm parameter set for option -e");
122 
123       if(a_rate > RATE || a_rate <= 0) {
124 	fprintf(stderr, "invalid pcm parameter 'rate' for option -e");
125 	usage(EXIT_FAILURE);
126       }
127 
128       if(!(a_bits == 16 || a_bits == 8)) {
129 	fprintf(stderr, "invalid pcm parameter 'bits' for option -e");
130 	usage(EXIT_FAILURE);
131       }
132 
133       if(!(chan == 0 || chan == 1 || chan == 2)) {
134 	fprintf(stderr, "invalid pcm parameter 'channels' for option -e");
135 	usage(EXIT_FAILURE);
136       }
137 
138       break;
139 
140     case 'i':
141 
142       if(optarg[0]=='-') usage(EXIT_FAILURE);
143       name = optarg;
144       break;
145 
146     case 't':
147       if(optarg[0]=='-') usage(EXIT_FAILURE);
148 
149       offset = optarg;
150       i=0;
151       songs[i]=atoi(offset);
152       while ((offset = strchr(offset,','))) {
153 	  offset++;
154 	  i++;
155 	  songs[i]=atoi(offset);
156       }
157       numsongs=i+1;
158       break;
159 
160     case 'o':
161       if(optarg[0]=='-') usage(EXIT_FAILURE);
162       base = optarg;
163       break;
164     case 'v':
165       version();
166       exit(0);
167       break;
168 
169     case 'h':
170       usage(EXIT_SUCCESS);
171     default:
172       usage(EXIT_FAILURE);
173     }
174   }
175 
176   printf("Got %d songs:\n", numsongs);
177   for (n=0; n<numsongs; n++)
178       printf("%d : %d\n", n, songs[n]);
179 
180 
181   if (!name) {
182       fprintf(stderr, "No filename given\n");
183       exit (EXIT_FAILURE);
184   }
185 
186   if ( (fd = open(name, O_RDONLY)) < 0) {
187       perror("open()");
188       return -1;
189   }
190 
191   if ( (fd = open(name, O_RDONLY)) < 0) {
192       perror("open()");
193       return -1;
194   }
195 
196   tc_snprintf(outfile, sizeof(outfile), "%s-%04d.mp3", base, cursong);
197   if ( (out = fopen(outfile, "w")) == NULL) {
198       perror ("fopen() output");
199       return -1;
200   }
201 
202   if(1) {
203 
204       uint8_t header[4];
205       int framesize = 0;
206       int chunks = 0;
207       int srate=0 , chans=0, bitrate=0;
208       off_t pos=0;
209       double ms = 0;
210 
211       min = 500;
212       max = 0;
213 
214       pos = lseek(fd, 0, SEEK_CUR);
215       // find mp3 header
216       while ((total += read(fd, header, 4))) {
217 	  if ( (framesize = tc_get_mp3_header (header, &chans, &srate, &bitrate)) > 0) {
218 	      fwrite (header, 4, 1,out);
219 	      ms += (framesize*8)/(bitrate);
220 	      break;
221 	  }
222 	  pos++;
223 	  lseek(fd, pos, SEEK_SET);
224       }
225       printf("POS %lld\n", (long long)pos);
226 
227       // Example for _1_ mp3 chunk
228       //
229       // fps       = 25
230       // framesize = 480 bytes
231       // bitrate   = 160 kbit/s == 20 kbytes/s == 20480 bytes/s == 819.20 bytes / frame
232       //
233       // 480 bytes = 480/20480 s/bytes = .0234 s = 23.4 ms
234       //
235       //  ms = (framesize*1000*8)/(bitrate*1000);
236       //                           why 1000 and not 1024?
237       //  correct? yes! verified with "cat file.mp3|mpg123 -w /dev/null -v -" -- tibit
238 
239       while (on) {
240 	  if ( (bytes_read = read(fd, buffer, framesize-4)) != framesize-4) {
241 	      on = 0;
242 	  } else {
243 	      total += bytes_read;
244 	      fwrite (buffer, bytes_read, 1,out);
245 	      while ((total += read(fd, header, 4))) {
246 
247 		  //printf("%x %x %x %x\n", header[0]&0xff, header[1]&0xff, header[2]&0xff, header[3]&0xff);
248 
249 		  if ( (framesize = tc_get_mp3_header (header, &chans, &srate, &bitrate)) < 0) {
250 		      fprintf(stderr, "[%s] corrupt mp3 file?\n", EXE);
251 		      on = 0;
252 		      break;
253 		  } else  {
254 
255 		      /*
256 		      printf("Found new header (%d) (framesize = %d) chan(%d) srate(%d) bitrate(%d)\n",
257 			  chunks, framesize, chans, srate, bitrate);
258 			  */
259 
260 		      ms += (framesize*8)/(bitrate);
261 		      // close/open
262 
263 		      if (ms>=songs[cursong]) {
264 			  fclose(out);
265 			  cursong++;
266 			  if (cursong>numsongs)
267 			      break;
268 			  tc_snprintf(outfile, sizeof(outfile), "%s-%04d.mp3", base, cursong);
269 			  if ( (out = fopen(outfile, "w")) == NULL) {
270 			      perror ("fopen() output");
271 			      return -1;
272 			  }
273 		      }
274 		      fwrite (header, 4, 1,out);
275 
276 		      ++chunks;
277 		      break;
278 		  }
279 	      }
280 
281 
282 	  }
283       }
284       fclose(out);
285       close(fd);
286       return(0);
287   }
288 
289 
290   fprintf(stderr, "[%s] unable to handle codec/filetype\n", EXE);
291 
292   exit(1);
293 
294 }
295 
296 /*************************************************************************/
297 
298 /*
299  * Local variables:
300  *   c-file-style: "stroustrup"
301  *   c-file-offsets: ((case-label . *) (statement-case-intro . *))
302  *   indent-tabs-mode: nil
303  * End:
304  *
305  * vim: expandtab shiftwidth=4:
306  */
307