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/ )

Reply via email to