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