/**************************************************************************** Huffman coding Copyright (C) 2017 Krzysztof Nikiel This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ****************************************************************************/ #include #include #include "coder.h" #include "huffdata.h" #include "huff2.h" #include "bitstream.h" static int escape(int x, int *code) { int preflen = 0; int base = 32; if (x > MAX_HUFF_ESC_VAL) { fprintf(stderr, "%s(%d): x_quant > %d\n", __FILE__, __LINE__, MAX_HUFF_ESC_VAL); return 0; } *code = 0; while (base <= x) { base <<= 1; *code <<= 1; *code |= 1; preflen++; } base >>= 1; // separator *code <<= 1; *code <<= (preflen + 4); *code |= (x - base); return (preflen << 1) + 5; } #define arrlen(array) (sizeof(array) / sizeof(*array)) static int huffcode(int *qs /* quantized spectrum */, int len, int bnum, CoderInfo *coder) { static hcode16_t * const hmap[12] = {0, book01, book02, book03, book04, book05, book06, book07, book08, book09, book10, book11}; hcode16_t *book; int cnt; int bits = 0, blen; int ofs, *qp; int data = 0; int idx; int datacnt; if (coder) datacnt = coder->datacnt; else datacnt = 0; book = hmap[bnum]; switch (bnum) { case 1: case 2: for(ofs = 0; ofs < len; ofs += 4) { qp = qs+ofs; idx = 27 * qp[0] + 9 * qp[1] + 3 * qp[2] + qp[3] + 40; if (idx < 0 || idx >= arrlen(book01)) { return -1; } blen = book[idx].len; if (coder) { data = book[idx].data; coder->s[datacnt].data = data; coder->s[datacnt++].len = blen; } bits += blen; } break; case 3: case 4: for(ofs = 0; ofs < len; ofs += 4) { qp = qs+ofs; idx = 27 * abs(qp[0]) + 9 * abs(qp[1]) + 3 * abs(qp[2]) + abs(qp[3]); if (idx < 0 || idx >= arrlen(book03)) { return -1; } blen = book[idx].len; if (!coder) { // add sign bits for(cnt = 0; cnt < 4; cnt++) if(qp[cnt]) blen++; } else { data = book[idx].data; // add sign bits for(cnt = 0; cnt < 4; cnt++) { if(qp[cnt]) { blen++; data <<= 1; if (qp[cnt] < 0) data |= 1; } } coder->s[datacnt].data = data; coder->s[datacnt++].len = blen; } bits += blen; } break; case 5: case 6: for(ofs = 0; ofs < len; ofs += 2) { qp = qs+ofs; idx = 9 * qp[0] + qp[1] + 40; if (idx < 0 || idx >= arrlen(book05)) { return -1; } blen = book[idx].len; if (coder) { data = book[idx].data; coder->s[datacnt].data = data; coder->s[datacnt++].len = blen; } bits += blen; } break; case 7: case 8: for(ofs = 0; ofs < len; ofs += 2) { qp = qs+ofs; idx = 8 * abs(qp[0]) + abs(qp[1]); if (idx < 0 || idx >= arrlen(book07)) { return -1; } blen = book[idx].len; if (!coder) { for(cnt = 0; cnt < 2; cnt++) if(qp[cnt]) blen++; } else { data = book[idx].data; for(cnt = 0; cnt < 2; cnt++) { if(qp[cnt]) { blen++; data <<= 1; if (qp[cnt] < 0) data |= 1; } } coder->s[datacnt].data = data; coder->s[datacnt++].len = blen; } bits += blen; } break; case 9: case 10: for(ofs = 0; ofs < len; ofs += 2) { qp = qs+ofs; idx = 13 * abs(qp[0]) + abs(qp[1]); if (idx < 0 || idx >= arrlen(book09)) { return -1; } blen = book[idx].len; if (!coder) { for(cnt = 0; cnt < 2; cnt++) if(qp[cnt]) blen++; } else { data = book[idx].data; for(cnt = 0; cnt < 2; cnt++) { if(qp[cnt]) { blen++; data <<= 1; if (qp[cnt] < 0) data |= 1; } } coder->s[datacnt].data = data; coder->s[datacnt++].len = blen; } bits += blen; } break; case HCB_ESC: for(ofs = 0; ofs < len; ofs += 2) { int x0, x1; qp = qs+ofs; x0 = abs(qp[0]); x1 = abs(qp[1]); if (x0 > 16) x0 = 16; if (x1 > 16) x1 = 16; idx = 17 * x0 + x1; if (idx < 0 || idx >= arrlen(book11)) { return -1; } blen = book[idx].len; if (!coder) { for(cnt = 0; cnt < 2; cnt++) if(qp[cnt]) blen++; } else { data = book[idx].data; for(cnt = 0; cnt < 2; cnt++) { if(qp[cnt]) { blen++; data <<= 1; if (qp[cnt] < 0) data |= 1; } } coder->s[datacnt].data = data; coder->s[datacnt++].len = blen; } bits += blen; if (x0 >= 16) { blen = escape(abs(qp[0]), &data); if (coder) { coder->s[datacnt].data = data; coder->s[datacnt++].len = blen; } bits += blen; } if (x1 >= 16) { blen = escape(abs(qp[1]), &data); if (coder) { coder->s[datacnt].data = data; coder->s[datacnt++].len = blen; } bits += blen; } } break; default: fprintf(stderr, "%s(%d) book %d out of range\n", __FILE__, __LINE__, bnum); return -1; } if (coder) coder->datacnt = datacnt; return bits; } int huffbook(CoderInfo *coder, int *qs /* quantized spectrum */, int len) { int cnt; int maxq = 0; int bookmin, lenmin; for (cnt = 0; cnt < len; cnt++) { int q = abs(qs[cnt]); if (maxq < q) maxq = q; } #define BOOKMIN(n)bookmin=n;lenmin=huffcode(qs,len,bookmin,0);if(huffcode(qs,len,bookmin+1,0) HCB_ZERO) huffcode(qs, len, bookmin, coder); coder->book[coder->bandcnt] = bookmin; return 0; } int writebooks(CoderInfo *coder, BitStream *stream, int write) { int bits = 0; int maxcnt, cntbits; int group; int bookbits = 4; if (coder->block_type == ONLY_SHORT_WINDOW){ maxcnt = 7; cntbits = 3; } else { maxcnt = 31; cntbits = 5; } for (group = 0; group < coder->groups.n; group++) { int band = group * coder->sfbn; int maxband = band + coder->sfbn; while (band < maxband) { int book = coder->book[band++]; int bookcnt = 1; if (write) { PutBit(stream, book, bookbits); } bits += bookbits; if (band < maxband) { while (book == coder->book[band]) { band++; bookcnt++; if (band >= maxband) break; } } while (bookcnt >= maxcnt) { if (write) PutBit(stream, maxcnt, cntbits); bits += cntbits; bookcnt -= maxcnt; } if (write) PutBit(stream, bookcnt, cntbits); bits += cntbits; } } return bits; } int writesf(CoderInfo *coder, BitStream *stream, int write) { int cnt; int bits = 0; int diff, length; int lastsf; int lastis; int lastpns; int initpns = 1; lastsf = coder->global_gain; lastis = 0; lastpns = coder->global_gain - SF_PNS_OFFSET; // fixme: move range check to quantizer for (cnt = 0; cnt < coder->bandcnt; cnt++) { int book = coder->book[cnt]; if ((book == HCB_INTENSITY) || (book== HCB_INTENSITY2)) { diff = coder->sf[cnt] - lastis; diff = clamp_sf_diff(diff); length = book12[SF_DELTA + diff].len; bits += length; lastis += diff; if (write) PutBit(stream, book12[SF_DELTA + diff].data, length); } else if (book == HCB_PNS) { diff = coder->sf[cnt] - lastpns; if (initpns) { initpns = 0; length = 9; bits += length; lastpns += diff; if (write) PutBit(stream, diff + 256, length); continue; } diff = clamp_sf_diff(diff); length = book12[SF_DELTA + diff].len; bits += length; lastpns += diff; if (write) PutBit(stream, book12[SF_DELTA + diff].data, length); } else if ((book != HCB_ZERO) && (book != HCB_NONE)) { diff = coder->sf[cnt] - lastsf; diff = clamp_sf_diff(diff); length = book12[SF_DELTA + diff].len; bits += length; lastsf += diff; if (write) PutBit(stream, book12[SF_DELTA + diff].data, length); } } return bits; }