📄 shpack_io.c
字号:
#include <stdio.h>#include <sys/types.h>#include <netinet/in.h>#include <sys/stat.h>#include <fcntl.h>#include <math.h>/**** Added byt JGF ****/#include <sp/sphere.h>#include <util/min.h>#ifdef fread# undef fread#endif#define fread(a,b,c,d) fob_fread((a),(b),(c),(d)) #ifdef fwrite# undef fwrite#endif#define fwrite(a,b,c,d) fob_fwrite((a),(b),(c),(d)) #ifdef putc# undef putc#endif#define putc(a,b) fob_putc((a),(b))#ifdef getc# undef getc#endif#define getc(a) fob_getc((a))#ifdef fgetc# undef fgetc#endif#define fgetc(a) fob_getc((a))#ifdef getw# undef getw#endif#define getw(a) fob_getw((a)) #ifdef fputc# undef fputc#endif#define fputc(a,b) fob_putc((a),(b))/**** End of FOB additions ****/#ifndef TRUE#define FALSE 0#define TRUE 1#endif#define COMPRESS 1#define UNCOMPRESS 2#define INFO 3#define SWAP_BYTES 1#define ALL_ONES 0xffffffffstatic short log2s[] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024,2048, 4096, 8192, 16384, 32768};/*keep*/static char ieee_order = -1; /*-1 means not set yet*/static char *SccsId = "@(#) %W% %D% MIT/LCS/SLS";/*************************************************************************** shortpack_io.c Peter Daly pdaly@goldilocks.lcs.mit.edu Spoken Language Systems Group MIT Laboratory for Computer Science Creation Date: 12-JUL-1990 This program compresses utterance files made up of short integers. Refer to the manpage for more information. This segment comprises the "guts" of the shortpack algorithim. Revision History: 08-OCT-1990 Modified to not compress files which have an odd number of bytes, since they are obviously not made up of short integers (pdaly). 28-AUG-1991 Rewrote many routines to make implementation clearer (mp) Compression algorithim by Mike Phillips, MIT/LCS/SLS Copyright (C) 1990, 1991 Massachusetts Institute of Technology All Rights Reserved**************************************************************************//* /*ok, here's how shortpack works:The idea is to pack short integers into as few bits as required forsequences of speech samples. For each sequence, a 16 bit header iswritten that says "here comes n words using m bits per word". Thecompression code needs to decide where to break up the sequences tooptimize the tradeoff between transmitting fewer bits for the sequencevs the cost of transmitting another header for another sequence break.The present algorithm does an OK job, but if you went to more work inthe compression algorithm, you could probably save a percent or two ofthe file size.If you just want to read and write shortpacked data from yourprograms, use the following two functions:read_shortpacked_data(array, num_elements, fp) - use this for reading shortpacked data into an array (works like fread())write_shortpacked_data(array, num_elements, fp) - use this for writing shortpacked data from an array (works like fwrite())If you want to do file-to-file compression (like the shortpack utilitydoes), use write_shortpack_reading_from_file() andread_shortpack_writing_to_file()These routines use a circular buffer to hold data between input andoutput of the shortpacked data.The file-to-file and file-to-memory routines use the same low levelroutines (so the low level routines support the use of circularbuffers (they use a mask before indexing the buffer array - thememory-to-file routines just use ALL_ONES as a mask))All of these routines should work with machines with either byte order(the routines load and dump shortpack file format data to and from themachines short representation).If you have any problems, let me know - mike (phillips@goldilocks.lcs.mit.edu)*/#define MAX_HEADER_FIELD 100#define MAX_SEQUENCE_SIZE 255/*this goes through the input array, looks for chunks to pack into sonumber of bit, compresses those into a temporary array, and writes aheader followed by the chunk of data*/write_shortpacked_data(array, num_elements, fp)short *array;int num_elements;FOB *fp;{ int i,j,k; int input_pointer; int num_in_chunk; int bits; input_pointer = 0; while(input_pointer < num_elements) { num_in_chunk = find_next_chunk_to_compress(array, input_pointer, num_elements, &bits, ALL_ONES); pack_and_write_chunk_to_file(array, input_pointer, num_in_chunk, bits, fp, ALL_ONES); input_pointer += num_in_chunk; } return input_pointer;}read_shortpacked_data(array, num_elements, fp)short *array;int num_elements;FOB *fp;{ int i,j,k; int input_pointer; int num_in_chunk; input_pointer = 0; while(input_pointer < num_elements) { num_in_chunk = read_shortpack_chunk_from_file(fp, array, input_pointer, num_elements, ALL_ONES); input_pointer += num_in_chunk; } return input_pointer;}#define CBUF_SIZE 512#define CBUF_MASK 511write_shortpack_reading_from_file(ifp, ofp, swap)FOB *ifp;FOB *ofp;int swap;{ int i,j,k; short cbuf[CBUF_SIZE]; int next_write,next_read; /*pointers_to_cbuf*/ int num_read; short test_short = 1; int how_much_to_write; char *char_ptr; char temp_char; char temp_char2; int num_to_read; int num_in_chunk; int bits; if(ieee_order == -1) /*set this if not set already*/ { ieee_order = (htons(test_short) == test_short); } next_read = next_write = 0; while(1) { /*first read data from file into cbuf, swapping bytes if needed*/ if(next_read <= next_write) { how_much_to_write = CBUF_SIZE - next_write; num_read = fread(&(cbuf[next_write]), sizeof(short), how_much_to_write, ifp); if((num_read == 0) && (next_read == next_write)) break;/* printf("num_read1 %d\n", num_read);*/ if(!(swap ^ ieee_order)) { char_ptr = (char*)&(cbuf[next_write]); for(i=0;i<num_read;i++) { temp_char = *char_ptr; temp_char2 = *(char_ptr+1); *(char_ptr++) = temp_char2; *(char_ptr++) = temp_char; } } if(num_read < how_much_to_write) { next_write += num_read; } else { next_write = 0; } } if(next_read > next_write) { how_much_to_write = next_read - next_write; num_read = fread(&(cbuf[next_write]), sizeof(short), how_much_to_write, ifp);/* printf("num_read2 %d\n", num_read);*/ if(!(swap ^ ieee_order)) { char_ptr = (char*)&(cbuf[next_write]); for(i=0;i<num_read;i++) { temp_char = *char_ptr; temp_char2 = *(char_ptr+1); *(char_ptr++) = temp_char2; *(char_ptr++) = temp_char; } } next_write += num_read; } /*now compress and write next chunk*/ if(next_write == next_read) { num_to_read = CBUF_SIZE; } else { if(next_write > next_read) { num_to_read = next_write - next_read; } else { num_to_read = CBUF_SIZE - (next_read - next_write); } } num_in_chunk = find_next_chunk_to_compress(cbuf, next_read, next_read + num_to_read, &bits, CBUF_MASK); pack_and_write_chunk_to_file(cbuf, next_read, num_in_chunk, bits, ofp, CBUF_MASK); next_read += num_in_chunk; next_read &= CBUF_MASK; }}read_shortpack_writing_to_file(ifp, ofp, swap)FOB *ifp;FOB *ofp;int swap;{ int i,j,k; short cbuf[CBUF_SIZE]; int next_write,next_read; /*pointers_to_cbuf*/ short test_short = 1; int how_much_to_write; int num_in_chunk; char *char_ptr; char temp_char; char temp_char2; int num_written; int room_in_cbuf; if(ieee_order == -1) /*set this if not set already*/ { ieee_order = (htons(test_short) == test_short); } next_read = next_write = 0; while(1) { if(next_write == next_read) { room_in_cbuf = CBUF_SIZE; } else { if(next_write > next_read) { room_in_cbuf = next_write - next_read; } else { room_in_cbuf = CBUF_SIZE - (next_read - next_write); } } num_in_chunk = read_shortpack_chunk_from_file(ifp, cbuf, next_write, next_write + room_in_cbuf, CBUF_MASK); if(num_in_chunk < 0) break; next_write += num_in_chunk; next_write &= CBUF_MASK; /*write data from cbuf to file, swapping bytes if needed*/ if(next_read >= next_write) { how_much_to_write = CBUF_SIZE - next_read; if(!(swap ^ ieee_order)) { char_ptr = (char*)&(cbuf[next_read]); for(i=0;i<how_much_to_write;i++) { temp_char = *char_ptr; temp_char2 = *(char_ptr+1); *(char_ptr++) = temp_char2; *(char_ptr++) = temp_char; } } num_written = fwrite(&(cbuf[next_read]), sizeof(short), how_much_to_write, ofp); if(num_written < how_much_to_write) { printf("read_shortpack_writing_to_file: HAD_TROUBLE_WRITING!!\n"); exit (-1); } else { next_read = 0; } } if(next_read < next_write) { how_much_to_write = next_write - next_read; if(!(swap ^ ieee_order)) { char_ptr = (char*)&(cbuf[next_read]); for(i=0;i<how_much_to_write;i++) { temp_char = *char_ptr; temp_char2 = *(char_ptr+1); *(char_ptr++) = temp_char2; *(char_ptr++) = temp_char; } } num_written = fwrite(&(cbuf[next_read]), sizeof(short), how_much_to_write, ofp); if(num_written < how_much_to_write) { printf("read_shortpack_writing_to_file: HAD_TROUBLE_WRITING!!\n"); exit (-1); } next_read += how_much_to_write; } }}/* * find_bits_needed(): deterimine the minimum number of bits needed to to represent a number. */intfind_bits_needed(num)short num;{ int i; num = abs(num); for (i = 14; i >= 0; i--) if ((num & log2s[i]) != 0) return (i + 1); return (0);}/* * find_next_chunk_to_compress: (compression) look ahead in the uncompressed data to determine how many bits will be needed to represent the next chunk of data. */find_next_chunk_to_compress(buffer, start, num_elements, pbits, mask)short *buffer;int start;int num_elements;int *pbits;int mask;{ int i,j,k; int end; short abs_element; int bits_for_element; int bits_for_chunk; short bits_for_element_cache[MAX_SEQUENCE_SIZE]; /*so we don't have to recompute each time*/ int num; int ind; if((num_elements - start) > MAX_SEQUENCE_SIZE) { end = start + MAX_SEQUENCE_SIZE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -