Created
May 23, 2019 19:41
-
-
Save jkbonfield/65cd8c9d968acbe683f6f1e920c9a6a1 to your computer and use it in GitHub Desktop.
ONT signal compression
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <string.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <inttypes.h> | |
#ifndef MAXD | |
#define MAXD 15 | |
#endif | |
unsigned char *encode(unsigned char *data, uint64_t len, uint64_t *out_len) { | |
uint64_t i, j; | |
signed short *in = (signed short *)data; | |
unsigned char *out = malloc(len*2); | |
int p = 0; | |
len /= 2; | |
for (i = 0, j = 0; i < len; i++) { | |
int d = in[i]-p; | |
if (d >= -127 && d < 127) { | |
out[j++] = d; | |
} else { | |
out[j++] = -128; | |
d = (d<0) ? -d*2+1 : d*2; | |
out[j++] = d&0xff; | |
out[j++] = (d>>8)&0xff; | |
} | |
// Slight differences imply average with previous value to | |
// smooth out noise, while large differences imply a big jump | |
// so use this value as predictor. | |
if (d >= -MAXD && d <= MAXD) | |
p = (p + in[i])>>1; | |
else | |
p = in[i]; | |
} | |
*out_len = j; | |
return out; | |
} | |
unsigned char *decode(unsigned char *data, uint64_t len, uint64_t *out_len) { | |
uint64_t i = 0, j = 0; | |
signed char *in = (signed char *)data; | |
signed short *out = malloc(len*2); | |
int p = 0; | |
while (i < len) { | |
int d = in[i++]; | |
if (d == -128) { | |
d = (unsigned char)in[i++]; | |
d += ((unsigned char)in[i++])<<8; | |
d = (d&1) ? -(d>>1) : (d>>1); | |
} | |
out[j++] = d + p; | |
if (d >= -MAXD && d <= MAXD) | |
p = (p + out[j-1])>>1; | |
else | |
p = out[j-1]; | |
} | |
*out_len = j*2; | |
return (unsigned char *)out; | |
} | |
#define BS 1024*1024 | |
static unsigned char *load(uint64_t *lenp) { | |
unsigned char *data = NULL; | |
uint64_t dsize = 0; | |
uint64_t dcurr = 0; | |
signed int len; | |
do { | |
if (dsize - dcurr < BS) { | |
dsize = dsize ? dsize * 2 : BS; | |
data = realloc(data, dsize); | |
} | |
len = read(0, data + dcurr, BS); | |
if (len > 0) | |
dcurr += len; | |
} while (len > 0); | |
if (len == -1) { | |
perror("read"); | |
} | |
*lenp = dcurr; | |
return data; | |
} | |
int main(int argc, char **argv) { | |
uint64_t len; | |
unsigned char *in = load(&len), *out; | |
if (argc > 1 && strcmp(argv[1], "-d") == 0) { | |
out = decode(in, len, &len); | |
} else { | |
out = encode(in, len, &len); | |
} | |
if (write(1, out, len) != len) | |
abort(); | |
free(in); | |
free(out); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment