Stack allocation cleanup...
[speexdsp.git] / libspeex / bits.c
1 /* Copyright (C) 2002 Jean-Marc Valin 
2    File: speex_bits.c
3
4    Handles bit packing/unpacking
5
6    Redistribution and use in source and binary forms, with or without
7    modification, are permitted provided that the following conditions
8    are met:
9    
10    - Redistributions of source code must retain the above copyright
11    notice, this list of conditions and the following disclaimer.
12    
13    - Redistributions in binary form must reproduce the above copyright
14    notice, this list of conditions and the following disclaimer in the
15    documentation and/or other materials provided with the distribution.
16    
17    - Neither the name of the Xiph.org Foundation nor the names of its
18    contributors may be used to endorse or promote products derived from
19    this software without specific prior written permission.
20    
21    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24    A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
25    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
33 */
34
35 #include "speex_bits.h"
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include "misc.h"
39
40 void speex_bits_init(SpeexBits *bits)
41 {
42    int i;
43    bits->bytes = speex_alloc(MAX_BYTES_PER_FRAME);
44
45    for (i=0;i<MAX_BYTES_PER_FRAME;i++)
46       bits->bytes[i]=0;
47    bits->nbBits=0;
48    bits->bytePtr=0;
49    bits->bitPtr=0;
50    bits->owner=1;
51 }
52
53 void speex_bits_init_buffer(SpeexBits *bits, void *buff)
54 {
55    int i;
56    bits->bytes = buff;
57
58    for (i=0;i<MAX_BYTES_PER_FRAME;i++)
59       bits->bytes[i]=0;
60    bits->nbBits=0;
61    bits->bytePtr=0;
62    bits->bitPtr=0;
63    bits->owner=0;
64 }
65
66 void speex_bits_destroy(SpeexBits *bits)
67 {
68    if (bits->owner)
69       speex_free(bits->bytes);
70    /* Will do something once the allocation is dynamic */
71 }
72
73 void speex_bits_reset(SpeexBits *bits)
74 {
75    int i;
76    for (i=0;i<MAX_BYTES_PER_FRAME;i++)
77       bits->bytes[i]=0;
78    bits->nbBits=0;
79    bits->bytePtr=0;
80    bits->bitPtr=0;
81 }
82
83 void speex_bits_rewind(SpeexBits *bits)
84 {
85    bits->bytePtr=0;
86    bits->bitPtr=0;
87 }
88
89 void speex_bits_read_from(SpeexBits *bits, char *bytes, int len)
90 {
91    int i;
92    if (len > MAX_BYTES_PER_FRAME)
93    {
94       fprintf (stderr, "Trying to init frame with too many bits");
95       exit(1);
96    }
97    for (i=0;i<len;i++)
98       bits->bytes[i]=bytes[i];
99    bits->nbBits=len<<3;
100    bits->bytePtr=0;
101    bits->bitPtr=0;
102 }
103
104 void speex_bits_flush(SpeexBits *bits)
105 {
106    int i;
107    if (bits->bytePtr>0)
108    {
109       for (i=bits->bytePtr;i<((bits->nbBits+7)>>3);i++)
110          bits->bytes[i-bits->bytePtr]=bits->bytes[i];
111    }
112    bits->nbBits -= bits->bytePtr<<3;
113    bits->bytePtr=0;
114 }
115
116 void speex_bits_read_whole_bytes(SpeexBits *bits, char *bytes, int len)
117 {
118    int i,pos;
119    speex_bits_flush(bits);
120    pos=bits->nbBits>>3;
121    for (i=0;i<len;i++)
122       bits->bytes[pos+i]=bytes[i];
123    bits->nbBits+=len<<3;
124 }
125
126 int speex_bits_write(SpeexBits *bits, char *bytes, int max_len)
127 {
128    int i;
129    if (max_len > ((bits->nbBits+7)>>3))
130       max_len = ((bits->nbBits+7)>>3);
131    for (i=0;i<max_len;i++)
132       bytes[i]=bits->bytes[i];
133    return max_len;
134 }
135
136 int speex_bits_write_whole_bytes(SpeexBits *bits, char *bytes, int max_len)
137 {
138    int i;
139    if (max_len > ((bits->nbBits)>>3))
140       max_len = ((bits->nbBits)>>3);
141    for (i=0;i<max_len;i++)
142       bytes[i]=bits->bytes[i];
143    
144    if (bits->bitPtr>0)
145       bits->bytes[0]=bits->bytes[max_len];
146    else
147       bits->bytes[0]=0;
148    for (i=1;i<((bits->nbBits)>>3)+1;i++)
149       bits->bytes[i]=0;
150    bits->bytePtr=0;
151    bits->nbBits &= 7;
152    return max_len;
153 }
154
155
156 void speex_bits_pack(SpeexBits *bits, int data, int nbBits)
157 {
158    unsigned int d=data;
159    while(nbBits)
160    {
161       int bit;
162       bit = (d>>(nbBits-1))&1;
163       bits->bytes[bits->bytePtr] |= bit<<(7-bits->bitPtr);
164       bits->bitPtr++;
165       /*fprintf(stderr, "%d %d\n", nbBits, bit);*/
166       if (bits->bitPtr==8)
167       {
168          bits->bitPtr=0;
169          bits->bytePtr++;
170       }
171       bits->nbBits++;
172       nbBits--;
173    }
174 }
175
176 int speex_bits_unpack_signed(SpeexBits *bits, int nbBits)
177 {
178    unsigned int d=speex_bits_unpack_unsigned(bits,nbBits);
179    /* If number is negative */
180    if (d>>(nbBits-1))
181    {
182       d |= (-1)<<nbBits;
183    }
184    return d;
185 }
186
187 unsigned int speex_bits_unpack_unsigned(SpeexBits *bits, int nbBits)
188 {
189    unsigned int d=0;
190    while(nbBits)
191    {
192       d<<=1;
193       d |= (bits->bytes[bits->bytePtr]>>(7-bits->bitPtr))&1;
194       bits->bitPtr++;
195       if (bits->bitPtr==8)
196       {
197          bits->bitPtr=0;
198          bits->bytePtr++;
199       }
200       nbBits--;
201    }
202    return d;
203 }
204
205 unsigned int speex_bits_peek_unsigned(SpeexBits *bits, int nbBits)
206 {
207    unsigned int d=0;
208    int bitPtr, bytePtr;
209    char *bytes;
210    bitPtr=bits->bitPtr;
211    bytePtr=bits->bytePtr;
212    bytes = bits->bytes;
213    while(nbBits)
214    {
215       d<<=1;
216       d |= (bytes[bytePtr]>>(7-bitPtr))&1;
217       bitPtr++;
218       if (bitPtr==8)
219       {
220          bitPtr=0;
221          bytePtr++;
222       }
223       nbBits--;
224    }
225    return d;
226 }
227
228 int speex_bits_peek(SpeexBits *bits)
229 {
230    return (bits->bytes[bits->bytePtr]>>(7-bits->bitPtr))&1;
231 }
232
233 void speex_bits_advance(SpeexBits *bits, int n)
234 {
235    int nbytes, nbits;
236    nbytes = n >> 3;
237    nbits = n & 7;
238    
239    bits->bytePtr += nbytes;
240    bits->bitPtr += nbits;
241    
242    if (bits->bitPtr>7)
243    {
244       bits->bitPtr-=8;
245       bits->bytePtr++;
246    }
247 }
248
249 int speex_bits_nbytes(SpeexBits *bits)
250 {
251    return ((bits->nbBits+7)>>3);
252 }