Flare skrev:
>Jeg (vi) er ved at lave et codec i C++. Dette indebærer at noget informtion
>skal gemmes i 2 - 16 bit alt afhængih af forholdene.
>Codec'et gemmer i et frameformat med følgende struktur:
>[12x1bit][25x4bit][25x4bit][data skrevet med 2 - 16 bit]
>En lang række af disse frames skal skrives til en fil efter hinanden. Men
>hvordan faen gør jeg dette?
>Hvilken metode vil være hensigtsmæssig at bruge. ? Og hvordan skrive jeg fx
>4 bit tallet 1011 til fil?
>Nogen ideer (erfaringer) hvordan man griber dette an?
Her er et program der kan gemme værdier helt tæt i en buffer. Det er på
kladdeniveau, men virker hvis man ikke stresser det. Det kan kun håndtere
positive tal (negative tal og tæt pakning rejser nogle problemer) og størrelser
under 30 bits.
Princippet er at man pakker en stribe tal med stuff(bits,value). Bagefter
kan de pakkes ud med retrieve(bits). Både pakning og hentning skal
foregå i ´rækkefølge.
Jeg vil dog ikke specielt anbefale det fordi de fordele det giver, næppe
opvejer ulemperne. Forestil dig f.eks min skuffelse da jeg i en måneds tid
havde finpudset et primtalsprogram der kunne pakke alle primtal op til 22 mio.
på en almindelig floppy (Erathostenes' si og bitpilleri), da jeg opdagede at
en zipning af en banal liste fyldte lige så lidt.
Programmet holder styr på positionerne ved hjælp af int pos_byte og pos_bit.
Så ved man hvor langt man er kommet i bytes og hvor mange bits deri der
allerede er optaget.
Bufferen er vilkårligt sat til 1000 byte, men kan naturligvis udvides efter behov.
Den kan så skrives til en fil når den er fyldt op, men det har jeg ikke kodet.
/* Buffer til opbevaring af værdier der spænder over et varierende antal bits.
Alle printsætninger uden for main() er i koden skrevet helt til venstre.
De bruges kun til kontrol og forklaring. Ligeså display().
Mulige katastrofer:
Der bruges ikke reset() før man henter data. Man vil da læse frem i en udefineret buffer.
Bitantallet ved hentning svarer ikke til antallet ved gemning.
Hentede data vil da være meningsløse fra første fejl og fremefter.
Negative tal kan ikke klares.
Der er ingen egentlig fejlhåndtering.
*/
#include <stdio.h>
// Bruges kun til testdata.
enum { ANTAL=4 };
// Testdata: (antal bits, værdi)
const int t[][2] = { {15,7}, {26,8}, {7,30}, {3,4} };
class Buffer {
public:
Buffer () { pos_byte=0, pos_bit=0; buff[0]=0; }
void stuff (const int &bits, int val);
void display ();
void reset () { pos_byte=0; pos_bit=0; };
int retrieve (const int &bits);
private:
int pos_byte, pos_bit;
unsigned char buff[1000];
};
void Buffer::stuff (const int &bits, int val) {
if (val<0) throw 1; // Primitiv fejlhåndtering.
if (bits>30) throw 2; // Undgår de værste katastrofer.
int max=1;
for (int b=0; b<bits; ++b) max*=2;
if (max<=val) throw 3;
printf("Val: %d ",val);
val<<=pos_bit;
printf("Skiftet val: %d Pos_bit: %d Pos_byte: %d\n",val,pos_bit,pos_byte);
buff[pos_byte]+=val & 0xFF;
pos_bit+=bits;
while (pos_bit>7) {
val/=256;
++pos_byte;
buff[pos_byte]=val & 0xFF;
pos_bit-=8;
}
}
void Buffer::display () { // Beregnet til kontrol.
int temp, mask;
for (int b=pos_byte; b>=0; --b) {
printf(" ");
temp=buff[b];
mask=128;
for (int n=0; n<8; ++n) {
if (temp & mask) printf("1");
else printf("0");
mask/=2;
}
}
printf("\n\n");
}
int Buffer::retrieve (const int &bits) {
unsigned int temp, mask=1;
int nr=pos_bit+bits, faktor=256;
printf("Pos_bit: %d Pos_byte: %d\n",pos_bit,pos_byte);
temp=buff[pos_byte];
while (nr>7) { ++pos_byte; nr-=8; temp+=buff[pos_byte]*faktor; faktor*=256; }
for (int n=0; n<pos_bit; ++n) temp/=2;
for (int n=1; n<bits; ++n) mask=mask*2+1;
printf("Bits: %d Maske: %d Temp: %d\n",bits,mask,temp);
pos_bit+=bits;
if (0 && pos_bit>7) {
pos_bit-=8;
++pos_byte;
}
pos_bit=nr;
return temp & mask;
}
int main () {
Buffer field;
for (int n=0; n<ANTAL; ++n) {
printf("(%d, %d) ",t[n][0],t[n][1]);
}
printf("\n\n");
for (int n=0; n<ANTAL; ++n) {
field.stuff(t[n][0],t[n][1]);
field.display();
}
field.reset();
for (int n=0; n<ANTAL; ++n) printf("Hentet: %d\n",field.retrieve(t[n][0]));
return 0;
}
--
Bertel
http://bertel.lundhansen.dk/ FIDUSO:
http://fiduso.dk/