organization

This commit is contained in:
'mr software' 2023-10-08 21:26:36 -07:00
parent 3989ed9779
commit 1f7a101e6c
8 changed files with 5321 additions and 5279 deletions

View File

@ -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

97
dat.h Normal file
View File

@ -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};

5000
huffman.h Normal file

File diff suppressed because it is too large Load Diff

5280
main.c

File diff suppressed because it is too large Load Diff

146
mp3.c Normal file
View File

@ -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[]);
}
}
}
}

47
mp3.h Normal file
View File

@ -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);

3
scr/huff Executable file
View File

@ -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}'

16
scr/huffcvt.c Normal file
View File

@ -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]));
}