Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Experimental index optimised direct VQ #42

Merged
merged 12 commits into from
Apr 19, 2022
Merged
39 changes: 39 additions & 0 deletions .github/workflows/cmake.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: CMake

on: [pull_request]

env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: Debug

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2

- name: Install packages
shell: bash
run: |
sudo apt-get update
sudo apt-get install octave octave-common octave-signal gnuplot sox p7zip-full

- name: Build codec2
shell: bash
run: |
git clone https://github.com/drowe67/codec2.git
cd codec2 && mkdir -p build_linux && cd build_linux
cmake ..
make
pwd

- name: Build LPCNet
shell: bash
run: |
mkdir -p build_linux && cd build_linux
cmake -DCODEC2_BUILD_DIR=$GITHUB_WORKSPACE/codec2/build_linux ..
make
# simple test to make sure the code runs
cd src && sox ../../wav/wia.wav -t raw -r 16000 - | ./lpcnet_enc -s | ./lpcnet_dec -s > /dev/null

40 changes: 0 additions & 40 deletions .travis.yml

This file was deleted.

6 changes: 6 additions & 0 deletions src/4stage_direct_split_indopt_vq.c

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ set(lpcnet_freedv_srcs
lpcnet_dump.c
4stage_pred_vq.c
4stage_direct_split_vq.c
4stage_direct_split_indopt_vq.c
lpcnet.c
lpcnet_freedv.c
nnet.c
nnet_rw.c
${lpcnet_SOURCE_DIR}/nnet_data.c
)

Expand Down Expand Up @@ -48,7 +48,7 @@ export(TARGETS lpcnetfreedv
add_executable(dump_data dump_data.c)
target_link_libraries(dump_data lpcnetfreedv m codec2)

add_executable(test_lpcnet test_lpcnet.c)
add_executable(test_lpcnet test_lpcnet.c nnet_rw.c)
target_link_libraries(test_lpcnet lpcnetfreedv m codec2)

if(SSE OR AVX OR AVX2 OR CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64")
Expand Down Expand Up @@ -91,13 +91,13 @@ target_link_libraries(quant_dec lpcnetfreedv m codec2)
add_executable(lpcnet_enc lpcnet_enc.c)
target_link_libraries(lpcnet_enc lpcnetfreedv m codec2)

add_executable(lpcnet_dec lpcnet_dec.c)
add_executable(lpcnet_dec lpcnet_dec.c nnet_rw.c)
target_link_libraries(lpcnet_dec lpcnetfreedv m codec2)

add_executable(idct idct.c)
target_link_libraries(idct lpcnetfreedv m codec2)

add_executable(nnet2f32 nnet2f32.c)
add_executable(nnet2f32 nnet2f32.c nnet_rw.c)
target_link_libraries(nnet2f32 lpcnetfreedv m)

add_executable(sw2packedulaw sw2packedulaw.c)
Expand Down
5 changes: 1 addition & 4 deletions src/lpcnet.c
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,7 @@ void lpcnet_destroy(LPCNetState *lpcnet)

void lpcnet_open_test_file(LPCNetState *lpcnet, char file_name[]) {
lpcnet->ftest = fopen(file_name, "wb");
if (lpcnet->ftest == NULL) {
fprintf(stderr, "Error opening LPCNet test file: %s\n", file_name);
exit(1);
}
assert(lpcnet->ftest != NULL);
}

void lpcnet_set_preemph(LPCNetState *lpcnet, float preemph) {
Expand Down
42 changes: 31 additions & 11 deletions src/lpcnet_dec.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,9 @@ int main(int argc, char **argv) {
int *m = pred_m;
float *vq = pred_vq;
int logmag = 0;
int direct_split = 0;

int vq_type = LPCNET_PRED;
int ber_st=0, ber_en=-1;

fin = stdin;
fout = stdout;

Expand All @@ -72,20 +73,23 @@ int main(int argc, char **argv) {
{"infile", required_argument, 0, 'i'},
{"outfile", required_argument, 0, 'u'},
{"ber", required_argument, 0, 'b'},
{"ber_st", required_argument, 0, 'c'},
{"ber_en", required_argument, 0, 'e'},
{"decimate", required_argument, 0, 'd'},
{"nnet", required_argument, 0, 'r'},
{"numstages", required_argument, 0, 'n'},
{"pitchquant", required_argument, 0, 'o'},
{"pred", required_argument, 0, 'p'},
{"directsplit", no_argument, 0, 's'},
{"split", no_argument, 0, 's'},
{"indexopt", no_argument, 0, 'x'},
{"verbose", no_argument, 0, 'v'},
{0, 0, 0, 0}
};

int c;
int opt_index = 0;

while ((c = getopt_long (argc, argv, "b:d:n:o:p:svi:u:r:", long_options, &opt_index)) != -1) {
while ((c = getopt_long (argc, argv, "b:c:e:d:n:o:p:sxvi:u:r:", long_options, &opt_index)) != -1) {
switch (c) {
case 'i':
if ((fin = fopen(optarg, "rb")) == NULL) {
Expand All @@ -103,10 +107,16 @@ int main(int argc, char **argv) {
ber = atof(optarg);
fprintf(stderr, "BER = %f\n", ber);
break;
case 'c':
ber_st = atoi(optarg);
break;
case 'd':
dec = atoi(optarg);
fprintf(stderr, "dec = %d\n", dec);
break;
case 'e':
ber_en = atoi(optarg);
break;
case 'n':
num_stages = atoi(optarg);
fprintf(stderr, "%d VQ stages\n", num_stages);
Expand All @@ -124,15 +134,23 @@ int main(int argc, char **argv) {
nnet_read(optarg);
break;
case 's':
direct_split = 1; m = direct_split_m; vq = direct_split_vq; pred = 0.0; logmag = 1; weight = 1.0;
fprintf(stderr, "split VQ\n");
vq_type = LPCNET_DIRECT_SPLIT;
m = direct_split_m; vq = direct_split_vq; pred = 0.0; logmag = 1; weight = 1.0;
fprintf(stderr, "direct split VQ\n");
break;
case 'x':
vq_type = LPCNET_DIRECT_SPLIT_INDEX_OPT;
m = direct_split_indopt_m; vq = direct_split_indopt_vq; pred = 0.0; logmag = 1; weight = 1.0;
fprintf(stderr, "index optimised direct split VQ\n");
break;
case 'v':
lpcnet_verbose = 1;
break;
default:
fprintf(stderr,"usage: %s [Options]:\n", argv[0]);
fprintf(stderr," [-b --ber BER]\n");
fprintf(stderr," [--ber_st bit Bit in frame where we start inserting errors (default 0)]\n");
fprintf(stderr," [--ber_en bit Bit in frame just after we stop inserting errors (default 51)]\n");
fprintf(stderr," [-d --decimation 1/2/3...]\n");
fprintf(stderr," [-n --numstages]\n [-o --pitchbits nBits]\n");
fprintf(stderr," [-p --pred predCoff]\n");
Expand All @@ -142,7 +160,7 @@ int main(int argc, char **argv) {
}
}

LPCNetFreeDV *lf = lpcnet_freedv_create(direct_split);
LPCNetFreeDV *lf = lpcnet_freedv_create(vq_type);
lpcnet_open_test_file(lf->net, "test_lpcnet_statesq.f32");
LPCNET_QUANT *q = lf->q;

Expand All @@ -161,14 +179,15 @@ int main(int argc, char **argv) {
char frame[q->bits_per_frame];
int bits_read = 0;
short pcm[lpcnet_samples_per_frame(lf)];

if (ber_en == -1) ber_en = q->bits_per_frame-1;

do {

bits_read = fread(frame, sizeof(char), q->bits_per_frame, fin);
nbits += bits_read;
nbits += ber_en - ber_st;
if (ber != 0.0) {
int i;
for(i=0; i<q->bits_per_frame; i++) {
for(i=ber_st; i<=ber_en; i++) {
float r = (float)rand()/RAND_MAX;
if (r < ber) {
frame[i] = (frame[i] ^ 1) & 0x1;
Expand All @@ -190,6 +209,7 @@ int main(int argc, char **argv) {
lpcnet_freedv_destroy(lf);

if (ber != 0.0)
fprintf(stderr, "nbits: %d nerr: %d BER: %4.3f\n", nbits, nerrs, (float)nerrs/nbits);
fprintf(stderr, "ber_st: %d ber_en: %d nbits: %d nerr: %d BER: %4.3f\n", ber_st, ber_en,
nbits, nerrs, (float)nerrs/nbits);
return 0;
}
22 changes: 15 additions & 7 deletions src/lpcnet_enc.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ int main(int argc, char **argv) {
int *m = pred_m;
float *vq = pred_vq;
int logmag = 0;
int direct_split = 0;
int vq_type = LPCNET_PRED;

fin = stdin;
fout = stdout;
Expand All @@ -70,15 +70,16 @@ int main(int argc, char **argv) {
{"numstages", required_argument, 0, 'n'},
{"pitchquant", required_argument, 0, 'o'},
{"pred", required_argument, 0, 'p'},
{"directsplit", no_argument, 0, 's'},
{"split", no_argument, 0, 's'},
{"indexopt", no_argument, 0, 'x'},
{"verbose", no_argument, 0, 'v'},
{0, 0, 0, 0}
};

int c;
int opt_index = 0;

while ((c = getopt_long (argc, argv, "d:n:o:p:svi:u:", long_options, &opt_index)) != -1) {
while ((c = getopt_long (argc, argv, "d:n:o:p:sxvi:u:", long_options, &opt_index)) != -1) {
switch (c) {
case 'i':
if ((fin = fopen(optarg, "rb")) == NULL) {
Expand Down Expand Up @@ -109,9 +110,14 @@ int main(int argc, char **argv) {
fprintf(stderr, "pred = %f\n", pred);
break;
case 's':
direct_split = 1;
vq_type = LPCNET_DIRECT_SPLIT;
m = direct_split_m; vq = direct_split_vq; pred = 0.0; logmag = 1; weight = 1.0;
fprintf(stderr, "split VQ\n");
fprintf(stderr, "direct split VQ\n");
break;
case 'x':
vq_type = LPCNET_DIRECT_SPLIT_INDEX_OPT;
m = direct_split_indopt_m; vq = direct_split_indopt_vq; pred = 0.0; logmag = 1; weight = 1.0;
fprintf(stderr, "index optimised direct split VQ\n");
break;
case 'v':
lpcnet_verbose = 1;
Expand All @@ -120,13 +126,15 @@ int main(int argc, char **argv) {
fprintf(stderr,"usage: %s [Options]:\n [-d --decimation 1/2/3...]\n", argv[0]);
fprintf(stderr," [-i --infile]\n [-u --outfile]\n");
fprintf(stderr," [-n --numstages]\n [-o --pitchbits nBits]\n");
fprintf(stderr," [-p --pred predCoff] [-s --split]\n");
fprintf(stderr," [-p --pred predCoff] Predictive quantiser prediction coeff\n");
fprintf(stderr," [-s --directsplit] Use direct split quaniser\n");
fprintf(stderr," [-x --indexopt] Use index optimised direct split quantiser\n");
fprintf(stderr," [-v --verbose]\n");
exit(1);
}
}

LPCNetFreeDV *lf = lpcnet_freedv_create(direct_split);
LPCNetFreeDV *lf = lpcnet_freedv_create(vq_type);
LPCNET_QUANT *q = lf->q;

q->weight = weight; q->pred = pred; q->mbest = mbest_survivors;
Expand Down
7 changes: 6 additions & 1 deletion src/lpcnet_freedv.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,14 @@
extern "C" {
#endif

// possible vq_type values in lpcnet_freedv_create()
#define LPCNET_PRED 0
#define LPCNET_DIRECT_SPLIT 1
#define LPCNET_DIRECT_SPLIT_INDEX_OPT 2

typedef struct LPCNetFreeDV LPCNetFreeDV;

LPCNetFreeDV* lpcnet_freedv_create(int direct_split);
LPCNetFreeDV* lpcnet_freedv_create(int vq_type);
void lpcnet_freedv_destroy(LPCNetFreeDV *lf);
void lpcnet_enc(LPCNetFreeDV *lf, short *pcm, char *frame);
void lpcnet_dec(LPCNetFreeDV *lf, char *frame, short* pcm);
Expand Down
32 changes: 27 additions & 5 deletions src/lpcnet_quant.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,24 @@ int lpcnet_verbose = 0;

static int quantise(const float * cb, float vec[], float w[], int k, int m, float *se);

LPCNET_QUANT *lpcnet_quant_create(int direct_split) {
LPCNET_QUANT *lpcnet_quant_create(int vq_type) {
assert((vq_type == LPCNET_PRED) || (vq_type == LPCNET_DIRECT_SPLIT) ||
(vq_type == LPCNET_DIRECT_SPLIT_INDEX_OPT));
LPCNET_QUANT *q = (LPCNET_QUANT*)malloc(sizeof(LPCNET_QUANT));
if (q == NULL) return NULL;
if (direct_split) {
if ((vq_type == LPCNET_DIRECT_SPLIT) || (vq_type == LPCNET_DIRECT_SPLIT_INDEX_OPT)) {
q->weight = 1.0; q->pred = 0.0;
q->mbest = DEFAULT_MBEST; q->pitch_bits = DEFAULT_PITCH_BITS; q->dec = DEFAULT_DEC;
q->num_stages = direct_split_num_stages; q->vq = direct_split_vq; q->m = direct_split_m; q->logmag = 1;
q->logmag = 1;
if (vq_type == LPCNET_DIRECT_SPLIT) {
q->num_stages = direct_split_num_stages;
q->m = direct_split_m;
q->vq = direct_split_vq;
} else {
q->num_stages = direct_split_indopt_num_stages;
q->m = direct_split_indopt_m;
q->vq = direct_split_indopt_vq;
}
}
else {
q->weight = DEFAULT_WEIGHT; q->pred = DEFAULT_PRED;
Expand Down Expand Up @@ -125,7 +136,8 @@ void quant_pred_mbest(float vec_out[],
int num_stages,
float vq[],
int m[], int k,
int mbest_survivors)
int mbest_survivors,
float ber)
{
float err[k], w[k], se1;
int i,j,s,s1,ind;
Expand Down Expand Up @@ -194,6 +206,16 @@ void quant_pred_mbest(float vec_out[],
if (lpcnet_fsv != NULL) fprintf(lpcnet_fsv, "%f\t%f\t", vec_in[0],sqrt(se1));
if (lpcnet_verbose) fprintf(stderr, " se1: %f\n", se1);

if (ber > 0.0) {
/* optionally insert random errors in indexes to test index optimisation */
for (s=0; s<num_stages; s++) {
int log2m = roundf(log2(m[s]));
for(int b=0; b<log2m; b++)
if ((float)rand()/RAND_MAX < ber)
indexes[s] ^= 1<<b;
}
}

quant_pred_output(vec_out, indexes, err, pred, num_stages, vq, k);

for(i=0; i<num_stages; i++)
Expand Down Expand Up @@ -365,7 +387,7 @@ int lpcnet_features_to_frame(LPCNET_QUANT *q, float features[], char frame[]) {

/* non-interpolated frame ----------------------------------------*/

quant_pred_mbest(q->features_quant, indexes, features, q->pred, q->num_stages, q->vq, q->m, k, q->mbest);
quant_pred_mbest(q->features_quant, indexes, features, q->pred, q->num_stages, q->vq, q->m, k, q->mbest, 0.0);
pitch_ind = pitch_encode(features[2*NB_BANDS], q->pitch_bits);
pitch_gain_ind = pitch_gain_encode(features[2*NB_BANDS+1]);
pack_frame(q->num_stages, q->m, indexes, q->pitch_bits, pitch_ind, pitch_gain_ind, frame);
Expand Down
Loading