blob: 6be836a1e492247ffd4a3ee6aca8153f0032b3b8 [file] [log] [blame]
/* Copyright (C) 2002 Jean-Marc Valin
File: speex_bits.c
Handles bit packing/unpacking
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "speex_bits.h"
#include <stdio.h>
#include <stdlib.h>
void speex_bits_init(SpeexBits *bits)
{
int i;
for (i=0;i<MAX_BYTES_PER_FRAME;i++)
bits->bytes[i]=0;
bits->nbBits=0;
bits->bytePtr=0;
bits->bitPtr=0;
}
void speex_bits_destroy(SpeexBits *bits)
{
/* Will do something once the allocation is dynamic */
}
void speex_bits_reset(SpeexBits *bits)
{
int i;
for (i=0;i<MAX_BYTES_PER_FRAME;i++)
bits->bytes[i]=0;
bits->nbBits=0;
bits->bytePtr=0;
bits->bitPtr=0;
}
void speex_bits_rewind(SpeexBits *bits)
{
bits->bytePtr=0;
bits->bitPtr=0;
}
void speex_bits_read_from(SpeexBits *bits, char *bytes, int len)
{
int i;
if (len > MAX_BYTES_PER_FRAME)
{
fprintf (stderr, "Trying to init frame with too many bits");
exit(1);
}
for (i=0;i<len;i++)
bits->bytes[i]=bytes[i];
bits->nbBits=len<<3;
bits->bytePtr=0;
bits->bitPtr=0;
}
void speex_bits_flush(SpeexBits *bits)
{
int i;
if (bits->bytePtr>0)
{
for (i=bits->bytePtr;i<((bits->nbBits+7)>>3);i++)
bits->bytes[i-bits->bytePtr]=bits->bytes[i];
}
bits->nbBits -= bits->bytePtr<<3;
bits->bytePtr=0;
}
void speex_bits_read_whole_bytes(SpeexBits *bits, char *bytes, int len)
{
int i,pos;
speex_bits_flush(bits);
pos=bits->nbBits>>3;
for (i=0;i<len;i++)
bits->bytes[pos+i]=bytes[i];
bits->nbBits+=len<<3;
}
int speex_bits_write(SpeexBits *bits, char *bytes, int max_len)
{
int i;
if (max_len > ((bits->nbBits+7)>>3))
max_len = ((bits->nbBits+7)>>3);
for (i=0;i<max_len;i++)
bytes[i]=bits->bytes[i];
return max_len;
}
int speex_bits_write_whole_bytes(SpeexBits *bits, char *bytes, int max_len)
{
int i;
if (max_len > ((bits->nbBits)>>3))
max_len = ((bits->nbBits)>>3);
for (i=0;i<max_len;i++)
bytes[i]=bits->bytes[i];
if (bits->bitPtr>0)
bits->bytes[0]=bits->bytes[max_len];
else
bits->bytes[0]=0;
for (i=1;i<((bits->nbBits)>>3)+1;i++)
bits->bytes[i]=0;
bits->bytePtr=0;
bits->nbBits &= 7;
return max_len;
}
void speex_bits_pack(SpeexBits *bits, int data, int nbBits)
{
unsigned int d=data;
while(nbBits)
{
int bit;
bit = (d>>(nbBits-1))&1;
bits->bytes[bits->bytePtr] |= bit<<(7-bits->bitPtr);
bits->bitPtr++;
/*fprintf(stderr, "%d %d\n", nbBits, bit);*/
if (bits->bitPtr==8)
{
bits->bitPtr=0;
bits->bytePtr++;
}
bits->nbBits++;
nbBits--;
}
}
int speex_bits_unpack_signed(SpeexBits *bits, int nbBits)
{
unsigned int d=speex_bits_unpack_unsigned(bits,nbBits);
/* If number is negative */
if (d>>(nbBits-1))
{
d |= (-1)<<nbBits;
}
return d;
}
unsigned int speex_bits_unpack_unsigned(SpeexBits *bits, int nbBits)
{
unsigned int d=0;
while(nbBits)
{
d<<=1;
d |= (bits->bytes[bits->bytePtr]>>(7-bits->bitPtr))&1;
bits->bitPtr++;
if (bits->bitPtr==8)
{
bits->bitPtr=0;
bits->bytePtr++;
}
nbBits--;
}
return d;
}