In article by Cem Alacayir:
> Hi!
> Does anyone have an idea how to split the mp3 in to parts?
> But I don't mean I want to have new mp3 files
> I only need the parts.
> For example, if I split a mp3 into 3 parts , the parts should be continuos ,
> I mean I should
> be able to play the parts in sequence (with a special player) and get the
> same result as playing the whole original mp3
> how is it possible? I need your help
> thanx
As Mark says, if you use the --nores option in LAME, you can cut an mp3
file into pieces on frame boundaries. I've attached below my C code which
does this.
Cheers,
Warren
/* mpcut: a really dirty hack to save a selected # of frames from one
* MP3 stream to another. Everything but main() comes from
* mp3asm-0.01 by Oliver Fromme <[EMAIL PROTECTED]>
*
* main() written by Warren Toomey, [EMAIL PROTECTED]
*/
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
extern int errno;
FILE *zin, *zout; /* Input & output files */
int framenum = 0; /* Current framenumber */
int verbose=0; /* Used for debugging purposes */
char *me = NULL; /* Name of running process */
char *Framebuf = NULL;
int Framebuflen = 0; /* Buffer for frame and its length in bytes */
u_int8_t bbuf[4]; /* Frame header as read in, not rearranged */
/*
* This constant array is optimized for fast access by the
* get_framedata() function which is called by the mp32var
* module for every single frame. It is not quite optimized
* for access by the get_frameinfo() function, but that is
* usually only called once per MPEG stream.
*
* 1st index: 0 = "MPEG 1.0", 1 = "MPEG 2.0"
* 2nd index: 0 unused, 1 = "Layer 3", 2 = "Layer 2", 3 = "Layer 1"
* 3rd index: bitrate index from frame header
*/
static const int kbpstab[2][4][16] =
{{
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320},
{0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384},
{0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448}
},
{
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160},
{0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160},
{0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256}
}};
static const unsigned freqtab[7] =
{44100, 48000, 32000, 22050, 24000, 16000, 11025};
/* Return 1 if the frame header is valid, 0 if invalid */
int valid_framehead(u_int32_t head)
{
if ((head & 0xffe00000) != 0xffe00000 ||
(head & 0x0c00) == 0x0c00 ||
!(head & 0x060000)) {
return (0);
} else
return (1);
}
/* Read the frame header from the stream. On failure, read on
* at most maxtries bytes in order to find a valid header
*/
u_int32_t read_head(u_int32_t maxtries)
{
u_int32_t head;
u_int32_t try;
switch (fread(bbuf, 1, 4, zin)) {
case 4: break;
case 0: return (0); /* EOF */
default: printf("%s: error reading frame header: %s\n",
me, strerror(errno));
return (0);
}
head = (u_int32_t) bbuf[0] << 24
| (u_int32_t) bbuf[1] << 16
| (u_int32_t) bbuf[2] << 8
| (u_int32_t) bbuf[3];
try = 0;
while (!valid_framehead(head)) {
try++;
if (maxtries--) {
switch (fread(bbuf, 1, 1, zin)) {
case 1: break;
case 0: return (0); /* EOF */
default: printf("%s: error reading frame header.\n", me);
return (0);
}
head = (head & 0xffffff) << 8 | bbuf[0];
} else {
printf("%s: can't find valid MPEG audio header\n", me);
errno = 0;
return (0);
}
}
if (try) printf("%s: skipped %d bad bytes.\n", me, try);
return (head);
}
/* Given the frame header, calculate the bytes per frame, and the
* bytes per side info, and return these in the int pointers.
* Return 1 if ok, or 0 if the frame is not recognised.
*/
int get_framedata(u_int32_t head, int *isize, int *dsize)
{
int freq; /* sample rate */
int laymi; /* 4 - audio layer */
int kbps; /* bit rate */
int l3spf; /* samples per frame for Layer 3 */
int bpf; /* bytes per frame */
int bpsi; /* bytes per side info */
switch (head & 0x00180000) {
case 0x00180000: /* MPEG 1.0 */
freq = freqtab[0x03 & head >> 10];
kbps = kbpstab[0][laymi = 0x03 & head >> 17][0x0f & head >> 12];
l3spf = 1152;
bpsi = ((head & 0x00c0) == 0x00c0) ? 17 : 32;
break;
case 0x00100000: /* MPEG 2.0 */
freq = freqtab[3 + (0x03 & head >> 10)];
kbps = kbpstab[1][laymi = 0x03 & head >> 17][0x0f & head >> 12];
l3spf = 576;
bpsi = ((head & 0x00c0) == 0x00c0) ? 9 : 17;
break;
default: /* "MPEG 2.5" */
freq = freqtab[6];
kbps = kbpstab[1][laymi = 0x03 & head >> 17][0x0f & head >> 12];
l3spf = 576;
bpsi = ((head & 0x00c0) == 0x00c0) ? 9 : 17;
}
switch (laymi) {
case 1: /* Layer 3 */
bpf = (kbps * 125 * l3spf) / freq;
if (head & 0x0200) bpf++;
if (!(head & 0x10000)) bpsi += 2;
break;
case 2: /* Layer 2 */
bpf = (kbps * 125 * 1152) / freq;
if (head & 0x0200) bpf++;
bpsi = 0;
break;
case 3: /* Layer 1 */
bpf = (kbps * 125 * 384) / (freq << 2) << 2;
if (head & 0x0200) bpf += 4;
bpsi = 0;
break;
default:
return (0);
}
*isize = bpsi;
*dsize = bpf - bpsi - 4;
if (verbose) {
printf("Frame %d:\n", framenum);
printf("\t sample rate %d\n", freq);
printf("\t 4 - audio layer %d\n", laymi);
printf("\t bit rate %d\n", kbps);
printf("\t samples per frame for Layer III %d\n", l3spf);
printf("\t bytes per frame %d\n", bpf);
printf("\t bytes per side info %d\n", bpsi);
}
return (1);
}
int main(int argc, char *argv[])
{
u_int32_t head;
int i, n, Numlist, Isize, Dsize, total, size;
int *startlist, *endlist;
me = argv[0];
verbose = 0;
/* Print usage message if not enough arguments */
if (argc < 5) {
printf("Usage: mpcut infile outfile start end [start end]\n"); exit(1);
}
/* Work out how many start/end list entries we need */
if ((argc & 1) == 0) {
printf("You have one too many start values at the end\n"); exit(1);
}
Numlist = (argc - 3) / 2;
startlist = (int *) malloc(Numlist * sizeof(int));
endlist = (int *) malloc(Numlist * sizeof(int));
if ((startlist == NULL) || (endlist == NULL)) {
printf("Malloc error\n"); exit(1);
}
/* Now read up through the arguments getting start and end values */
for (i = 0, n = 3; n < argc; n++, i++) {
startlist[i] = atoi(argv[n]); n++;
if ((i!=0) && (startlist[i]<=endlist[i-1])) {
printf("Start value %d smaller than end value %d\n",
startlist[i], endlist[i-1]); exit(1);
}
endlist[i] = atoi(argv[n]);
if (endlist[i]<=startlist[i]) {
printf("End value %d smaller than start value %d\n",
endlist[i], startlist[i]); exit(1);
}
}
/* Open up the input and output files */
zin = fopen(argv[1], "r");
if (zin == NULL) {
printf("Cannot open %s: %s\n", argv[1], strerror(errno)); exit(1);
}
zout = fopen(argv[2], "wb");
if (zout == NULL) {
printf("Cannot open %s: %s\n", argv[2], strerror(errno)); exit(1);
}
/* Loop over all the input frames */
for (framenum = 0, i = 0; i < Numlist; framenum++) {
head = read_head(300);
if (head == 0) break;
if (!valid_framehead(head)) break;
if (!get_framedata(head, &Isize, &Dsize)) break;
total = Isize + Dsize;
/* Allocate Framebuf as required */
if (Framebuflen < total) {
if (Framebuf != NULL) free(Framebuf);
Framebuf = (char *) malloc(total);
if (Framebuf == NULL) { printf("Malloc error\n"); exit(1); }
}
/* Read in the frame */
size = fread(Framebuf, 1, total, zin);
if (size == -1) { printf("Read error\n"); exit(1); }
if (size < total) break;
/* Write the frame if required */
if (framenum > endlist[i]) {
i++; if (verbose) printf("\n\n"); continue;
}
if (framenum >= startlist[i]) {
if (verbose) printf("%d ", framenum);
fwrite(&bbuf, 1, 4, zout);
fwrite(Framebuf, 1, total, zout);
}
}
if (verbose) printf("\n");
exit(0);
}
--
MP3 ENCODER mailing list ( http://geek.rcc.se/mp3encoder/ )