huffman.c
上传用户:tuheem
上传日期:2007-05-01
资源大小:21889k
文件大小:4k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. /**********************************************************************  * MPEG/audio 编码/解码软件              *  * VERSION 2.10                                                       *  *********************************************************************/ #include <string.h>
  2. #include <stdlib.h>
  3. #include "common.h" #include "huffman.h"       HUFFBITS dmask = 1 << (sizeof(HUFFBITS)*8-1); struct huffcodetab ht[HTN]; /* 所有 huffcodtable headers的数组 */
  4. /* 0..31 Huffman code table 0..31 */
  5. /* 32,33 count1-tables */
  6. /* 读取 huffman 解码表 */ int read_decoder_table(FILE *fi)  {   int n,i,nn,t;   unsigned int v0,v1;   char command[100],line[100];   for (n=0;n<HTN;n++) {          do {       fgets(line,99,fi);     } while ((line[0] == '#') || (line[0] < ' '));           sscanf(line,"%s %s %u %u %u %u",command,ht[n].tablename,            &ht[n].treelen, &ht[n].xlen, &ht[n].ylen, &ht[n].linbits);     if (strcmp(command,".end")==0)       return n;     else if (strcmp(command,".table")!=0) {       fprintf(stderr,"huffman table %u data corruptedn",n);       return -1;     }     ht[n].linmax = (1<<ht[n].linbits)-1;         sscanf(ht[n].tablename,"%u",&nn);     if (nn != n) {       fprintf(stderr,"wrong table number %un",n);       return(-2);     }      do {       fgets(line,99,fi);     } while ((line[0] == '#') || (line[0] < ' '));     sscanf(line,"%s %u",command,&t);     if (strcmp(command,".reference")==0) {       ht[n].ref   = t;       ht[n].val   = ht[t].val;       ht[n].treelen  = ht[t].treelen;       if ( (ht[n].xlen != ht[t].xlen) ||            (ht[n].ylen != ht[t].ylen)  ) {         fprintf(stderr,"wrong table %u referencen",n);         return (-3);       };       while ((line[0] == '#') || (line[0] < ' ') ) {         fgets(line,99,fi);       }     }         else if (strcmp(command,".treedata")==0) {       ht[n].ref  = -1;       ht[n].val = (unsigned char (*)[2])          calloc(2*(ht[n].treelen),sizeof(unsigned char));       if ((ht[n].val == NULL) && ( ht[n].treelen != 0 )){      fprintf(stderr, "heaperror at table %dn",n);      exit (-10);       }       for (i=0;i<ht[n].treelen; i++) {         fscanf(fi,"%x %x",&v0, &v1);         ht[n].val[i][0]=(unsigned char)v0;         ht[n].val[i][1]=(unsigned char)v1;       }       fgets(line,99,fi); /* 读取剩余行 */     }     else {       fprintf(stderr,"huffman decodertable error at table %dn",n);     }   }   return n; } /* 进行huffman解码 */ /* 注意! 对counta,countb - 4 bit 值 用 y返回, discard x */ int huffman_decoder(struct huffcodetab *h, int *x, int *y, int *v, int *w) {     HUFFBITS level;   int point = 0;   int error = 1;   level     = dmask;   if (h->val == NULL) return 2;   /* table 0 不需要 bits */   if ( h->treelen == 0)   {  *x = *y = 0;      return 0;   }   /* 查找 Huffman table. */   do {     if (h->val[point][0]==0) {   /*树的结尾*/       *x = h->val[point][1] >> 4;       *y = h->val[point][1] & 0xf;       error = 0;       break;     }      if (hget1bit()) {       while (h->val[point][1] >= MXOFF) point += h->val[point][1];        point += h->val[point][1];     }     else {       while (h->val[point][0] >= MXOFF) point += h->val[point][0];        point += h->val[point][0];     }     level >>= 1;   } while (level  || (point < ht->treelen) );      /* 检查错误 */      if (error) { /* 设置 x 和 y 为一中间值 */     printf("Illegal Huffman code in data.n");     *x = (h->xlen-1 << 1);     *y = (h->ylen-1 << 1);   }   /* 处理信号编码 */   if (h->tablename[0] == '3'       && (h->tablename[1] == '2' || h->tablename[1] == '3')) {      *v = (*y>>3) & 1;      *w = (*y>>2) & 1;      *x = (*y>>1) & 1;      *y = *y & 1;      /* v, w, x 和 y 在比特流中是颠倒的,交换他们           */       /*   {int i=*v; *v=*y; *y=i; i=*w; *w=*x; *x=i;}  MI */      if (*v)         if (hget1bit() == 1) *v = -*v;      if (*w)         if (hget1bit() == 1) *w = -*w;      if (*x)         if (hget1bit() == 1) *x = -*x;      if (*y)         if (hget1bit() == 1) *y = -*y;      }         /* 对dual table情况,处理信号编码 */      else {          /* 在测试比特流中x 和 y是颠倒的           这里颠倒 x 和 y 使测试比特流正常 */           if (h->linbits)        if ((h->xlen-1) == *x)           *x += hgetbits(h->linbits);      if (*x)         if (hget1bit() == 1) *x = -*x;      if (h->linbits)           if ((h->ylen-1) == *y)          *y += hgetbits(h->linbits);      if (*y)         if (hget1bit() == 1) *y = -*y;      }      return error;   }