diff --git a/main.c b/main.c index 9a21036..e403bdc 100644 --- a/main.c +++ b/main.c @@ -1,19 +1,33 @@ #include #include #include +#include #include #include #include #include +// 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) +//#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 bitrb(x, y, z) ibitrb((uint8_t*)x, y, z) #define cast(x, y) (*((x*)&(y))) -uint32_t bitrb(uint8_t* s, uint32_t b, char e) { // bit range big endian +#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 %X\n", a); + 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; } @@ -5127,6 +5141,32 @@ uint32_t verify_l3(uint32_t d) { // returns 0 if header is valid return (d & 0xFFFE0000) ^ 0xFFFA0000; } +typedef struct { + uint8_t x; + uint8_t y; +} coord; + +// 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}, +}; + void rdl3(uint32_t* s, mp3_frame* m) { uint32_t d = ntohl(*(s++)); m->hdr = d; @@ -5143,9 +5183,98 @@ void rdl3(uint32_t* s, mp3_frame* m) { m->crc = htons(*((uint16_t*)s)); // only valid if m->crc - int bp = m->prot << 4; // bitpointer - if(m->mode) { // mono - + 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[]); + } + } } } @@ -5164,11 +5293,20 @@ int main(int argc, char** argv) { uint8_t* stream = malloc(s.st_size); read(fd, stream, s.st_size); + static char* yn[2] = {"no", "yes"}; static char* chtyp[4] = {"stereo", "joint stereo", "dual mono (stereo)", "mono"}; static char* emph[4] = {"none", "50/15 ms", "reserved", "CCIT J.17"}; - printf("begin reading %s (%u bytes at %p)\n", argv[f], s.st_size, stream); + printf("begin reading %s (%lu bytes at %p)\n", argv[f], s.st_size, stream); + + if(!memcmp(stream, "ID3", 3)) { + int d = htonl(*((uint32_t*)(stream + 6))); + sp += d + 10 + ((stream[5] & 0x10) ? 10 : 0); + printf("ID3v2 detected, skipping %08X bytes so as not to deal with it\n", sp); + } + + if(!memcmp(stream + s.st_size - 128, "TAG", 3)) printf("TAG detected :)\n"); while(!verify_l3(*(uint32_t*)(stream + sp))) { printf("frame %u sync at %u (%X)!\n", fc, sp, sp); @@ -5196,5 +5334,7 @@ int main(int argc, char** argv) { sp += m.len; fc++; } + + free(stream); } }