organization
This commit is contained in:
parent
3989ed9779
commit
1f7a101e6c
11
README.md
11
README.md
|
@ -1,2 +1,13 @@
|
|||
# MPEG-1 Layer III
|
||||
## 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