organization
This commit is contained in:
parent
3989ed9779
commit
1f7a101e6c
11
README.md
11
README.md
|
@ -1,2 +1,13 @@
|
||||||
# MPEG-1 Layer III
|
# MPEG-1 Layer III
|
||||||
## the best audio format in fact
|
## the best audio format in fact
|
||||||
|
### (it is true)
|
||||||
|
|
||||||
|
# files
|
||||||
|
- dat.h: miscellaneous tables and constants needed by the library
|
||||||
|
- huffman.h: generated huffman table
|
||||||
|
- main.c: test application for the library
|
||||||
|
- mp3.c: library code
|
||||||
|
- mp3.h: library header, include this in client code
|
||||||
|
- scr: scripts unneeded to use the library, provided for reference purposes
|
||||||
|
+ huff: wrapper for huffcvt, generating huffman tables copied to the clipboard from the mp3 specification
|
||||||
|
+ scr/huffcvt.c: changes huffman string format to c array
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
uint16_t l3_bitrates[16] = {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0};
|
||||||
|
uint16_t l3_smprates[4] = {44100, 48000, 32000, 0};
|
||||||
|
|
||||||
|
// TODO possiblility block_type is undefined if blocksplit not set. read spec for blocksplit_flag and block_type
|
||||||
|
// table to get length of scalefactor bands
|
||||||
|
uint8_t sfcom[16][2] = {
|
||||||
|
{0,0},
|
||||||
|
{0,1},
|
||||||
|
{0,2},
|
||||||
|
{0,3},
|
||||||
|
{3,0},
|
||||||
|
{1,1},
|
||||||
|
{1,2},
|
||||||
|
{1,3},
|
||||||
|
{2,1},
|
||||||
|
{2,2},
|
||||||
|
{2,3},
|
||||||
|
{3,1},
|
||||||
|
{3,2},
|
||||||
|
{3,3},
|
||||||
|
{4,2},
|
||||||
|
{4,3},
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t sf[3][33] = {
|
||||||
|
{ // 32000hz band
|
||||||
|
4,4,4,4,4,4,6,6,8,10,12,16,20,24,30,38,46,56,68,84,102,
|
||||||
|
4,4,4,4,6,8,12,16,20,26,34,42
|
||||||
|
}, { // 44100hz band
|
||||||
|
4,4,4,4,4,4,6,6,8,8,10,12,16,20,24,28,34,42,50,54,76,
|
||||||
|
4,4,4,4,6,8,10,12,14,18,22,30
|
||||||
|
}, { // 48000hz band
|
||||||
|
4,4,4,4,4,4,6,6,6,8,10,12,16,18,22,28,34,40,46,54,54,
|
||||||
|
4,4,4,4,6,6,10,12,14,16,20,26
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t preemph[21] = {0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,2,2,3,3,3,2};
|
||||||
|
|
||||||
|
long double alias[8] = {
|
||||||
|
-.6,
|
||||||
|
-.535,
|
||||||
|
-.33,
|
||||||
|
-.185,
|
||||||
|
-.095,
|
||||||
|
-.041,
|
||||||
|
-.0142,
|
||||||
|
-.0037
|
||||||
|
};
|
||||||
|
|
||||||
|
// Huffman code table for quadruples (A)
|
||||||
|
// search by value
|
||||||
|
uint8_t hquada[16] = {
|
||||||
|
0b10000000,
|
||||||
|
0b01010000,
|
||||||
|
0b01000000,
|
||||||
|
0b00101000,
|
||||||
|
0b01100000,
|
||||||
|
0b00010100,
|
||||||
|
0b00100000,
|
||||||
|
0b00010000,
|
||||||
|
0b01110000,
|
||||||
|
0b00011000,
|
||||||
|
0b00110000,
|
||||||
|
0b00000000,
|
||||||
|
0b00111000,
|
||||||
|
0b00001000,
|
||||||
|
0b00001100,
|
||||||
|
0b00000100,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Huffman code table for quadruples (B)
|
||||||
|
// What The Hell
|
||||||
|
// search by index
|
||||||
|
uint8_t hquadb[16] = {
|
||||||
|
15,
|
||||||
|
14,
|
||||||
|
13,
|
||||||
|
12,
|
||||||
|
11,
|
||||||
|
10,
|
||||||
|
9,
|
||||||
|
8,
|
||||||
|
7,
|
||||||
|
6,
|
||||||
|
5,
|
||||||
|
4,
|
||||||
|
3,
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
// first ESC table is 16
|
||||||
|
char linbits[16] = {1, 2, 3, 4, 6, 8, 10, 13, 4, 5, 6, 7, 8, 9, 11, 13};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,146 @@
|
||||||
|
#include "mp3.h"
|
||||||
|
|
||||||
|
#include "huffman.h"
|
||||||
|
#include "dat.h"
|
||||||
|
|
||||||
|
// TODO autodetect endianness here
|
||||||
|
#define fromle(x) (x)
|
||||||
|
|
||||||
|
// get bit big endian
|
||||||
|
//#define bitb(x, y) ((((uint8_t*)(x))[(y) >> 3] >> (7 - ((y) & 7))) & 1)
|
||||||
|
|
||||||
|
uint8_t bitb(uint8_t* s, uint32_t b) {
|
||||||
|
return (s[b >> 3] >> (7 - (b & 7))) & 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define cast(x, y) (*((x*)&(y)))
|
||||||
|
|
||||||
|
#define cblimit 21
|
||||||
|
#define cblimit_short 12
|
||||||
|
|
||||||
|
uint32_t ibitrb(uint8_t* s, uint32_t* b, char e) { // bit range big endian
|
||||||
|
uint32_t a = 0;
|
||||||
|
for(int i = 0; i < e; i++) a = (a << 1) | bitb(s, (*b)+i);
|
||||||
|
//printf("bitrb %i at %i: 0x%X, 0d%u\n", e, *b, a, a);
|
||||||
|
*b += e;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t verify_l3(uint32_t d) { // returns 0 if header is valid
|
||||||
|
d = ntohl(d);
|
||||||
|
printf("magic %08X\n", d);
|
||||||
|
//return (d & 0xFFF00000) ^ 0xFFF00000;
|
||||||
|
return (d & 0xFFFE0000) ^ 0xFFFA0000;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void rdl3(uint32_t* s, mp3_frame* m) {
|
||||||
|
uint32_t d = ntohl(*(s++));
|
||||||
|
m->hdr = d;
|
||||||
|
m->prot = (d >> 16) & 1;
|
||||||
|
m->bitrate = l3_bitrates[(d >> 12) & 0xF];
|
||||||
|
m->smprate = l3_smprates[(d >> 10) & 3];
|
||||||
|
m->smpbit = (d >> 10) & 3;
|
||||||
|
m->len = 144000 * m->bitrate / m->smprate + ((d >> 9) & 1);
|
||||||
|
m->priv = (d >> 8) & 1;
|
||||||
|
m->mode = (d >> 6) & 3;
|
||||||
|
m->jmss = (d >> 5) & 1;
|
||||||
|
m->jint = (d >> 4) & 1;
|
||||||
|
m->emph = d & 3;
|
||||||
|
|
||||||
|
m->crc = htons(*((uint16_t*)s)); // only valid if m->crc
|
||||||
|
|
||||||
|
uint32_t bp = m->prot << 4; // bitpointer
|
||||||
|
|
||||||
|
uint16_t main_data_end = bitrb(s, &bp, 9);
|
||||||
|
char private_bits = bitrb(s, &bp, 5 - ((m->mode != 3) << 1));
|
||||||
|
char num_ch = 1 + (m->mode != 3);
|
||||||
|
char scfsi[4][num_ch];
|
||||||
|
uint16_t part2_3_length[2][num_ch];
|
||||||
|
uint16_t big_values[2][num_ch];
|
||||||
|
uint8_t global_gain[2][num_ch];
|
||||||
|
uint8_t scalefac_compress[2][num_ch];
|
||||||
|
uint8_t blocksplit_flag[2][num_ch];
|
||||||
|
|
||||||
|
// used if blocksplit flag is set
|
||||||
|
uint8_t block_type[2][num_ch];
|
||||||
|
uint8_t switch_point[2][num_ch];
|
||||||
|
uint8_t table_select[2][2][num_ch];
|
||||||
|
uint8_t subblock_gain[3][2][num_ch];
|
||||||
|
|
||||||
|
// used if NOT set
|
||||||
|
uint8_t region_address1[2][num_ch];
|
||||||
|
uint8_t region_address2[2][num_ch];
|
||||||
|
|
||||||
|
uint8_t preflag[2][num_ch];
|
||||||
|
uint8_t scalefac_scale[2][num_ch];
|
||||||
|
uint8_t count1table_select[2][num_ch];
|
||||||
|
|
||||||
|
for(int band = 0; band < 4; band++) for(int ch = 0; ch < num_ch; ch++) scfsi[band][ch] = bitrb(s, &bp, 1);
|
||||||
|
|
||||||
|
for(int gr = 0; gr < 2; gr++) for(int ch = 0; ch < num_ch; ch++) {
|
||||||
|
part2_3_length[gr][ch] = bitrb(s, &bp, 12);
|
||||||
|
big_values[gr][ch] = bitrb(s, &bp, 9);
|
||||||
|
global_gain[gr][ch] = bitrb(s, &bp, 8);
|
||||||
|
scalefac_compress[gr][ch] = bitrb(s, &bp, 4);
|
||||||
|
blocksplit_flag[gr][ch] = bitrb(s, &bp, 1);
|
||||||
|
if(blocksplit_flag[gr][ch]) {
|
||||||
|
block_type[gr][ch] = bitrb(s, &bp, 2);
|
||||||
|
switch_point[gr][ch] = bitrb(s, &bp, 1);
|
||||||
|
for(int reg = 0; reg < 2; reg++) table_select[reg][gr][ch] = bitrb(s, &bp, 5);
|
||||||
|
for(int window = 0; window < 3; window++) subblock_gain[window][gr][ch] = bitrb(s, &bp, 3);
|
||||||
|
} else {
|
||||||
|
for(int reg = 0; reg < 3; reg++) table_select[reg][gr][ch] = bitrb(s, &bp, 5);
|
||||||
|
region_address1[gr][ch] = bitrb(s, &bp, 4);
|
||||||
|
region_address2[gr][ch] = bitrb(s, &bp, 3);
|
||||||
|
}
|
||||||
|
preflag[gr][ch] = bitrb(s, &bp, 1);
|
||||||
|
scalefac_scale[gr][ch] = bitrb(s, &bp, 1);
|
||||||
|
count1table_select[gr][ch] = bitrb(s, &bp, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// begin to parse main_data
|
||||||
|
// TODO completely unclear where it is supposed to start - comment from specification reproduced below
|
||||||
|
/***
|
||||||
|
The main_data follows. It does not follow the above side information in the
|
||||||
|
bitstream. The main_data ends at a location in the main_data bitstream
|
||||||
|
preceding the frame header of the following frame at an offset given by the
|
||||||
|
value of main_data_end (see definition of main_data_end and 3-Annex Fig.3-
|
||||||
|
A.7.1
|
||||||
|
***/
|
||||||
|
|
||||||
|
int bpsave = bp;
|
||||||
|
|
||||||
|
for(int gr = 0; gr < 2; gr++) for(int ch = 0; ch < num_ch; ch++) {
|
||||||
|
if(blocksplit_flag[gr][ch] && block_type[gr][ch] == 2) {
|
||||||
|
// long window(?)
|
||||||
|
for(int cb = 0; cb < (switch_point[gr][ch] ? 8 : 0); cb++) if(!scfsi[cb] | !gr) {
|
||||||
|
// TODO scalefac[cb][gr][ch]
|
||||||
|
// use scalefac_compress[gr][ch]
|
||||||
|
int sfcd;
|
||||||
|
if(block_type[gr][ch] != 2) sfcd = cb > 10;
|
||||||
|
else if(switch_point[gr][ch]) {
|
||||||
|
// TODO if block_type is 2 and switch_point is 1
|
||||||
|
} else sfcd = cb > 5;
|
||||||
|
//scalefac[cb][0/*window*/][gr][ch] = bitrb(s, &bp, sfcom[scalefac_compress[gr][ch]][sfcd]);
|
||||||
|
|
||||||
|
}
|
||||||
|
// short window(?)
|
||||||
|
for(int cb = (switch_point[gr][ch] ? 3 : 0); cb < cblimit_short; cb++) for(int window = 0; window < 3; window++) if(!scfsi[cb] | !gr) {
|
||||||
|
// TODO scalefac[cb][gr][ch]
|
||||||
|
// use scalefac_compress[gr][ch]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for(int cb = 0; cb < cblimit; cb++) if(!scfsi[cb] | !gr) {
|
||||||
|
// TODO scalefac[cb][gr][ch]
|
||||||
|
// use scalefac_compress[gr][ch]
|
||||||
|
}
|
||||||
|
// TODO huffman bits
|
||||||
|
unsigned short csz = 16, ci = 0;
|
||||||
|
coord* c = malloc(csz * sizeof(coord));
|
||||||
|
while(bp < bpsave + part2_3_length[gr][ch]) {
|
||||||
|
//bp += huffman(table_select[]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#define bitrb(x, y, z) ibitrb((uint8_t*)x, y, z)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t x;
|
||||||
|
uint8_t y;
|
||||||
|
} coord;
|
||||||
|
|
||||||
|
// frame data
|
||||||
|
typedef struct {
|
||||||
|
|
||||||
|
uint32_t hdr;
|
||||||
|
|
||||||
|
// parsed out
|
||||||
|
uint16_t bitrate;
|
||||||
|
uint16_t smprate;
|
||||||
|
uint16_t len;
|
||||||
|
|
||||||
|
// bitflags
|
||||||
|
uint8_t prot; // crc protection - TODO add to verify_l3
|
||||||
|
uint8_t priv;
|
||||||
|
uint8_t smpbit;
|
||||||
|
uint8_t jint; // joint stereo - intensity stereo
|
||||||
|
uint8_t jmss; // joint stereo - MS stereo (?)
|
||||||
|
|
||||||
|
// indices
|
||||||
|
uint8_t mode;
|
||||||
|
uint8_t emph; // emphasis?
|
||||||
|
|
||||||
|
// parsed data
|
||||||
|
int32_t crc; // negative when not present
|
||||||
|
|
||||||
|
uint8_t dat[1018];
|
||||||
|
} mp3_frame;
|
||||||
|
|
||||||
|
uint8_t bitb(uint8_t* s, uint32_t b);
|
||||||
|
uint32_t ibitrb(uint8_t* s, uint32_t* b, char e);
|
||||||
|
uint32_t verify_l3(uint32_t d);
|
||||||
|
void rdl3(uint32_t* s, mp3_frame* m);
|
|
@ -0,0 +1,3 @@
|
||||||
|
echo -e ", {\t\t\t\t\t\t\t// $1"
|
||||||
|
eval `wl-paste|sed 's/^/\.\/huffcvt /g;s/$/;/g'`
|
||||||
|
echo -ne '\t}'
|
|
@ -0,0 +1,16 @@
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
unsigned long btoi(char* s) {
|
||||||
|
unsigned long r = 0;
|
||||||
|
int l = strlen(s) - 1;
|
||||||
|
for(int i = l; i >= 0; i--) {
|
||||||
|
r <<= 1;
|
||||||
|
r |= (s[l-i]-'0');
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
printf("\t\t{%s,%s,%s,%i},\n", argv[1], argv[2], argv[3], btoi(argv[4]));
|
||||||
|
}
|
Loading…
Reference in New Issue