> Hi all,
>       I'm trying to use Oliver Fromme's mp3asm tool
> (http://dorifer.heim3.tu-clausthal.de/~olli/mpg123/mp3asm.html) to select
> portions of the mp3 streams produced by Lame. However, it's essentially useless
> because mp3asm can't cope with frame data actually being stored in
> multiple frames. mp3asm tries to insert an `empty' frame, but this doesn't
> seem to work.
> 
> What's a good solution to this problem? The mp3 streams I'm editing are
> just lectures, so I could live with a slight loss of quality. Can I
> disable the bit reservoir in Lame to keep frame data within one frame?
> 
> Alternatively, how difficult would it be to extract the `extra' data
> from a previous frame. For example, suppose I want to extract frames
> 100 to 800 from an mp3 stream. However, some of frame 100's data occurs
> earlier. Can I easily construct and insert a frame before frame 100,
> so that the new mp3 file contains one new frame, then frames 100 to 800?

I've been doing similar things, - I've got a bit of code that lets me grab a nun=mber 
of frames from within a stream. 

So all I've been doing is recording half a second of silence as mp3 in the same 
format, then using this tool to append the section of auiod I'm interested in.
That seems to work fine for me.

If you're bored enough you can even find the syncwords manually and calculate your 
offsets.


Anyway - I would *love* to make my extraction code grab automatically padd the intro 
with the correct frame data. In fact I'd really like to do a frame level mp3 editor.


I'm appending the code BTW...
#include "stdlib.h"
#include "stdio.h"


#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <dirent.h>


#define MPG_MD_MONO 3

typedef struct mp3_headerSt {
        int lay;
        int version;
        int error_protection;
        int bitrate_index;
        int sampling_frequency;
        int padding;
        int extension;
        int mode;
        int mode_ext;
        int copyright;
        int original;
        int emphasis;
        int stereo;
        int framesize;
} mp3_header_t;

unsigned int bitrates[3][3][15] =
{
  {
    {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448},
    {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384},
    {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320}
  },
  {
    {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256},
    {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},
    {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}
  }
};

unsigned int s_freq[3][4] =
{
    {44100, 48000, 32000, 0},
    {22050, 24000, 16000, 0},
    {11025, 8000, 8000, 0}
};

char *mode_names[5] = {"stereo", "j-stereo", "dual-ch", "single-ch", 
                        "multi-ch"};
char *layer_names[3] = {"I", "II", "III"};
char *version_names[3] = {"MPEG-1", "MPEG-2 LSF", "MPEG-2.5"};
char *version_nums[3] = {"1", "2", "2.5"};


int head_check(unsigned long head)
{
        if ((head & 0xffe00000) != 0xffe00000)
                return 0;
        if (!((head >> 17) & 3))
                return 0;
        if (((head >> 12) & 0xf) == 0xf)
                return 0;
        if (!((head >> 12) & 0xf))
                return 0;
        if (((head >> 10) & 0x3) == 0x3)
                return 0;
        if (((head >> 19) & 1) == 1 && ((head >> 17) & 3) == 3 && ((head >> 16) & 1) 
== 1)
                return 0;
        if ((head & 0xffff0000) == 0xfffe0000)
                return 0;
        
        return 1;
}


/* This is needed to give us the format output from the decoders */
int mp3info (unsigned char *buff,long readsize)
{
        size_t temp;
        unsigned char *buffer;
        mp3_header_t mh;
        unsigned long my_head;
        buffer = buff - 1;
        
        do {
                buffer++;
                my_head=((unsigned long) buffer[0] << 24) |
                        ((unsigned long) buffer[1] << 16) |
                        ((unsigned long) buffer[2] << 8) |
                        (unsigned long) buffer[3];      
        } while (!head_check(my_head) && ((size_t)(buffer - buff) < readsize));
        if((buffer-buff)==readsize){
                return readsize;
        }
        /*fprintf(stderr,"offset = %d\n",buffer-buff);*/
        else {
                switch ((buffer[1] >> 3 & 0x3)){
                case 3:
                        mh.version = 0;
                        break;
                case 2:
                        mh.version = 1;
                        break;
                case 0:
                        mh.version = 2;
                default:
                        return -1;
                }
                
                mh.lay = 4 - ((buffer[1] >> 1) & 0x3);
                mh.error_protection = !(buffer[1] & 0x1);
                mh.bitrate_index = (buffer[2] >> 4) & 0x0F;
                mh.sampling_frequency = (buffer[2] >> 2) & 0x3;
                mh.padding = (buffer[2] >> 1) & 0x01;
                mh.extension = buffer[2] & 0x01;
                mh.mode = (buffer[3] >> 6) & 0x3;
                mh.mode_ext = (buffer[3] >> 4) & 0x03;
                mh.copyright = (buffer[3] >> 3) & 0x01;
                mh.original = (buffer[3] >> 2) & 0x1;
                mh.emphasis = (buffer[3]) & 0x3;
                mh.stereo = (mh.mode == MPG_MD_MONO) ? 1 : 2;
                
                fprintf (stderr, "Layer: %s\t\tVersion: %s\tFrequency: %d\n",
                         layer_names[mh.lay - 1], version_names[mh.version],
                         s_freq[mh.version][mh.sampling_frequency]);
                fprintf (stderr, "Bitrate: %d kbit/s\tPadding: %d\tMode: %s\n",
                         bitrates[mh.version][mh.lay - 1][mh.bitrate_index],
                         mh.padding, mode_names[mh.mode]);
                fprintf (stderr, "Ext: %d\tMode_Ext: %d\tCopyright: %d\tOriginal: 
%d\n",mh.extension, mh.mode_ext, mh.copyright, mh.original);
                fprintf (stderr, "Error Protection: %d\tEmphasis: %d\tStereo: 
%d\n",mh.error_protection, mh.emphasis, mh.stereo);
                
                switch(mh.lay){
                case 1:
                        mh.framesize = (long) 
bitrates[mh.version][0][mh.bitrate_index] * 12000 * 4.0;
                        mh.framesize /= s_freq[mh.version][mh.sampling_frequency];
                        if(mh.version) mh.framesize *=2;
                        mh.framesize += mh.padding;
                        break;
                case 2:
                case 3:
                        mh.framesize = bitrates[mh.version][mh.lay - 
1][mh.bitrate_index] * 144000;
                        mh.framesize /= s_freq[mh.version][mh.sampling_frequency];
                        if(mh.version) mh.framesize *=2;
                        mh.framesize+=mh.padding;
                }
                return mh.framesize;
        }
        return readsize;
}

int analyse_mp3(char *filename){
        int fd;
        unsigned char buff[1024];
        unsigned char *data;
        unsigned char *ptr;
        int frames;
        long len;
        struct stat buf;
        long off;
        
        stat(filename,&buf);
        len= buf.st_size;
        fd=open(filename,O_RDONLY);
        if((data = mmap(0,len,PROT_READ,MAP_SHARED,fd,0))==(void*)-1){
                close(fd);
                return 0;
        }
        frames=0;
        ptr=data;
        while((ptr-data)<=(len -1 )){
                off= mp3info(ptr,len-(ptr-data));
                fprintf(stderr,"frame %d size %d  
%d\n",frames,ptr-data,len-(ptr-data));
                ptr+=off;
                frames++;
        }
        munmap(data,len);
        close(fd);
}  

int extract_fragment(char *filename,int start,int end){
        int fd;
        unsigned char buff[1024];
        unsigned char *data;
        unsigned char *ptr;
        int frames;
        long len;
        struct stat buf;
        long off;
        
        stat(filename,&buf);
        len= buf.st_size;
        fd=open(filename,O_RDONLY);
        if((data = mmap(0,len,PROT_READ,MAP_SHARED,fd,0))==(void*)-1){
                close(fd);
                return 0;
        }
        frames=0;
        ptr=data;
        while(((ptr-data)<(len -128))&&(frames<=end)){
                off= mp3info(ptr,1024);
                fprintf(stderr,"frame %d size %d  
%d\n",frames,ptr-data,len-(ptr-data));
                if((frames>=start) &&(frames<=end)){
                        fwrite(ptr,1,off,stdout);
                }
                ptr+=off;
                frames++;
        }
        munmap(data,len);
        close(fd);
}  





int main(int argc,char *argv[]){

        if(argc==2){
                analyse_mp3(argv[1]);
        }

        if(argc>=4){
                extract_fragment(argv[1],atoi(argv[2]),atoi(argv[3]));
        } else {
                fprintf(stderr,"oops, lacking command line args\n");
        }
}





Reply via email to