1 /* bits.c
2  * Bit manipulations for Kexis
3  * NOTE: This code is Buggy for a number of cases, and is DEFINATELY broke
4  * on 64 bit, or big edian machines. (read: just about everything but intel)
5  * Copyright (C) 2000 Wayde Milas (wmilas@rarcoa.com)
6  *
7     This program is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation; either version 2 of the License, or
10     (at your option) any later version.
11 
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.
16 
17     You should have received a copy of the GNU General Public License
18     along with this program; if not, write to the Free Software
19     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20 */
21 
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include "types.h"
25 #include "bits.h"
26 #include "encode.h"
27 #include "kexis.h"
28 
29 /* This is just an function used to dump raw bits so I can see what the hell
30  * is going on when debugging.
31  */
print_bits(long bits,int len,unsigned long print)32 void print_bits(long bits, int len, unsigned long print)
33 {
34 	int loop=len-1;
35 	int	hold=0;
36 
37 	if(DEBUG == 1 &&
38 		(print>DEBUG_POS-DEBUG_DOWN && print<DEBUG_POS+DEBUG_UP)) {
39 		while(loop >= 0) {
40 			hold = 1<<loop;
41 			if((bits & hold) != 0)
42 				printf("1");
43 			else
44 			printf("0");
45 
46 			if((loop % 4) == 0)
47 				printf(" ");
48 
49 			loop--;
50 		}
51 		printf("  : %ld\n", bits);
52 	}
53 }
54 
push_bits(KEXISBLOCKSTRUCT * kexisBlock,long outBits,long length,OPTIONSTRUCT * options,PCMBLOCKSTRUCT * pcmBlock)55 void push_bits(KEXISBLOCKSTRUCT *kexisBlock, long outBits, long length,
56 	OPTIONSTRUCT *options, PCMBLOCKSTRUCT *pcmBlock)
57 {
58 	long		assembly=0;
59 
60 	// Check and see if the length of outbits is more
61 	// than 32. If so, we are in deep shit.
62 	if(length > 32) {
63 		printf("\nbitCounter: %d  length: %ld\n", kexisBlock->bitCounter, length);
64 		sprintf(options->errorString, "Bit Overflow in push_bits!");
65 		handle_error(options);
66 	}
67 
68 	//if(DEBUG==1 && (kexisBlock->debugBlockCount>DEBUG_POS-DEBUG_DOWN && kexisBlock->debugBlockCount<DEBUG_POS+DEBUG_UP))
69 		//printf("BitCounter: %d, Length: %ld, Data: %ld Count: %ld\n",
70 		//	kexisBlock->bitCounter, length, outBits, kexisBlock->debugBlockCount);
71 
72 	// Handle the most common case where there is no boundy issue.
73 	if(kexisBlock->bitCounter + length < 32) {
74 		// Loading outBits into the assembly.
75 		assembly = outBits;
76 		//print_bits(assembly, 32, kexisBlock->debugBlockCount);
77 		// shifting assembly into top word, packing tight based on
78 		// biitkexisBlock->debugBlockCounter.
79 		assembly <<= ((32 - kexisBlock->bitCounter) - length);
80 		//print_bits(assembly, 32, kexisBlock->debugBlockCount);
81 		// Move bits into transfer
82 		kexisBlock->bitBucket |= assembly;
83 		//print_bits(kexisBlock->bitBucket, 32, kexisBlock->debugBlockCount);
84 		// adjust bitCounter length;
85 		// check and see if we are right at the end
86 		kexisBlock->bitCounter += length;
87 	}
88 	else if(kexisBlock->bitCounter + length == 32) {
89 		// Loading outBits into the assembly.
90 		assembly = outBits;
91 		//print_bits(assembly, 32, kexisBlock->debugBlockCount);
92 		// shifting assembly into top word, packing tight based on
93 		// biitkexisBlock->debugBlockCounter.
94 		assembly <<= ((32 - kexisBlock->bitCounter) - length);
95 		//print_bits(assembly, 32, kexisBlock->debugBlockCount);
96 		// Move bits into data stream
97 		kexisBlock->data[kexisBlock->dataPosition] =
98 			kexisBlock->bitBucket | assembly;
99 		//print_bits(kexisBlock->data[kexisBlock->dataPosition], 32,
100 		//kexisBlock->debugBlockCount);
101 		//zer the bit bucket;
102 		kexisBlock->bitBucket = 0;
103 		// increment the kexisBlock->debugBlockCounter
104 		kexisBlock->dataPosition++;
105 		kexisBlock->bitCounter = 0;
106 		// If the stream is full, dump it to disk.
107 		if(kexisBlock->dataPosition == options->frameSize/2){
108 			write_kexisblock(options, kexisBlock, pcmBlock);
109 			kexisBlock->dataPosition = 0;
110 		}
111 	}
112 	// There is a boundry issue
113 	else {
114 		// Loading outBits into the assembly.
115 		assembly = outBits;
116 		//print_bits(assembly, 32, kexisBlock->debugBlockCount);
117 		// shift the assembly over so we get the fontmost bits.
118 		assembly >>= (length - (32 - kexisBlock->bitCounter));
119 		//print_bits(assembly, 32, kexisBlock->debugBlockCount);
120 		// We only want 32 - kexisBlock->bitCounter bits, Mask he rest out.
121 		assembly &= ((1<<(32-kexisBlock->bitCounter)) -1);
122 		//print_bits(assembly, 32, kexisBlock->debugBlockCount);
123 		// combine assembly and bitbucket and put it in the out stream;
124 		kexisBlock->data[kexisBlock->dataPosition] =
125 			kexisBlock->bitBucket | assembly;
126 		//print_bits(kexisBlock->data[kexisBlock->dataPosition], 32,
127 		//kexisBlock->debugBlockCount);
128 		// adjsut the  data Position;
129 		kexisBlock->dataPosition++;
130 		// If the stream is full, dump it to disk.
131 		if(kexisBlock->dataPosition == options->frameSize/2){
132 			write_kexisblock(options, kexisBlock, pcmBlock);
133 			kexisBlock->dataPosition = 0;
134 		}
135 
136 		// put in the data again.
137 		assembly = outBits;
138 		//print_bits(assembly, 32, kexisBlock->debugBlockCount);
139 		// mask out the front most bits we have already saved.
140 		assembly &= ((1<<(length - (32-kexisBlock->bitCounter))) -1);
141 		//print_bits(assembly, 32, kexisBlock->debugBlockCount);
142 		// shift it all the way to the front
143 		assembly <<= (32 - (length - (32-kexisBlock->bitCounter)));
144 		//print_bits(assembly, 32, kexisBlock->debugBlockCount);
145 		// transfer it into bit bucket.
146 		kexisBlock->bitBucket = assembly;
147 		//print_bits(kexisBlock->bitBucket, 32, kexisBlock->debugBlockCount);
148 		// increment bit kexisBlock->debugBlockCounter;
149 		kexisBlock->bitCounter = length - (32 - kexisBlock->bitCounter);
150 	}
151 }
152 
cleanup_bits(KEXISBLOCKSTRUCT * kexisBlock,OPTIONSTRUCT * options,PCMBLOCKSTRUCT * pcmBlock)153 void cleanup_bits(KEXISBLOCKSTRUCT *kexisBlock, OPTIONSTRUCT *options,
154 	PCMBLOCKSTRUCT *pcmBlock)
155 {
156 
157 	kexisBlock->data[kexisBlock->dataPosition] = kexisBlock->bitBucket;
158 	kexisBlock->dataPosition++;
159 
160 	write_kexisblock(options, kexisBlock, pcmBlock);
161 }
162 
bit_suck(KEXISBLOCKSTRUCT * kexisBlock,long len,PCMBLOCKSTRUCT * pcmBlock,OPTIONSTRUCT * options)163 long bit_suck(KEXISBLOCKSTRUCT *kexisBlock, long len, PCMBLOCKSTRUCT *pcmBlock,
164 	OPTIONSTRUCT *options)
165 {
166 	unsigned long holdData=0;
167 	unsigned long holdData2=0;
168 	size_t holdRead;
169 
170 	//if(DEBUG==1 && (kexisBlock->debugBlockCount>DEBUG_POS-DEBUG_DOWN && kexisBlock->debugBlockCount<DEBUG_POS+DEBUG_UP))
171     //printf("sub: %ld, Length: %ld Count: %ld\n", kexisBlock->subBlockPointer,
172 			//len, kexisBlock->debugBlockCount);
173 	// check and see if we the data we need is gonna be past a boundry.
174 	if(kexisBlock->subBlockPointer + len < 32) {
175 		// assign holdData
176 		holdData = kexisBlock->data[kexisBlock->blockPointer];
177 		//print_bits(holdData, 32, kexisBlock->debugBlockCount);
178 		//shift the bits we want all the way to the right
179 		holdData >>= (32 - (kexisBlock->subBlockPointer + len));
180 		//print_bits(holdData, 32, kexisBlock->debugBlockCount);
181 		// mask those bits.
182 		holdData &= ((1<<len) -1);
183 		//print_bits(holdData, 32, kexisBlock->debugBlockCount);
184 		// increment our kexisBlock->debugBlockCounters.
185 		kexisBlock->subBlockPointer += len;
186 		// return it
187 		return holdData;
188 	}
189 	else if(kexisBlock->subBlockPointer + len == 32) {
190 		// assign holdData
191 		holdData = kexisBlock->data[kexisBlock->blockPointer];
192 		//print_bits(holdData, 32, kexisBlock->debugBlockCount);
193 		//shift the bits we want all the way to the right
194 		holdData >>= (32 - (kexisBlock->subBlockPointer + len));
195 		//print_bits(holdData, 32, kexisBlock->debugBlockCount);
196 		// mask those bits.
197 		holdData &= ((1<<len) -1);
198 		//print_bits(holdData, 32, kexisBlock->debugBlockCount);
199 		// increment subblock.
200 		kexisBlock->subBlockPointer =0;
201 		kexisBlock->blockPointer++;
202 		// see if we need to read in more date.
203 		if(kexisBlock->blockPointer == (options->frameSize/2)){
204 			holdRead = fread(kexisBlock->data, sizeof(long), options->frameSize/2,
205 				options->inFileStream);
206 			if(holdRead <= 0) {
207 				sprintf(options->errorString, "In Error reading from %s!",
208 					options->inFileName);
209 				 handle_error(options);
210 			}
211 			kexisBlock->blockPointer=0;
212 		}
213 
214 		return holdData;
215 	}
216 	// else we need to cross a boundry
217 	else {
218 		// assign holdData
219 		holdData = kexisBlock->data[kexisBlock->blockPointer];
220 		//print_bits(holdData, 32, kexisBlock->debugBlockCount);
221 		// mask lowest bits we need only.
222 		holdData &= ((1<<(32 - kexisBlock->subBlockPointer)) -1);
223 		//print_bits(holdData, 32, kexisBlock->debugBlockCount);
224 		//shift em left. to make room for the remainder.
225 		holdData <<= (len-(32-kexisBlock->subBlockPointer));
226 		//print_bits(holdData, 32, kexisBlock->debugBlockCount);
227 
228 		kexisBlock->blockPointer++;
229 		// read in more data if we need it.
230 		if(kexisBlock->blockPointer == (options->frameSize/2)){
231 			holdRead = fread(kexisBlock->data, sizeof(long), options->frameSize/2,
232 				options->inFileStream);
233 			if(holdRead <= 0) {
234 				sprintf(options->errorString, "In Error reading from %s!",
235 					options->inFileName);
236 				handle_error(options);
237 			}
238 			kexisBlock->blockPointer=0;
239 		}
240 
241 		// grab the second word.
242 		holdData2 = kexisBlock->data[kexisBlock->blockPointer];
243 		//print_bits(holdData2, 32, kexisBlock->debugBlockCount);
244 		//shift the part we want all the way from the left to teh right.
245 		holdData2 >>= (32 - (len - (32 - kexisBlock->subBlockPointer)));
246 		//print_bits(holdData2, 32, kexisBlock->debugBlockCount);
247 		// mask out any bits we dont need.
248 		holdData2 &= ((1<<(len -(32 - kexisBlock->subBlockPointer))) -1);
249 		//print_bits(holdData2, 32, kexisBlock->debugBlockCount);
250 		// combine the two together.
251 		holdData = holdData | holdData2;
252 		//print_bits(holdData, 32, kexisBlock->debugBlockCount);
253 		// increment the sub block pointer.
254 		kexisBlock->subBlockPointer = len - (32 - kexisBlock->subBlockPointer);
255 		return holdData;
256 	}
257 }
258