void codeDesilence ( void *inb, void *outb) /*********************************************************************** Silence deencoding ************************************************************************ inb input buffer outb output buffer ***********************************************************************/ { memBUFF *inbuff = (memBUFF *) inb; memBUFF *outbuff = (memBUFF *) outb; int c, run_count=0; while(buffGetc(inbuff, c) != MEM_EOB){ if(c==SILENCECODE){ buffGetc(inbuff, run_count); while(run_count-- >0) buffPutc(outbuff, 0x0); } else buffPutc(outbuff, c); } }
int huffDecoder (wpcBITBUFF *bit_buff, wpcBUFF *outbuff, huffNODE *nodes, int root_node) /************************************************************************* decode all the symbols in the bit stream buffer ************************************************************************** bit_buffer input buffer for the bit stream outbuff output buffer for the byte stream nodes array[] holding the nodes of the Huffman tree root_node node to start decoding ************************************************************************** Note: Decoding is done on a bit-by-bit base. When a leaf node is reach, the symbol is written to the output. *************************************************************************/ { int node, tmp; for(; ; ){ /* start from the root */ node = root_node; /* while going through the internal nodes */ do { bitInputbit(bit_buff, tmp); if(tmp == WPC_EOB) return WPC_EOB; else if(tmp) node = nodes[node].child_1; else node = nodes[node].child_0; } while(node > HUFFENDOFBLK); if(node == HUFFENDOFBLK) break; /* output the symbol */ buffPutc(outbuff, node); } return 0; }
void codeSilence (void *inb, void *outb) /*********************************************************************** Silence encoding, takes care of "silence" pieces ************************************************************************ inb input buffer outb output buffer ***********************************************************************/ { memBUFF *inbuff = (memBUFF *) inb; memBUFF *outbuff = (memBUFF *) outb; int look_ahead[LOOKAHSZ]; int index, i, run_length, flag; /* preload the look ahead buffer */ for(i=0; i<LOOKAHSZ; i++) if(buffGetc(inbuff, look_ahead[i]) == MEM_EOB) break; /* if not enough samples, no RLE */ if(i < LOOKAHSZ){ buffMerge(outbuff, inbuff); return; } index = 0; for(;;){ if(look_ahead[index] == MEM_EOB) break; if(silence_run(look_ahead, index)){ run_length = 0; do{ flag = buffGetc(inbuff, look_ahead[index]); if(flag == MEM_EOB) look_ahead[index] = MEM_EOB; index ++; index &= LOOKAHMASK; if(++run_length == MAXLENGTH){ buffPutc(outbuff, SILENCECODE); buffPutc(outbuff, MAXLENGTH); run_length = 0; } } while(!end_of_silence(look_ahead, index)); if(run_length > 0){ buffPutc(outbuff, SILENCECODE); buffPutc(outbuff, run_length); } } if(look_ahead[index] == MEM_EOB) break; /* the silence code in the input get changed */ if(look_ahead[index] == SILENCECODE) look_ahead[index]++; buffPutc(outbuff, look_ahead[index]); /* get a new code */ flag = buffGetc(inbuff, look_ahead[index]); if(flag == MEM_EOB) look_ahead[index] = MEM_EOB; index ++; index &= LOOKAHMASK; } }
memBUFF* pEncode(int *qx, int n) /****************************************************************************** qx array[] of input integers n length of input Returned: encoded output ******************************************************************************/ { int i; size_t nsize; unsigned int s; unsigned char c1,c2; memBUFF *buff; /* allocate spaces */ nsize = 2*n*sizeof(char); buff = buffAlloc1((int) nsize); /* encoding */ for(i=0;i<n;i++){ if(qx[i] > 0){ /* if overflow */ if(qx[i] > QUANTMAX){ s = qx[i]; /* is there any signal on earth that can make this happen? */ if(s > MAXLOAD) s = MAXLOAD; /* shift the level to avoid silence code */ s = (s << 1) + 1; /* output a prefix code */ buffPutc(buff, PC_OVERFLOW); /* output a short, higher byte first */ c1 = s/BYTEMAX; buffPutc(buff, c1); c2 = s - c1*BYTEMAX; buffPutc(buff, c2); } else { c1 = (unsigned char) qx[i]; buffPutc(buff, c1); } } /* negative */ else{ /* if underflow */ if(qx[i] < -QUANTMAX){ s = - qx[i]; /* is there any signal on earth that can make this happen? */ if(s > MAXLOAD) s = MAXLOAD; /* shift the level to avoid silence code */ s = (s << 1) + 1; /* output a prefix code */ buffPutc(buff, PC_UNDERFLOW); /* output a short, higher byte first */ c1 = s/BYTEMAX; buffPutc(buff, c1); c2 = s - c1*BYTEMAX; buffPutc(buff, c2); } else{ c1 = (unsigned char) qx[i]; buffPutc(buff, c1); } } } /* adjust the buffer size */ buffRealloc1(buff, buff->pos); /* return the buffer pointer */ return(buff); }
void codeSilence (void *inb, void *outb) /*********************************************************************** Silence encoding, takes care of "silence" pieces ************************************************************************ inb input buffer outb output buffer ************************************************************************ Note: To avoid the inefficiency in encoding isolated 0's, I start a run only when there are CODESTARTTHRSHOLD consective 0's. Therefore, a look ahead buffer is needed. The run is stopped as soon as there is a non-0 symbol. ***********************************************************************/ { wpcBUFF *inbuff = (wpcBUFF *) inb; wpcBUFF *outbuff = (wpcBUFF *) outb; int look_ahead[CODELOOKAHSZ]; int index, i, run_length, flag; /* preload the look ahead buffer */ for(i=0; i<CODELOOKAHSZ; i++) if(buffGetc(inbuff, look_ahead[i]) == WPC_EOB) break; /* if not enough samples, no RLE */ if(i < CODELOOKAHSZ){ buffMerge(outbuff, inbuff); return; } index = 0; for(;;){ if(look_ahead[index] == WPC_EOB) break; if(silence_run(look_ahead, index)){ run_length = 0; do{ flag = buffGetc(inbuff, look_ahead[index]); if(flag == WPC_EOB) look_ahead[index] = WPC_EOB; index ++; index &= CODELOOKAHMASK; if(++run_length == CODEMAXLENGTH){ buffPutc(outbuff, CODESILENCECODE); buffPutc(outbuff, CODEMAXLENGTH); run_length = 0; } } while(!end_of_silence(look_ahead, index)); if(run_length > 0){ buffPutc(outbuff, CODESILENCECODE); buffPutc(outbuff, run_length); } } if(look_ahead[index] == WPC_EOB) break; /* the silence code in the input get changed */ if(look_ahead[index] == CODESILENCECODE) look_ahead[index]++; buffPutc(outbuff, look_ahead[index]); /* get a new code */ flag = buffGetc(inbuff, look_ahead[index]); if(flag == WPC_EOB) look_ahead[index] = WPC_EOB; index ++; index &= CODELOOKAHMASK; } }
int huffOutputcounts (wpcBITBUFF *bit_buff, huffNODE *nodes) /************************************************************************* output the hit count table to the output buffer ************************************************************************** bit_buff buffer holding the encoded bit stream nodes array[] of nodes hold the leaves (the symbols) of the Huffman tree ************************************************************************** Note: All the side information needed for decoding is this hit count table, from which the Huffman tree that is neede for decoding can be built. To reduce the overhead of the hit count table, a simplified runlength coding is used. It contains the first and last symbols in the run, followed by the hit counts of each symbol. The last symbol HUFFTERM is used as the terminator. Only runs longer than HUFFRUNMIN is treated this way. *************************************************************************/ { int first, last, next, i; int nbytes = 0; /* the first symbol in a run */ first = 0; while(first < (HUFFNSYMBOL-1) && nodes[first].count ==0) first ++; for(; first < HUFFNSYMBOL; first=next){ /* find the last symbol in this run and the first symbol of the next run */ last = first + 1; for (; ; ){ for(; last < HUFFNSYMBOL; last ++) if(nodes[last].count == 0) break; last -- ; for(next = last + 1; next < HUFFNSYMBOL; next ++) if(nodes[next].count != 0) break; if(next > (HUFFNSYMBOL-1)) break; if((next - last) > HUFFRUNMIN) break; last = next; } /* output the first, last and hit counts */ if(buffPutc(bit_buff->buff, first) == WPC_EOB) return WPC_EOB; nbytes ++; if(buffPutc(bit_buff->buff, last) == WPC_EOB) return WPC_EOB; nbytes ++; for(i=first; i<=last; i++){ if(buffPutc(bit_buff->buff, nodes[i].count) == WPC_EOB) return WPC_EOB; nbytes ++; } } /* output the terminator for the end of count table */ if(buffPutc(bit_buff->buff, HUFFTERM) == WPC_EOB) return WPC_EOB; nbytes ++; return (nbytes); }