This document will describe what are the basis parts that programmer needs in order to rip audio , join or cut an Audio File if it is MPEG1 layer 1 , or 3 - also knows as MP3.
We also will show how to rip Wave file.
To rip audio is to mark points from A-B. The points are given mostly using time.
A: 0:1:6:72 where
0 – hours
1 – minutes
6 - seconds
72 – milliseconds.
The audio frame is not longer than tens of milliseconds, that’s why you can be accurate at the frame based.
We will start with MPX. The most popular audio format in the planet today is the MP3.
When we have big mp3 audio file and we want to edit it we can search the internet for a software.
There are software that in order to edit mp3 files (rip join or cut) will need to convert the MP3 file into Wave file , edit and than compress it again. This operation reduce the quality of the file. (There program that does not) and here we about to explain how they do it.
The Header of MPx file:
MPx file sync start with FFF , 12 bits of ‘1’. In order to check when the frame started you need to open a file and search for that sync.If you find it, it does not means that you find the sync word , it does mean that you can check that the rest of the header is valid.
If the rest of the header is valid , you can collect information about the frame and determine what are the A and B points for your input.
This is the header of the MPx file format. You see it in the C version that also show the numbers of bits for every field.
hdr.version = getbits(1);
hdr.lay = 4-getbits(2);
hdr.error_protection = !getbits(1);
hdr.bitrate_index = getbits(4);
hdr.sampling_frequency = getbits(2);
hdr.padding = getbits(1);
hdr.extension = getbits(1);
hdr.mode = getbits(2);
hdr.mode_ext = getbits(2);
hdr.copyright = getbits(1);
hdr.original = getbits(1);
hdr.emphasis = getbits(2);
Analyzing the frame header:
Getting the layer:
In the spec of the MPEG audio you can find that detecting the layer (1,2 or 3) is done using the following formula:
lay = hdr.lay – 1
if (lay ) is not 1 , 2 or 3 , than the sync you have find (0xFFF) is not the start sync of a frame and you need search for another sync.
Getting the bitrate:
The information in the header are index to a table and does contains the real Information (save place)
The bitrate will receive from a table:
Using the header version , layer and the bitrate_index.
c_bitrate = bitrate[hdr.version][lay][hdr.bitrate_index]
Getting the same frequncy:
The sample frequency will received this table.
frequency = s_freq[hdr.version][hdr.sampling_frequency] ;
Getting the audio offset:
Audio offset is the audio frame size. This data tells you the size In bytes of every audio frame.
For example you can know the number of audio frame by:
number_of_frames = FileSize / audio_offset
If the audio file was compress in CBR (constant bit rate) than the audio frame size will be the same all over the file. That means that the checking of the header can be done only one and you can be sure that all the frame are with the same properties.
In case the audio was compress in VBR, it means that you need to check every sync and every header.
This is the formula to calculate the audio frame size:
audio_offset = 144 * c_bitrate * 1000 / (frequency * 1000);
Now we need to know what the length of the frame in milliseconds:
audio_sample_time = 1152 / frequency
When we have the number of frames in the audio file and the frame sample time we can calculate the time of the total file:
total_time = audio_sample_time * number_of_frames
Calculating the A and B points:
The given A and B points will be give probably from an application with the format that we show (HH:MM:SS:MS)
We need to calculate the offset in bytes of point A , seek to this point and mark it as point A to our ripper:
First we calculate the number of frames to our A point:
__int64 ns0 = start_point / audio_sample_time;
And than using the audio frame size we can determine our objective:
The offset in file(in bytes)
__int64 offset_in_file = ns0 * audio_offset;
Now you can seek to this point (open the file and do fseek) or we suggest to read all the file int a memory using allocating big buffer(malloc). This is faster.
At the same manner you can find you B point in the file and than start thinking about your tasks:
- Rip means that you want to save the data only from point A into point B
- Join means that you want to insert another file from position A than glue the entire file.
- Cut means that you have the A position as your ending postion.
<A name=layer>typedef </A>