From 053a7bc70dcb864d162877b0b05ce90f9d02f9a0 Mon Sep 17 00:00:00 2001 From: David Date: Fri, 19 Jul 2019 07:00:27 +0930 Subject: [PATCH 01/20] building up Octave simulation of adaptive EQ --- octave/vq_700c_eq.m | 70 +++++++++++++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 21 deletions(-) diff --git a/octave/vq_700c_eq.m b/octave/vq_700c_eq.m index 8ecb317c..936470d1 100644 --- a/octave/vq_700c_eq.m +++ b/octave/vq_700c_eq.m @@ -46,6 +46,21 @@ function vq_700c_plots(fn_array) endfunction +% single stage vq a target matrix with adaptive EQ + +function [errors eqs] = vq_targets_adap_eq(vq, targets) + errors = []; [tmp K] = size(vq); gain=0.1; + eqs = []; eq = prev_eq = zeros(1,K); + for i=1:length(targets) + [mse_list index_list] = search_vq(vq, targets(i,:)-eq, 1); + error = targets(i,:) - eq - vq(index_list(1),:); + eq = (1-gain)*prev_eq + gain*error; + prev_eq = eq; + errors = [errors; error]; eqs = [eqs; eq]; + end +endfunction + + % two stage mbest vq a target matrix function [errors targets_] = vq_targets2(vq1, vq2, targets) @@ -54,6 +69,19 @@ function vq_700c_plots(fn_array) endfunction +% two stage mbest vq a target matrix, with adap_eq + +function [errors targets_] = vq_targets2_adap_eq(vq1, vq2, targets) + vqset(:,:,1)= vq1; vqset(:,:,2)=vq2; m=5; [tmp K] = size(targets); gain=0.1; + eq = zeros(1, K); errors = []; targets_ = []; + for i=1:length(targets) + [error target_ ] = mbest(vqset, targets(i,:)-eq, m); + eq = (1-gain)*eq + gain*error; + errors = [errors; error]; targets_ = [targets_; target_]; + end +endfunction + + % given target and vq matrices, estimate eq via two metrics function [eq1 eq2] = est_eq(vq, targets) @@ -103,14 +131,14 @@ function save_f32(fn, m) % VQ is in .txt file in this directory, we have two to choose from. train_120 is the Codec 2 700C VQ, % train_all_speech was trained up from a different, longer database, as a later exercise - #vq_name = "train_120"; - vq_name = "train_all_speech"; + vq_name = "train_120"; + #vq_name = "train_all_speech"; vq1 = load(sprintf("%s_1.txt", vq_name)); vq2 = load(sprintf("%s_2.txt", vq_name)); - printf("-------------------------------------------------------------------\n"); - printf("Sample Initial vqstg1 vqstg1_eq vqsgt2 vq2stg_eq\n"); - printf("-------------------------------------------------------------------\n"); + printf("----------------------------------------------------------------------------------\n"); + printf("Sample Initial vqs1 vqsg1_eq vq1_adapeq vqs2 vqs2_eq vqs2_adapeq \n"); + printf("----------------------------------------------------------------------------------\n"); fn_targets = {"hts1a" "hts2a" "cq_ref" "ve9qrp_10s" "vk5qi" "c01_01_8k" "ma01_01" "cq_freedv_8k"}; %fn_targets = {"hts1a"}; @@ -123,9 +151,11 @@ function save_f32(fn, m) % first stage VQ errors1 = vq_targets(vq1, targets); errors1_eq = vq_targets(vq1, targets-eq); + errors1_adap_eq = vq_targets_adap_eq(vq1, targets); % two stage mbest VQ [errors2 targets_] = vq_targets2(vq1, vq2, targets); [errors2_eq targets_eq_] = vq_targets2(vq1, vq2, targets-eq); + [errors2_adap_eq targets_eq_] = vq_targets2_adap_eq(vq1, vq2, targets); % save to .f32 files for listening tests if strcmp(vq_name,"train_120") @@ -135,9 +165,9 @@ function save_f32(fn, m) save_f32(sprintf("../script/%s_vq2_as.f32", fn_targets{i}), targets_); save_f32(sprintf("../script/%s_vq2_as_eq.f32", fn_targets{i}), targets_eq_); end - printf("%-17s %6.2f %6.2f %6.2f %6.2f %6.2f\n", fn_targets{i}, - var(targets(:)), var(errors1(:)), var(errors1_eq(:)), - var(errors2(:)), var(errors2_eq(:))); + printf("%-17s %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f\n", fn_targets{i}, + var(targets(:)), var(errors1(:)), var(errors1_eq(:)), var(errors1_adap_eq(:)), + var(errors2(:)), var(errors2_eq(:)), var(errors2_adap_eq(:))); end endfunction @@ -150,18 +180,15 @@ function interactive(fn_vq_txt, fn_target_f32) [targets e] = load_targets(fn_target_f32); hi_energy_frames = find(e>20); [eq1 eq2] = est_eq(vq, targets); - [eq1_hi eq2_hi] = est_eq(vq, targets(hi_energy_frames,:)); + [tmp adap_eq1] = vq_targets_adap_eq(vq, targets); figure(1); clf; mesh(e+targets) figure(2); clf; - plot(eq1,'b;eq1;') - hold on; - %plot(eq2,'g;eq2;'); - plot(eq1_hi,'r;eq1 hi;'); - %plot(eq2_hi,'c;eq2 hi;'); - hold off; - figure(3); clf; plot(e(:,1)) + %plot(eq1,'b;eq1;') + %hold on; plot(adap_eq1,'c;adap eq1;'); hold off; + mesh(adap_eq1); + figure(3); clf; plot(e(:,1)); title('Energy') % enter single step loop f = 20; neq = 0; eq=zeros(1,K); @@ -174,6 +201,7 @@ function interactive(fn_vq_txt, fn_target_f32) hold on; plot(e(f)+vq(index_list,:),'g;vq;'); plot(error,'r;error;'); + plot(eq,'c;eq;'); plot([1 K],[e(f) e(f)],'--') hold off; axis([1 K -20 80]) @@ -186,11 +214,11 @@ function interactive(fn_vq_txt, fn_target_f32) if k == 'n' f+=1; end if k == 'e' neq++; - if neq == 3 neq = 0; end - if neq == 0 eq = zeros(1,K); end - if neq == 1 eq = eq1; end - if neq == 2 eq = eq2; end end + if neq == 3 neq = 0; end + if neq == 0 eq = zeros(1,K); end + if neq == 1 eq = eq1; end + if neq == 2 eq = adap_eq1(f,:); end if k == 'b' f-=1; end until (k == 'q') printf("\n"); @@ -201,6 +229,6 @@ function interactive(fn_vq_txt, fn_target_f32) % choose one of these to run first % You'll need to run scripts/train_700C_quant.sh first to generate the .f32 files -interactive("train_120_1.txt", "cq_ref.f32") +interactive("train_120_1.txt", "vk5qi.f32") %table_across_samples; %vq_700c_plots({"hts1a.f32" "hts2a.f32" "ve9qrp_10s.f32" "ma01_01.f32" "train_120_1.txt"}) From 6b2981838965efb48cdb602ff3e6c2a5fe271841 Mon Sep 17 00:00:00 2001 From: David Date: Fri, 19 Jul 2019 12:15:50 +0930 Subject: [PATCH 02/20] adaptive eq experients, including contrived lfboost/hfcut experiments. lfboost sound much worse, and EQ has only a small effect --- octave/vq_700c_eq.m | 62 ++++++++++++++++++++++++++------------ script/train_700c_quant.sh | 19 ++++++++---- 2 files changed, 55 insertions(+), 26 deletions(-) diff --git a/octave/vq_700c_eq.m b/octave/vq_700c_eq.m index 936470d1..568dffa4 100644 --- a/octave/vq_700c_eq.m +++ b/octave/vq_700c_eq.m @@ -48,9 +48,9 @@ function vq_700c_plots(fn_array) % single stage vq a target matrix with adaptive EQ -function [errors eqs] = vq_targets_adap_eq(vq, targets) - errors = []; [tmp K] = size(vq); gain=0.1; - eqs = []; eq = prev_eq = zeros(1,K); +function [errors eqs] = vq_targets_adap_eq(vq, targets, eq) + errors = []; gain=0.02; + eqs = []; prev_eq = eq; for i=1:length(targets) [mse_list index_list] = search_vq(vq, targets(i,:)-eq, 1); error = targets(i,:) - eq - vq(index_list(1),:); @@ -61,7 +61,7 @@ function vq_700c_plots(fn_array) endfunction -% two stage mbest vq a target matrix +% two stage mbest VQ a target matrix function [errors targets_] = vq_targets2(vq1, vq2, targets) vqset(:,:,1)= vq1; vqset(:,:,2)=vq2; m=5; @@ -69,20 +69,24 @@ function vq_700c_plots(fn_array) endfunction -% two stage mbest vq a target matrix, with adap_eq +% two stage mbest VQ a target matrix, with adap_eq -function [errors targets_] = vq_targets2_adap_eq(vq1, vq2, targets) - vqset(:,:,1)= vq1; vqset(:,:,2)=vq2; m=5; [tmp K] = size(targets); gain=0.1; - eq = zeros(1, K); errors = []; targets_ = []; +function [errors targets_ eq] = vq_targets2_adap_eq(vq1, vq2, targets, eq) + vqset(:,:,1)= vq1; vqset(:,:,2)=vq2; m=5; gain=0.02; + errors = []; targets_ = []; for i=1:length(targets) - [error target_ ] = mbest(vqset, targets(i,:)-eq, m); - eq = (1-gain)*eq + gain*error; + t = targets(i,:)-eq; + [error target_ indexes] = mbest(vqset, t, m); + % use first stage VQ as error driving adaptive EQ + eq_error = t - vq1(indexes(1),:); + eq = (1-gain)*eq + gain*eq_error; errors = [errors; error]; targets_ = [targets_; target_]; end endfunction -% given target and vq matrices, estimate eq via two metrics +% Given target and vq matrices, estimate eq via two metrics. First +% metric seems to work best. Both uses first stage VQ error for EQ function [eq1 eq2] = est_eq(vq, targets) [ntargets K] = size(targets); @@ -140,34 +144,49 @@ function save_f32(fn, m) printf("Sample Initial vqs1 vqsg1_eq vq1_adapeq vqs2 vqs2_eq vqs2_adapeq \n"); printf("----------------------------------------------------------------------------------\n"); - fn_targets = {"hts1a" "hts2a" "cq_ref" "ve9qrp_10s" "vk5qi" "c01_01_8k" "ma01_01" "cq_freedv_8k"}; + fn_targets = { "cq_freedv_8k_lfboost" "cq_freedv_8k_hfcut" "cq_freedv_8k" "hts1a" "hts2a" "cq_ref" "ve9qrp_10s" "vk5qi" "c01_01_8k" "ma01_01"}; %fn_targets = {"hts1a"}; + figs=1; for i=1:length(fn_targets) % load target and estimate eq [targets e] = load_targets(fn_targets{i}); eq = est_eq(vq1, targets); - % first stage VQ + % first stage VQ ----------------- + errors1 = vq_targets(vq1, targets); errors1_eq = vq_targets(vq1, targets-eq); - errors1_adap_eq = vq_targets_adap_eq(vq1, targets); - % two stage mbest VQ + + % two passes to allow time for adaption, we use results from 2nd pas + [errors1_adap_eq eqs] = vq_targets_adap_eq(vq1, targets, zeros(1,K)); + errors1_adap_eq = vq_targets_adap_eq(vq1, targets, eqs(end,:)); + + % two stage mbest VQ -------------- + [errors2 targets_] = vq_targets2(vq1, vq2, targets); [errors2_eq targets_eq_] = vq_targets2(vq1, vq2, targets-eq); - [errors2_adap_eq targets_eq_] = vq_targets2_adap_eq(vq1, vq2, targets); + + % two passes to allow time for adaption, we use results from 2nd pass + [errors2_adap_eq targets_adap_eq_ eq] = vq_targets2_adap_eq(vq1, vq2, targets, zeros(1,K)); + [errors2_adap_eq targets_adap_eq_ eq] = vq_targets2_adap_eq(vq1, vq2, targets, eq); % save to .f32 files for listening tests if strcmp(vq_name,"train_120") save_f32(sprintf("../script/%s_vq2.f32", fn_targets{i}), targets_); save_f32(sprintf("../script/%s_vq2_eq.f32", fn_targets{i}), targets_eq_); + save_f32(sprintf("../script/%s_vq2_adap_eq.f32", fn_targets{i}), targets_adap_eq_); else save_f32(sprintf("../script/%s_vq2_as.f32", fn_targets{i}), targets_); save_f32(sprintf("../script/%s_vq2_as_eq.f32", fn_targets{i}), targets_eq_); end - printf("%-17s %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f\n", fn_targets{i}, + printf("%-21s %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f\n", fn_targets{i}, var(targets(:)), var(errors1(:)), var(errors1_eq(:)), var(errors1_adap_eq(:)), var(errors2(:)), var(errors2_eq(:)), var(errors2_adap_eq(:))); + + figure(figs++); + plot(var(errors2'),'b;vq;'); hold on; plot(var(errors2_eq'),'g;vq_eq;'); plot(var(errors2_adap_eq'),'r;adap_eq;'); hold off; + title(fn_targets{i}); end endfunction @@ -180,7 +199,10 @@ function interactive(fn_vq_txt, fn_target_f32) [targets e] = load_targets(fn_target_f32); hi_energy_frames = find(e>20); [eq1 eq2] = est_eq(vq, targets); - [tmp adap_eq1] = vq_targets_adap_eq(vq, targets); + + % two passes .... + [tmp adap_eq1] = vq_targets_adap_eq(vq, targets, zeros(1,K)); + [tmp adap_eq1] = vq_targets_adap_eq(vq, targets, adap_eq1(end,:)); figure(1); clf; mesh(e+targets) @@ -229,6 +251,6 @@ function interactive(fn_vq_txt, fn_target_f32) % choose one of these to run first % You'll need to run scripts/train_700C_quant.sh first to generate the .f32 files -interactive("train_120_1.txt", "vk5qi.f32") -%table_across_samples; +%interactive("train_120_1.txt", "cq_ref.f32") +table_across_samples; %vq_700c_plots({"hts1a.f32" "hts2a.f32" "ve9qrp_10s.f32" "ma01_01.f32" "train_120_1.txt"}) diff --git a/script/train_700c_quant.sh b/script/train_700c_quant.sh index 74dd4270..1c3d83e4 100755 --- a/script/train_700c_quant.sh +++ b/script/train_700c_quant.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/bash -x # train_700C_quant.sh # David Rowe May 2019 # @@ -58,9 +58,14 @@ function test_uq() { $CODEC2_BUILD/src/c2dec 700C $b'.bin' - --loadratek $b'_ratek.f32' | sox -q -t .s16 -c 1 -r 8000 -b 16 - $SAMPLES/$b'_uq.wav' } +# extract features for use in octave octave/vq_700c_eq.m function feat() { - b=$(basename "$1" .raw) - $CODEC2_BUILD/src/c2enc 700C $1'.raw' /dev/null --mlfeat $b.f32 + RAW_FILES="../raw/hts1a ../raw/hts2a ../raw/vk5qi ../raw/cq_ref ../raw/ve9qrp_10s $HOME/Downloads/ma01_01 $HOME/Downloads/c01_01_8k $HOME/Downloads/cq_freedv_8k $HOME/Downloads/cq_freedv_8k_lfboost $HOME/Downloads/cq_freedv_8k_hfcut " + for f in $RAW_FILES + do + b=$(basename "$f" .raw) + $CODEC2_BUILD/src/c2enc 700C $f'.raw' $b'.bin' --mlfeat $b'_feat.f32' + done } # generate a bunch of test samples for a listening test @@ -79,15 +84,16 @@ function listen() { # Generate a bunch of test samples for VQ equalisation listening tests. Assumes # Octave has generated rate K quantised .f32 files function listen_vq_eq() { - FILES="hts1a hts2a vk5qi cq_ref ve9qrp_10s ma01_01 c01_01_8k cq_freedv_8k" + FILES="hts1a hts2a vk5qi cq_ref ve9qrp_10s ma01_01 c01_01_8k cq_freedv_8k cq_freedv_8k_lfboost cq_freedv_8k_hfcut" for f in $FILES do # try equaliser wth train_120 VQ $CODEC2_BUILD/src/c2dec 700C $f'.bin' - --loadratek $f'_vq2.f32' | sox -q -t .s16 -c 1 -r 8000 -b 16 - $SAMPLES/$f'_vq2.wav' $CODEC2_BUILD/src/c2dec 700C $f'.bin' - --loadratek $f'_vq2_eq.f32' | sox -q -t .s16 -c 1 -r 8000 -b 16 - $SAMPLES/$f'_vq2_eq.wav' + $CODEC2_BUILD/src/c2dec 700C $f'.bin' - --loadratek $f'_vq2_adap_eq.f32' | sox -q -t .s16 -c 1 -r 8000 -b 16 - $SAMPLES/$f'_vq2_adap_eq.wav' # try equaliser wth train_all_speech VQ - $CODEC2_BUILD/src/c2dec 700C $f'.bin' - --loadratek $f'_vq2_as.f32' | sox -q -t .s16 -c 1 -r 8000 -b 16 - $SAMPLES/$f'_vq2_as.wav' - $CODEC2_BUILD/src/c2dec 700C $f'.bin' - --loadratek $f'_vq2_as_eq.f32' | sox -q -t .s16 -c 1 -r 8000 -b 16 - $SAMPLES/$f'_vq2_as_eq.wav' + #$CODEC2_BUILD/src/c2dec 700C $f'.bin' - --loadratek $f'_vq2_as.f32' | sox -q -t .s16 -c 1 -r 8000 -b 16 - $SAMPLES/$f'_vq2_as.wav' + #$CODEC2_BUILD/src/c2dec 700C $f'.bin' - --loadratek $f'_vq2_as_eq.f32' | sox -q -t .s16 -c 1 -r 8000 -b 16 - $SAMPLES/$f'_vq2_as_eq.wav' done } @@ -96,5 +102,6 @@ mkdir -p $SAMPLES # choose which function to run here #train #listen +#feat listen_vq_eq From 27ed60889da94ca1c4217ade41611f60d68a10dd Mon Sep 17 00:00:00 2001 From: David Date: Fri, 19 Jul 2019 16:12:57 +0930 Subject: [PATCH 03/20] moved EQ in front of VQ, based on differnece between mean of targets vectors and stage 1 of VQ. Good obj results using block averages --- octave/vq_700c_eq.m | 51 +++++++++++++++++--------------------- script/train_700c_quant.sh | 4 +-- 2 files changed, 25 insertions(+), 30 deletions(-) diff --git a/octave/vq_700c_eq.m b/octave/vq_700c_eq.m index 568dffa4..56ad7b49 100644 --- a/octave/vq_700c_eq.m +++ b/octave/vq_700c_eq.m @@ -141,7 +141,7 @@ function save_f32(fn, m) vq2 = load(sprintf("%s_2.txt", vq_name)); printf("----------------------------------------------------------------------------------\n"); - printf("Sample Initial vqs1 vqsg1_eq vq1_adapeq vqs2 vqs2_eq vqs2_adapeq \n"); + printf("Sample Initial vq1 vq1_eq2 vq1_eq2 vq2 vq2_eq1 vq2_eq2 \n"); printf("----------------------------------------------------------------------------------\n"); fn_targets = { "cq_freedv_8k_lfboost" "cq_freedv_8k_hfcut" "cq_freedv_8k" "hts1a" "hts2a" "cq_ref" "ve9qrp_10s" "vk5qi" "c01_01_8k" "ma01_01"}; @@ -151,41 +151,39 @@ function save_f32(fn, m) % load target and estimate eq [targets e] = load_targets(fn_targets{i}); - eq = est_eq(vq1, targets); + eq1 = est_eq(vq1, targets); + + % simple EQ based on difference between mean of inout and mean of vq1 (stage 1 VQ) + eq2 = mean(targets)-mean(vq1); % first stage VQ ----------------- errors1 = vq_targets(vq1, targets); - errors1_eq = vq_targets(vq1, targets-eq); - - % two passes to allow time for adaption, we use results from 2nd pas - [errors1_adap_eq eqs] = vq_targets_adap_eq(vq1, targets, zeros(1,K)); - errors1_adap_eq = vq_targets_adap_eq(vq1, targets, eqs(end,:)); + eqav = mean(targets); + errors1_eq1 = vq_targets(vq1, targets-eq1); + errors1_eq2 = vq_targets(vq1, targets-eq2); % two stage mbest VQ -------------- [errors2 targets_] = vq_targets2(vq1, vq2, targets); - [errors2_eq targets_eq_] = vq_targets2(vq1, vq2, targets-eq); - - % two passes to allow time for adaption, we use results from 2nd pass - [errors2_adap_eq targets_adap_eq_ eq] = vq_targets2_adap_eq(vq1, vq2, targets, zeros(1,K)); - [errors2_adap_eq targets_adap_eq_ eq] = vq_targets2_adap_eq(vq1, vq2, targets, eq); + [errors2_eq1 targets_eq1_] = vq_targets2(vq1, vq2, targets-eq1); + [errors2_eq2 targets_eq2_] = vq_targets2(vq1, vq2, targets-eq2); % save to .f32 files for listening tests if strcmp(vq_name,"train_120") save_f32(sprintf("../script/%s_vq2.f32", fn_targets{i}), targets_); - save_f32(sprintf("../script/%s_vq2_eq.f32", fn_targets{i}), targets_eq_); - save_f32(sprintf("../script/%s_vq2_adap_eq.f32", fn_targets{i}), targets_adap_eq_); + save_f32(sprintf("../script/%s_vq2_eq1.f32", fn_targets{i}), targets_eq1_); + save_f32(sprintf("../script/%s_vq2_eq2.f32", fn_targets{i}), targets_eq2_); else save_f32(sprintf("../script/%s_vq2_as.f32", fn_targets{i}), targets_); save_f32(sprintf("../script/%s_vq2_as_eq.f32", fn_targets{i}), targets_eq_); end printf("%-21s %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f\n", fn_targets{i}, - var(targets(:)), var(errors1(:)), var(errors1_eq(:)), var(errors1_adap_eq(:)), - var(errors2(:)), var(errors2_eq(:)), var(errors2_adap_eq(:))); + var(targets(:)), var(errors1(:)), var(errors1_eq1(:)), var(errors1_eq2(:)), + var(errors2(:)), var(errors2_eq1(:)), var(errors2_eq2(:))); figure(figs++); - plot(var(errors2'),'b;vq;'); hold on; plot(var(errors2_eq'),'g;vq_eq;'); plot(var(errors2_adap_eq'),'r;adap_eq;'); hold off; + plot(var(errors2'),'b;vq2;'); hold on; plot(var(errors2_eq1'),'g;vq2_eq1;'); plot(var(errors2_eq2'),'r;vq2_eq2;'); hold off; title(fn_targets{i}); end endfunction @@ -197,19 +195,16 @@ function interactive(fn_vq_txt, fn_target_f32) K = 20; vq = load("train_120_1.txt"); [targets e] = load_targets(fn_target_f32); - hi_energy_frames = find(e>20); - [eq1 eq2] = est_eq(vq, targets); - - % two passes .... - [tmp adap_eq1] = vq_targets_adap_eq(vq, targets, zeros(1,K)); - [tmp adap_eq1] = vq_targets_adap_eq(vq, targets, adap_eq1(end,:)); + eq1 = est_eq(vq, targets); + eq2 = mean(targets) - mean(vq); figure(1); clf; mesh(e+targets) figure(2); clf; - %plot(eq1,'b;eq1;') - %hold on; plot(adap_eq1,'c;adap eq1;'); hold off; - mesh(adap_eq1); + plot(eq1,'b;eq;') + hold on; + plot(eqav,'c;eqav;'); plot(vqav,'r;vqav;'); plot(eq2,'g;eq2;'); + hold off; figure(3); clf; plot(e(:,1)); title('Energy') % enter single step loop @@ -240,7 +235,7 @@ function interactive(fn_vq_txt, fn_target_f32) if neq == 3 neq = 0; end if neq == 0 eq = zeros(1,K); end if neq == 1 eq = eq1; end - if neq == 2 eq = adap_eq1(f,:); end + if neq == 2 eq = eq2; end if k == 'b' f-=1; end until (k == 'q') printf("\n"); @@ -251,6 +246,6 @@ function interactive(fn_vq_txt, fn_target_f32) % choose one of these to run first % You'll need to run scripts/train_700C_quant.sh first to generate the .f32 files -%interactive("train_120_1.txt", "cq_ref.f32") +%interactive("train_120_1.txt", "cq_freedv_8k_lfboost.f32") table_across_samples; %vq_700c_plots({"hts1a.f32" "hts2a.f32" "ve9qrp_10s.f32" "ma01_01.f32" "train_120_1.txt"}) diff --git a/script/train_700c_quant.sh b/script/train_700c_quant.sh index 1c3d83e4..9be7207a 100755 --- a/script/train_700c_quant.sh +++ b/script/train_700c_quant.sh @@ -89,8 +89,8 @@ function listen_vq_eq() { do # try equaliser wth train_120 VQ $CODEC2_BUILD/src/c2dec 700C $f'.bin' - --loadratek $f'_vq2.f32' | sox -q -t .s16 -c 1 -r 8000 -b 16 - $SAMPLES/$f'_vq2.wav' - $CODEC2_BUILD/src/c2dec 700C $f'.bin' - --loadratek $f'_vq2_eq.f32' | sox -q -t .s16 -c 1 -r 8000 -b 16 - $SAMPLES/$f'_vq2_eq.wav' - $CODEC2_BUILD/src/c2dec 700C $f'.bin' - --loadratek $f'_vq2_adap_eq.f32' | sox -q -t .s16 -c 1 -r 8000 -b 16 - $SAMPLES/$f'_vq2_adap_eq.wav' + $CODEC2_BUILD/src/c2dec 700C $f'.bin' - --loadratek $f'_vq2_eq1.f32' | sox -q -t .s16 -c 1 -r 8000 -b 16 - $SAMPLES/$f'_vq2_eq1.wav' + $CODEC2_BUILD/src/c2dec 700C $f'.bin' - --loadratek $f'_vq2_eq2.f32' | sox -q -t .s16 -c 1 -r 8000 -b 16 - $SAMPLES/$f'_vq2_eq2.wav' # try equaliser wth train_all_speech VQ #$CODEC2_BUILD/src/c2dec 700C $f'.bin' - --loadratek $f'_vq2_as.f32' | sox -q -t .s16 -c 1 -r 8000 -b 16 - $SAMPLES/$f'_vq2_as.wav' #$CODEC2_BUILD/src/c2dec 700C $f'.bin' - --loadratek $f'_vq2_as_eq.f32' | sox -q -t .s16 -c 1 -r 8000 -b 16 - $SAMPLES/$f'_vq2_as_eq.wav' From 93d38b0d70b5459a4ad26ae016b53115da9c8ebd Mon Sep 17 00:00:00 2001 From: David Date: Sat, 20 Jul 2019 09:02:08 +0930 Subject: [PATCH 04/20] experimenting with block based technqiues --- octave/vq_700c_eq.m | 100 +++++++++++++++++++++++++++++-------- script/train_700c_quant.sh | 2 +- 2 files changed, 80 insertions(+), 22 deletions(-) diff --git a/octave/vq_700c_eq.m b/octave/vq_700c_eq.m index 56ad7b49..59f1e60a 100644 --- a/octave/vq_700c_eq.m +++ b/octave/vq_700c_eq.m @@ -48,14 +48,16 @@ function vq_700c_plots(fn_array) % single stage vq a target matrix with adaptive EQ -function [errors eqs] = vq_targets_adap_eq(vq, targets, eq) +function [errors eqs] = vq_targets_adap_eq(vq, targets, eqs) errors = []; gain=0.02; - eqs = []; prev_eq = eq; + eq = eqs(end,:); for i=1:length(targets) - [mse_list index_list] = search_vq(vq, targets(i,:)-eq, 1); - error = targets(i,:) - eq - vq(index_list(1),:); - eq = (1-gain)*prev_eq + gain*error; - prev_eq = eq; + t = targets(i,:) - eq; + mean(t) + %t -= mean(t); + [mse_list index_list] = search_vq(vq, t, 1); + error = t - vq(index_list(1),:); + eq = (1-gain)*eq + gain*error; errors = [errors; error]; eqs = [eqs; eq]; end endfunction @@ -76,6 +78,7 @@ function vq_700c_plots(fn_array) errors = []; targets_ = []; for i=1:length(targets) t = targets(i,:)-eq; + t -= mean(t')'; [error target_ indexes] = mbest(vqset, t, m); % use first stage VQ as error driving adaptive EQ eq_error = t - vq1(indexes(1),:); @@ -141,11 +144,11 @@ function save_f32(fn, m) vq2 = load(sprintf("%s_2.txt", vq_name)); printf("----------------------------------------------------------------------------------\n"); - printf("Sample Initial vq1 vq1_eq2 vq1_eq2 vq2 vq2_eq1 vq2_eq2 \n"); + printf("Sample Initial vq1 vq1_eq2 vq1_eq2 vq2 vq2_eq1 vq2_eq2 \n"); printf("----------------------------------------------------------------------------------\n"); fn_targets = { "cq_freedv_8k_lfboost" "cq_freedv_8k_hfcut" "cq_freedv_8k" "hts1a" "hts2a" "cq_ref" "ve9qrp_10s" "vk5qi" "c01_01_8k" "ma01_01"}; - %fn_targets = {"hts1a"}; + #fn_targets = {"hts1a"}; figs=1; for i=1:length(fn_targets) @@ -153,21 +156,19 @@ function save_f32(fn, m) [targets e] = load_targets(fn_targets{i}); eq1 = est_eq(vq1, targets); - % simple EQ based on difference between mean of inout and mean of vq1 (stage 1 VQ) - eq2 = mean(targets)-mean(vq1); - % first stage VQ ----------------- errors1 = vq_targets(vq1, targets); - eqav = mean(targets); errors1_eq1 = vq_targets(vq1, targets-eq1); - errors1_eq2 = vq_targets(vq1, targets-eq2); + [errors1_eq2 eqs2] = vq_targets_adap_eq(vq1, targets, zeros(1,K)); + [errors1_eq2 eqs2] = vq_targets_adap_eq(vq1, targets, eqs2(end,:)); % two stage mbest VQ -------------- [errors2 targets_] = vq_targets2(vq1, vq2, targets); [errors2_eq1 targets_eq1_] = vq_targets2(vq1, vq2, targets-eq1); - [errors2_eq2 targets_eq2_] = vq_targets2(vq1, vq2, targets-eq2); + [errors2_eq2 targets_eq2_ eq2] = vq_targets2_adap_eq(vq1, vq2, targets, zeros(1,K)); + [errors2_eq2 targets_eq2_ eq2] = vq_targets2_adap_eq(vq1, vq2, targets, eq2); % save to .f32 files for listening tests if strcmp(vq_name,"train_120") @@ -183,7 +184,8 @@ function save_f32(fn, m) var(errors2(:)), var(errors2_eq1(:)), var(errors2_eq2(:))); figure(figs++); - plot(var(errors2'),'b;vq2;'); hold on; plot(var(errors2_eq1'),'g;vq2_eq1;'); plot(var(errors2_eq2'),'r;vq2_eq2;'); hold off; + %plot(var(errors2'),'b;vq2;'); hold on; plot(var(errors2_eq1'),'g;vq2_eq1;'); plot(var(errors2_eq2'),'r;vq2_eq2;'); hold off; + plot(eq2) title(fn_targets{i}); end endfunction @@ -196,16 +198,19 @@ function interactive(fn_vq_txt, fn_target_f32) vq = load("train_120_1.txt"); [targets e] = load_targets(fn_target_f32); eq1 = est_eq(vq, targets); - eq2 = mean(targets) - mean(vq); + + [errors1_eq2 eqs2] = vq_targets_adap_eq(vq, targets, zeros(1,K)); + [errors1_eq2 eqs2] = vq_targets_adap_eq(vq, targets, eqs2(end,:)); + eq2 = eqs2(end,:); figure(1); clf; mesh(e+targets) figure(2); clf; - plot(eq1,'b;eq;') + plot(eq1,'b;eq1;') hold on; - plot(eqav,'c;eqav;'); plot(vqav,'r;vqav;'); plot(eq2,'g;eq2;'); + plot(mean(targets),'c;mean(targets);'); plot(eq2,'g;eq2;'); hold off; - figure(3); clf; plot(e(:,1)); title('Energy') + figure(3); clf; mesh(eqs2); title('eq2 evolving') % enter single step loop f = 20; neq = 0; eq=zeros(1,K); @@ -235,17 +240,70 @@ function interactive(fn_vq_txt, fn_target_f32) if neq == 3 neq = 0; end if neq == 0 eq = zeros(1,K); end if neq == 1 eq = eq1; end - if neq == 2 eq = eq2; end + if neq == 2 eq = eqs2(f,:); end if k == 'b' f-=1; end until (k == 'q') printf("\n"); endfunction + +% Experiment to test iterative approach of block update and remove +% mean (ie frame energy), shows some promise at reducing HF energy +% over several iterations while not affecting alreayd good samples + +function experiment_iterate_block(fn_vq_txt, fn_target_f32) + K = 20; + vq = load("train_120_1.txt"); + [targets e] = load_targets(fn_target_f32); + + figure(1); clf; + plot(mean(targets),'b;mean(targets);'); + hold on; + plot(mean(vq), 'g;mean(vq);'); + figure(2); clf; hold on; + eq = zeros(1,K); + for i=1:3 + t = targets - eq; + errors = vq_targets(vq, t); + eq += est_eq(vq, t); + figure(1); plot(mean(t)); + figure(2); plot(eq); + printf("i: %d %6.2f\n", i, var(errors(:))) + end +endfunction + +% adaptive version of above + +function experiment_iterate_adap(fn_vq_txt, fn_target_f32) + K = 20; + vq = load("train_120_1.txt"); + [targets e] = load_targets(fn_target_f32); + + figure(3); clf; + plot(mean(targets),'b;mean(targets);'); + hold on; + plot(mean(vq), 'g;mean(vq);'); + figure(4); clf; hold on; + eqs = zeros(1,K); + for i=1:3 + [errors eqs] = vq_targets_adap_eq(vq, targets, eqs); + t = targets - eqs(end,:); + figure(3); plot(mean(t)); + figure(4); plot(eqs(end,:)); + printf("i: %d %6.2f\n", i, var(errors(:))) + end + figure(5); clf; mesh(eqs); +endfunction + + more off % choose one of these to run first % You'll need to run scripts/train_700C_quant.sh first to generate the .f32 files %interactive("train_120_1.txt", "cq_freedv_8k_lfboost.f32") -table_across_samples; +%table_across_samples; %vq_700c_plots({"hts1a.f32" "hts2a.f32" "ve9qrp_10s.f32" "ma01_01.f32" "train_120_1.txt"}) +%vq_700c_plots({"ve9qrp_10s.f32" "cq_freedv_8k_lfboost.f32" "cq_freedv_8k_hfcut.f32" "cq_freedv_8k.f32"}) +experiment_iterate_block("train_120_1.txt", "cq_freedv_8k_lfboost.f32") +%experiment_iterate_adap("train_120_1.txt", "cq_freedv_8k_lfboost.f32") diff --git a/script/train_700c_quant.sh b/script/train_700c_quant.sh index 9be7207a..4fd0c720 100755 --- a/script/train_700c_quant.sh +++ b/script/train_700c_quant.sh @@ -10,7 +10,7 @@ SRC=~/Downloads/all_speech_8k.sw CODEC2_BUILD=/home/david/codec2/build_linux K=20 -SAMPLES=~/tmp/c2vec_pass +SAMPLES=~/tmp/c2vec_pass2 # train a new VQ function train() { From b51a4b9e49f9769f064e06e9491b08f04f88e92c Mon Sep 17 00:00:00 2001 From: David Date: Sat, 20 Jul 2019 19:00:42 +0930 Subject: [PATCH 05/20] iterative version sounds pretty good and gd obj measures --- octave/vq_700c_eq.m | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/octave/vq_700c_eq.m b/octave/vq_700c_eq.m index 59f1e60a..0411d626 100644 --- a/octave/vq_700c_eq.m +++ b/octave/vq_700c_eq.m @@ -159,16 +159,19 @@ function save_f32(fn, m) % first stage VQ ----------------- errors1 = vq_targets(vq1, targets); - errors1_eq1 = vq_targets(vq1, targets-eq1); - [errors1_eq2 eqs2] = vq_targets_adap_eq(vq1, targets, zeros(1,K)); - [errors1_eq2 eqs2] = vq_targets_adap_eq(vq1, targets, eqs2(end,:)); + errors1_eq1 = vq_targets(vq1, targets-eq1); + eq2 = zeros(1,K); + for it=1:3 + t = targets - eq2; + errors1_eq2 = vq_targets(vq1, t); + eq2 += est_eq(vq1, t); + end % two stage mbest VQ -------------- [errors2 targets_] = vq_targets2(vq1, vq2, targets); [errors2_eq1 targets_eq1_] = vq_targets2(vq1, vq2, targets-eq1); - [errors2_eq2 targets_eq2_ eq2] = vq_targets2_adap_eq(vq1, vq2, targets, zeros(1,K)); - [errors2_eq2 targets_eq2_ eq2] = vq_targets2_adap_eq(vq1, vq2, targets, eq2); + [errors2_eq2 targets_eq2_] = vq_targets2(vq1, vq2, targets-eq2); % save to .f32 files for listening tests if strcmp(vq_name,"train_120") @@ -179,13 +182,13 @@ function save_f32(fn, m) save_f32(sprintf("../script/%s_vq2_as.f32", fn_targets{i}), targets_); save_f32(sprintf("../script/%s_vq2_as_eq.f32", fn_targets{i}), targets_eq_); end - printf("%-21s %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f\n", fn_targets{i}, + printf("%-21s %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f\n", fn_targets{i}, var(targets(:)), var(errors1(:)), var(errors1_eq1(:)), var(errors1_eq2(:)), var(errors2(:)), var(errors2_eq1(:)), var(errors2_eq2(:))); - figure(figs++); + figure(figs++); clf; %plot(var(errors2'),'b;vq2;'); hold on; plot(var(errors2_eq1'),'g;vq2_eq1;'); plot(var(errors2_eq2'),'r;vq2_eq2;'); hold off; - plot(eq2) + plot(mean(targets); hold on; plot(mean(vq)); plot(eq2); hold off; title(fn_targets{i}); end endfunction @@ -302,8 +305,8 @@ function experiment_iterate_adap(fn_vq_txt, fn_target_f32) % You'll need to run scripts/train_700C_quant.sh first to generate the .f32 files %interactive("train_120_1.txt", "cq_freedv_8k_lfboost.f32") -%table_across_samples; +table_across_samples; %vq_700c_plots({"hts1a.f32" "hts2a.f32" "ve9qrp_10s.f32" "ma01_01.f32" "train_120_1.txt"}) %vq_700c_plots({"ve9qrp_10s.f32" "cq_freedv_8k_lfboost.f32" "cq_freedv_8k_hfcut.f32" "cq_freedv_8k.f32"}) -experiment_iterate_block("train_120_1.txt", "cq_freedv_8k_lfboost.f32") +%experiment_iterate_block("train_120_1.txt", "cq_freedv_8k_lfboost.f32") %experiment_iterate_adap("train_120_1.txt", "cq_freedv_8k_lfboost.f32") From 440304293213926246ccc2783ddbc59998341c30 Mon Sep 17 00:00:00 2001 From: David Date: Sun, 21 Jul 2019 06:12:16 +0930 Subject: [PATCH 06/20] block adaptive working pretty well, except one sample (ve9qrp_10s) messed up by EQ --- octave/vq_700c_eq.m | 74 +++++++++++++++++++-------------------------- 1 file changed, 31 insertions(+), 43 deletions(-) diff --git a/octave/vq_700c_eq.m b/octave/vq_700c_eq.m index 0411d626..f94f3f7e 100644 --- a/octave/vq_700c_eq.m +++ b/octave/vq_700c_eq.m @@ -46,7 +46,7 @@ function vq_700c_plots(fn_array) endfunction -% single stage vq a target matrix with adaptive EQ +% single stage vq a target matrix with adaptive EQ, this didn't work function [errors eqs] = vq_targets_adap_eq(vq, targets, eqs) errors = []; gain=0.02; @@ -63,6 +63,26 @@ function vq_700c_plots(fn_array) endfunction +% single stage vq a target matrix with block adaptive EQ, this works +% well with nblock == 10 + +function [errors eq] = vq_targets_block_eq(vq, targets, eq, nblock) + errors = []; n = 0; [tmp K] = size(vq); error_eq = zeros(1,K); + for i=1:length(targets) + t = targets(i,:) - eq; + [mse_list index_list] = search_vq(vq, t, 1); + error = t - vq(index_list(1),:); + error_eq += error; + errors = [errors; error]; + n++; + if n == nblock + eq += error_eq/nblock; + n = 0; error_eq = zeros(1,K); + end + end +endfunction + + % two stage mbest VQ a target matrix function [errors targets_] = vq_targets2(vq1, vq2, targets) @@ -144,7 +164,7 @@ function save_f32(fn, m) vq2 = load(sprintf("%s_2.txt", vq_name)); printf("----------------------------------------------------------------------------------\n"); - printf("Sample Initial vq1 vq1_eq2 vq1_eq2 vq2 vq2_eq1 vq2_eq2 \n"); + printf("Sample Initial vq1 vq1_eq2 vq1_eq2 vq2 vq2_eq1 vq2_eq2 \n"); printf("----------------------------------------------------------------------------------\n"); fn_targets = { "cq_freedv_8k_lfboost" "cq_freedv_8k_hfcut" "cq_freedv_8k" "hts1a" "hts2a" "cq_ref" "ve9qrp_10s" "vk5qi" "c01_01_8k" "ma01_01"}; @@ -160,12 +180,7 @@ function save_f32(fn, m) errors1 = vq_targets(vq1, targets); errors1_eq1 = vq_targets(vq1, targets-eq1); - eq2 = zeros(1,K); - for it=1:3 - t = targets - eq2; - errors1_eq2 = vq_targets(vq1, t); - eq2 += est_eq(vq1, t); - end + [errors1_eq2 eq2] = vq_targets_block_eq(vq1, targets, zeros(1,K), 10); % two stage mbest VQ -------------- @@ -182,14 +197,14 @@ function save_f32(fn, m) save_f32(sprintf("../script/%s_vq2_as.f32", fn_targets{i}), targets_); save_f32(sprintf("../script/%s_vq2_as_eq.f32", fn_targets{i}), targets_eq_); end - printf("%-21s %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f\n", fn_targets{i}, + printf("%-21s %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f\n", fn_targets{i}, var(targets(:)), var(errors1(:)), var(errors1_eq1(:)), var(errors1_eq2(:)), var(errors2(:)), var(errors2_eq1(:)), var(errors2_eq2(:))); figure(figs++); clf; %plot(var(errors2'),'b;vq2;'); hold on; plot(var(errors2_eq1'),'g;vq2_eq1;'); plot(var(errors2_eq2'),'r;vq2_eq2;'); hold off; - plot(mean(targets); hold on; plot(mean(vq)); plot(eq2); hold off; - title(fn_targets{i}); + plot(mean(targets),'g;mean(targets);'); hold on; plot(mean(vq1),'g;mean(vq1);'); plot(eq2,'r;eq2;'); hold off; + title(fn_targets{i}); axis([1 K -20 30]); end endfunction @@ -252,7 +267,7 @@ function interactive(fn_vq_txt, fn_target_f32) % Experiment to test iterative approach of block update and remove % mean (ie frame energy), shows some promise at reducing HF energy -% over several iterations while not affecting alreayd good samples +% over several iterations while not affecting already good samples function experiment_iterate_block(fn_vq_txt, fn_target_f32) K = 20; @@ -266,47 +281,20 @@ function experiment_iterate_block(fn_vq_txt, fn_target_f32) figure(2); clf; hold on; eq = zeros(1,K); for i=1:3 - t = targets - eq; - errors = vq_targets(vq, t); - eq += est_eq(vq, t); - figure(1); plot(mean(t)); + [errors eq] = vq_targets_block_eq(vq, targets, eq, 10); + figure(1); plot(mean(targets-eq)); figure(2); plot(eq); printf("i: %d %6.2f\n", i, var(errors(:))) end endfunction -% adaptive version of above - -function experiment_iterate_adap(fn_vq_txt, fn_target_f32) - K = 20; - vq = load("train_120_1.txt"); - [targets e] = load_targets(fn_target_f32); - - figure(3); clf; - plot(mean(targets),'b;mean(targets);'); - hold on; - plot(mean(vq), 'g;mean(vq);'); - figure(4); clf; hold on; - eqs = zeros(1,K); - for i=1:3 - [errors eqs] = vq_targets_adap_eq(vq, targets, eqs); - t = targets - eqs(end,:); - figure(3); plot(mean(t)); - figure(4); plot(eqs(end,:)); - printf("i: %d %6.2f\n", i, var(errors(:))) - end - figure(5); clf; mesh(eqs); -endfunction - - more off % choose one of these to run first % You'll need to run scripts/train_700C_quant.sh first to generate the .f32 files %interactive("train_120_1.txt", "cq_freedv_8k_lfboost.f32") -table_across_samples; +%table_across_samples; %vq_700c_plots({"hts1a.f32" "hts2a.f32" "ve9qrp_10s.f32" "ma01_01.f32" "train_120_1.txt"}) %vq_700c_plots({"ve9qrp_10s.f32" "cq_freedv_8k_lfboost.f32" "cq_freedv_8k_hfcut.f32" "cq_freedv_8k.f32"}) -%experiment_iterate_block("train_120_1.txt", "cq_freedv_8k_lfboost.f32") -%experiment_iterate_adap("train_120_1.txt", "cq_freedv_8k_lfboost.f32") +experiment_iterate_block("train_120_1.txt", "ve9qrp_10s.f32") From 11541933a73ada8315f4eb0508d5f1fbe207e51b Mon Sep 17 00:00:00 2001 From: David Date: Sun, 21 Jul 2019 07:18:23 +0930 Subject: [PATCH 07/20] integrator with gain, but still unsatisfactory on ve9qrp or speed, trying input EQ again --- octave/vq_700c_eq.m | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/octave/vq_700c_eq.m b/octave/vq_700c_eq.m index f94f3f7e..b0d61a62 100644 --- a/octave/vq_700c_eq.m +++ b/octave/vq_700c_eq.m @@ -67,7 +67,7 @@ function vq_700c_plots(fn_array) % well with nblock == 10 function [errors eq] = vq_targets_block_eq(vq, targets, eq, nblock) - errors = []; n = 0; [tmp K] = size(vq); error_eq = zeros(1,K); + errors = []; n = 0; [tmp K] = size(vq); error_eq = zeros(1,K); gain=0.20; for i=1:length(targets) t = targets(i,:) - eq; [mse_list index_list] = search_vq(vq, t, 1); @@ -76,7 +76,7 @@ function vq_700c_plots(fn_array) errors = [errors; error]; n++; if n == nblock - eq += error_eq/nblock; + eq = 0.99*eq + gain*error_eq/nblock; n = 0; error_eq = zeros(1,K); end end @@ -288,13 +288,35 @@ function experiment_iterate_block(fn_vq_txt, fn_target_f32) end endfunction +% Experiment to test EQ of input (before) VQ. We set a threshold on +% when to equalise, so we don't upset already flat-ish samples. + +function experiment_input_eq(fn_vq_txt, fn_target_f32) + K = 20; + vq = load("train_120_1.txt"); + [targets e] = load_targets(fn_target_f32); + + slope = -12/K; + ideal = 6:slope:-6-slope; + eq = mean(targets) - ideal; + + figure(1); clf; + plot(mean(targets),'b;mean(targets);'); + hold on; + plot(ideal, 'g;ideal;'); + plot(eq, 'r;eq;'); + plot(mean(targets)-eq, 'c;equalised;'); +endfunction + more off % choose one of these to run first % You'll need to run scripts/train_700C_quant.sh first to generate the .f32 files %interactive("train_120_1.txt", "cq_freedv_8k_lfboost.f32") -%table_across_samples; +table_across_samples; %vq_700c_plots({"hts1a.f32" "hts2a.f32" "ve9qrp_10s.f32" "ma01_01.f32" "train_120_1.txt"}) -%vq_700c_plots({"ve9qrp_10s.f32" "cq_freedv_8k_lfboost.f32" "cq_freedv_8k_hfcut.f32" "cq_freedv_8k.f32"}) -experiment_iterate_block("train_120_1.txt", "ve9qrp_10s.f32") +%vq_700c_plots({"ve9qrp_10s.f32" "cq_freedv_8k_lfboost.f32" "cq_ref.f32" "hts1a.f32" "vk5qi.f32"}) +%experiment_iterate_block("train_120_1.txt", "ve9qrp_10s.f32") +%experiment_iterate_block("train_120_1.txt", "cq_freedv_8k_lfboost.f32") +experiment_input_eq("train_120_1.txt", "ve9qrp_10s.f32") From 8b7a08d750ace07072274da5b5c3bcd80f9d29c0 Mon Sep 17 00:00:00 2001 From: David Date: Sun, 21 Jul 2019 09:28:46 +0930 Subject: [PATCH 08/20] better results with a different ideal profile that penaliss high LF energy. improves cq_freedv_8k samples, cq_ref, vk5qi, and doesn't affect other samples. --- octave/vq_700c_eq.m | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/octave/vq_700c_eq.m b/octave/vq_700c_eq.m index b0d61a62..0e511c1c 100644 --- a/octave/vq_700c_eq.m +++ b/octave/vq_700c_eq.m @@ -176,11 +176,15 @@ function save_f32(fn, m) [targets e] = load_targets(fn_targets{i}); eq1 = est_eq(vq1, targets); + ideal = [ 8 10 12 14 14*ones(1,K-4) ]; + eq2 = mean(targets) - ideal; + eq2(find(eq2 < 0)) = 0; + % first stage VQ ----------------- errors1 = vq_targets(vq1, targets); errors1_eq1 = vq_targets(vq1, targets-eq1); - [errors1_eq2 eq2] = vq_targets_block_eq(vq1, targets, zeros(1,K), 10); + errors1_eq2 = vq_targets(vq1, targets-eq2); % two stage mbest VQ -------------- @@ -296,9 +300,11 @@ function experiment_input_eq(fn_vq_txt, fn_target_f32) vq = load("train_120_1.txt"); [targets e] = load_targets(fn_target_f32); - slope = -12/K; - ideal = 6:slope:-6-slope; + %slope = -12/K; const = 10; + %ideal = const + (6:slope:-6-slope); + ideal = [ 8 10 12 14 14*ones(1,K-4) ]; eq = mean(targets) - ideal; + eq(find(eq < 0)) = 0; figure(1); clf; plot(mean(targets),'b;mean(targets);'); @@ -319,4 +325,4 @@ function experiment_input_eq(fn_vq_txt, fn_target_f32) %vq_700c_plots({"ve9qrp_10s.f32" "cq_freedv_8k_lfboost.f32" "cq_ref.f32" "hts1a.f32" "vk5qi.f32"}) %experiment_iterate_block("train_120_1.txt", "ve9qrp_10s.f32") %experiment_iterate_block("train_120_1.txt", "cq_freedv_8k_lfboost.f32") -experiment_input_eq("train_120_1.txt", "ve9qrp_10s.f32") +%experiment_input_eq("train_120_1.txt", "vk5qi.f32") From 2de97623d9785a41e7168ef09923bba10c9807e2 Mon Sep 17 00:00:00 2001 From: David Date: Sun, 21 Jul 2019 11:23:55 +0930 Subject: [PATCH 09/20] adaptive front EQ, added wieght for train_120 VQ 20th sample, which neatly brought down obj measures. Listening tests meets goals - samples with LF energy are improved --- octave/vq_700c_eq.m | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/octave/vq_700c_eq.m b/octave/vq_700c_eq.m index 0e511c1c..76fa3f37 100644 --- a/octave/vq_700c_eq.m +++ b/octave/vq_700c_eq.m @@ -152,6 +152,20 @@ function save_f32(fn, m) targets = feat(:,2:K+1); endfunction +% rather simple EQ in front of VQ + +function [eqs ideal] = est_eq_front(targets) + [tmp K] = size(targets); + ideal = [ 8 10 12 14 14*ones(1,K-1-4) -20]; + eq = zeros(1,K); gain = 0.02; + eqs = []; + for i=1:length(targets) + update = targets(i,:) - ideal; + eq = (1-gain)*eq + gain*update; + eq(find(eq < 0)) = 0; + eqs = [eqs; eq]; + end +endfunction function table_across_samples K = 20; @@ -168,17 +182,15 @@ function save_f32(fn, m) printf("----------------------------------------------------------------------------------\n"); fn_targets = { "cq_freedv_8k_lfboost" "cq_freedv_8k_hfcut" "cq_freedv_8k" "hts1a" "hts2a" "cq_ref" "ve9qrp_10s" "vk5qi" "c01_01_8k" "ma01_01"}; - #fn_targets = {"hts1a"}; + #fn_targets = {"cq_freedv_8k_lfboost"}; figs=1; for i=1:length(fn_targets) % load target and estimate eq [targets e] = load_targets(fn_targets{i}); eq1 = est_eq(vq1, targets); - - ideal = [ 8 10 12 14 14*ones(1,K-4) ]; - eq2 = mean(targets) - ideal; - eq2(find(eq2 < 0)) = 0; + eq2s = est_eq_front(targets); + eq2 = eq2s(end,:); % first stage VQ ----------------- @@ -295,23 +307,22 @@ function experiment_iterate_block(fn_vq_txt, fn_target_f32) % Experiment to test EQ of input (before) VQ. We set a threshold on % when to equalise, so we don't upset already flat-ish samples. -function experiment_input_eq(fn_vq_txt, fn_target_f32) +function experiment_front_eq(fn_vq_txt, fn_target_f32) K = 20; vq = load("train_120_1.txt"); [targets e] = load_targets(fn_target_f32); - %slope = -12/K; const = 10; - %ideal = const + (6:slope:-6-slope); - ideal = [ 8 10 12 14 14*ones(1,K-4) ]; - eq = mean(targets) - ideal; - eq(find(eq < 0)) = 0; + [eqs ideal] = est_eq_front(targets); figure(1); clf; plot(mean(targets),'b;mean(targets);'); hold on; plot(ideal, 'g;ideal;'); - plot(eq, 'r;eq;'); - plot(mean(targets)-eq, 'c;equalised;'); + plot(eqs(end,:), 'r;eq;'); + plot(mean(targets)-eqs(end,:), 'c;equalised;'); + plot(mean(vq),'b--;mean(vq);'); + hold off; + figure(2); clf; mesh(eqs); endfunction more off @@ -325,4 +336,4 @@ function experiment_input_eq(fn_vq_txt, fn_target_f32) %vq_700c_plots({"ve9qrp_10s.f32" "cq_freedv_8k_lfboost.f32" "cq_ref.f32" "hts1a.f32" "vk5qi.f32"}) %experiment_iterate_block("train_120_1.txt", "ve9qrp_10s.f32") %experiment_iterate_block("train_120_1.txt", "cq_freedv_8k_lfboost.f32") -%experiment_input_eq("train_120_1.txt", "vk5qi.f32") +%experiment_front_eq("train_120_1.txt", "cq_freedv_8k_lfboost.f32") From 42560c9583fa7a3b020730e420ad855ea51cf716 Mon Sep 17 00:00:00 2001 From: David Date: Sun, 21 Jul 2019 17:04:39 +0930 Subject: [PATCH 10/20] new ctest for codec 2 700C Octave-C port --- CMakeLists.txt | 11 ++++++++++- octave/tnewamp1.m | 27 +++++++++++++-------------- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 051852e9..7023ea7e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -80,7 +80,7 @@ if(NOT WIN32) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") endif() -set(CMAKE_C_FLAGS_DEBUG "-g -O2") +set(CMAKE_C_FLAGS_DEBUG "-g -O2 -DDUMP") set(CMAKE_C_FLAGS_RELEASE "-O3") # @@ -296,6 +296,15 @@ if(UNITTEST) include(CTest) enable_testing() + add_test(NAME test_codec2_700c_octave_port + COMMAND sh -c "cd ${CMAKE_CURRENT_BINARY_DIR}/src; + ./c2sim ../../raw/hts1a.raw --phase0 --postfilter --dump hts1a --lpc 10 --dump_pitch_e hts1a_pitche.txt; \ + cd ${CMAKE_CURRENT_BINARY_DIR}/unittest; ./tnewamp1 ../../raw/hts1a.raw; \ + cd ${CMAKE_CURRENT_SOURCE_DIR}/octave; \ + octave --no-gui -qf tnewamp1.m") + set_tests_properties(test_codec2_700c_octave_port PROPERTIES + PASS_REGULAR_EXPRESSION "passes: 8") + add_test(NAME test_FDMDV_modem_octave_port COMMAND sh -c "$ && octave --no-gui -qf ${CMAKE_CURRENT_SOURCE_DIR}/octave/tfdmdv.m" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/octave) diff --git a/octave/tnewamp1.m b/octave/tnewamp1.m index 56945c8e..cffd038f 100644 --- a/octave/tnewamp1.m +++ b/octave/tnewamp1.m @@ -20,7 +20,7 @@ 3/ Run C version which generates a file of Octave test vectors as ouput: $ cd codec2-dev/build_linux/unittest - $ ./tnewamp1 ../../raw/hts1a + $ ./tnewamp1 ../../raw/hts1a.raw 4/ Run Octave script to generate Octave test vectors and compare with C. @@ -34,8 +34,7 @@ | play -q -t raw -r 8000 -s -2 - #} - -function tnewamp1(input_prefix) +function tnewamp1(input_prefix="../build_linux/src/hts1a") newamp_700c; autotest; more off; @@ -176,15 +175,17 @@ function tnewamp1(input_prefix) figure(3); clf; mesh(abs(H - H_c(:,1:max_amp))); - check(rate_K_surface, rate_K_surface_c, 'rate_K_surface', 0.01); - check(mean_f, mean_c, 'mean', 0.01); - check(rate_K_surface_, rate_K_surface__c, 'rate_K_surface_', 0.01); - check(interpolated_surface_, interpolated_surface__c, 'interpolated_surface_', 0.01); - check(model_(:,1), model__c(:,1), 'interpolated Wo_', 0.001); - check(voicing_, voicing__c, 'interpolated voicing'); - check(model_(:,3:max_amp+2), model__c(:,3:max_amp+2), 'rate L Am surface ', 0.1); - check(H, H_c(:,1:max_amp), 'phase surface'); - + passes = 0; + passes += check(rate_K_surface, rate_K_surface_c, 'rate_K_surface', 0.01); + passes += check(mean_f, mean_c, 'mean', 0.01); + passes += check(rate_K_surface_, rate_K_surface__c, 'rate_K_surface_', 0.01); + passes += check(interpolated_surface_, interpolated_surface__c, 'interpolated_surface_', 0.01); + passes += check(model_(:,1), model__c(:,1), 'interpolated Wo_', 0.001); + passes += check(voicing_, voicing__c, 'interpolated voicing'); + passes += check(model_(:,3:max_amp+2), model__c(:,3:max_amp+2), 'rate L Am surface ', 0.1); + passes += check(H, H_c(:,1:max_amp), 'phase surface'); + printf("passes: %d\n", passes); + % Save to disk to check synthesis is OK with c2sim output_prefix = input_prefix; @@ -239,8 +240,6 @@ function tnewamp1(input_prefix) end fclose(fv); - printf("\n") - endfunction From 00e61531ad6ab0647f1010ba43d59a5e2704afb5 Mon Sep 17 00:00:00 2001 From: David Date: Sun, 21 Jul 2019 17:28:58 +0930 Subject: [PATCH 11/20] debugging ctest --- octave/tnewamp1.m | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/octave/tnewamp1.m b/octave/tnewamp1.m index cffd038f..35fa0002 100644 --- a/octave/tnewamp1.m +++ b/octave/tnewamp1.m @@ -35,10 +35,12 @@ #} function tnewamp1(input_prefix="../build_linux/src/hts1a") + printf("starting tnewamp1.c input_prefix: %s\n", input_prefix); + newamp_700c; autotest; more off; - + max_amp = 80; postfilter = 0; % optional postfiler that runs on Am, not used atm synth_phase = 1; From 80e0b555232913dcccfcae7c8a34bd2484def379 Mon Sep 17 00:00:00 2001 From: David Date: Sun, 21 Jul 2019 17:30:40 +0930 Subject: [PATCH 12/20] debugging ctest --- CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7023ea7e..6b32b19c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -302,8 +302,7 @@ if(UNITTEST) cd ${CMAKE_CURRENT_BINARY_DIR}/unittest; ./tnewamp1 ../../raw/hts1a.raw; \ cd ${CMAKE_CURRENT_SOURCE_DIR}/octave; \ octave --no-gui -qf tnewamp1.m") - set_tests_properties(test_codec2_700c_octave_port PROPERTIES - PASS_REGULAR_EXPRESSION "passes: 8") + set_tests_properties(test_codec2_700c_octave_port PROPERTIES PASS_REGULAR_EXPRESSION "passes: 8") add_test(NAME test_FDMDV_modem_octave_port COMMAND sh -c "$ && octave --no-gui -qf ${CMAKE_CURRENT_SOURCE_DIR}/octave/tfdmdv.m" From 8e1596720efbc1152e54570b362322f6e98782bd Mon Sep 17 00:00:00 2001 From: David Date: Sun, 21 Jul 2019 17:48:47 +0930 Subject: [PATCH 13/20] cleaning up some unused code --- octave/newamp_700c.m | 16 +++++++++------- octave/tnewamp1.m | 4 +++- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/octave/newamp_700c.m b/octave/newamp_700c.m index 15010f0d..d92e06a9 100644 --- a/octave/newamp_700c.m +++ b/octave/newamp_700c.m @@ -1,14 +1,11 @@ -% newamp.m +% newamp_700c.m % -% Copyright David Rowe 2015 +% Copyright David Rowe 2017 % This program is distributed under the terms of the GNU General Public License % Version 2 % -% Library of Octave functions to explore new ideas in amplitude -% (spectral envelope) modelling. See newamp_fby (frame by frame -% analysis) and newamp_batch (batch processing for listening tests) -% -% Code here to support a bunch of experimental ideas, many that didn't work out. +% Library of Octave functions to explore rate K, mel spaced +% quantisation of spectral magntides used in Codec 2 700C mode. 1; melvq; % mbest VQ functions @@ -349,6 +346,10 @@ function save_vq(vqset, filenameprefix) endfunction +function [rate_K_vec eq] = front_eq(rate_vec, eq) +endfunction + +#{ % -------------------------------------------------------------------------------- % Experimental functions used for masking, piecewise models, not part of newamp1 % -------------------------------------------------------------------------------- @@ -1263,5 +1264,6 @@ function write_bit_stream_file(fn, ind_log, bits_per_param) subplot(212) plot(mask_sample_freqs_kHz*1000, e) endfunction +#} diff --git a/octave/tnewamp1.m b/octave/tnewamp1.m index 35fa0002..80a99dc1 100644 --- a/octave/tnewamp1.m +++ b/octave/tnewamp1.m @@ -72,10 +72,12 @@ function tnewamp1(input_prefix="../build_linux/src/hts1a") load train_120_1.txt; load train_120_2.txt; train_120_vq(:,:,1)= train_120_1; train_120_vq(:,:,2)= train_120_2; m=5; m=5; - + + eq = zeros(1,K); for f=1:frames mean_f(f) = mean(rate_K_surface(f,:)); rate_K_surface_no_mean(f,:) = rate_K_surface(f,:) - mean_f(f); + % [rate_K_surface_no_mean(f,:) eq] = front_eq(rate_K_surface_no_mean(f,:), eq); end [res rate_K_surface_no_mean_ ind] = mbest(train_120_vq, rate_K_surface_no_mean, m); From 3317031e87379c368a5f18728eae925bf807daed Mon Sep 17 00:00:00 2001 From: David Date: Sun, 21 Jul 2019 18:00:26 +0930 Subject: [PATCH 14/20] made test less verbose --- .travis.yml | 3 +- CMakeLists.txt | 2 +- octave/newamp_700c.m | 922 +------------------------------------------ octave/tnewamp1.m | 8 +- unittest/tnewamp1.c | 6 +- 5 files changed, 16 insertions(+), 925 deletions(-) diff --git a/.travis.yml b/.travis.yml index 01de69f1..0efb3ff6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,7 +30,8 @@ script: - mkdir -p $BUILDSTD - cd $BUILDSTD - cmake $CODEC2DEV -- CTEST_OUTPUT_ON_FAILURE=1 make -j4 all test +- ctest -V -R test_codec2_700c_octave_port +#- CTEST_OUTPUT_ON_FAILURE=1 make -j4 all test - mkdir -p $BUILDSTM - cd $BUILDSTM - if [ -e $STDLIBDIR ]; then (ln -s $STDLIBDIR . && cmake $CODEC2DEV/stm32 -DPERIPHLIBDIR="$STDLIBDIR" diff --git a/CMakeLists.txt b/CMakeLists.txt index 6b32b19c..ecc6672b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -300,7 +300,7 @@ if(UNITTEST) COMMAND sh -c "cd ${CMAKE_CURRENT_BINARY_DIR}/src; ./c2sim ../../raw/hts1a.raw --phase0 --postfilter --dump hts1a --lpc 10 --dump_pitch_e hts1a_pitche.txt; \ cd ${CMAKE_CURRENT_BINARY_DIR}/unittest; ./tnewamp1 ../../raw/hts1a.raw; \ - cd ${CMAKE_CURRENT_SOURCE_DIR}/octave; \ + cd ${CMAKE_CURRENT_SOURCE_DIR}/octave; pwd; \ octave --no-gui -qf tnewamp1.m") set_tests_properties(test_codec2_700c_octave_port PROPERTIES PASS_REGULAR_EXPRESSION "passes: 8") diff --git a/octave/newamp_700c.m b/octave/newamp_700c.m index d92e06a9..1aee04bb 100644 --- a/octave/newamp_700c.m +++ b/octave/newamp_700c.m @@ -4,8 +4,8 @@ % This program is distributed under the terms of the GNU General Public License % Version 2 % -% Library of Octave functions to explore rate K, mel spaced -% quantisation of spectral magntides used in Codec 2 700C mode. +% Library of Octave functions to for rate K, mel spaced +% vector quantisation of spectral magntides used in Codec 2 700C mode. 1; melvq; % mbest VQ functions @@ -349,921 +349,3 @@ function save_vq(vqset, filenameprefix) function [rate_K_vec eq] = front_eq(rate_vec, eq) endfunction -#{ -% -------------------------------------------------------------------------------- -% Experimental functions used for masking, piecewise models, not part of newamp1 -% -------------------------------------------------------------------------------- - - -function [maskdB_ maskdB_cyclic Dabs dk_ D1_ ind] = decimate_in_freq(maskdB, cyclic=1, k=7, vq) - - % Lets try to come up with a smoothed, cyclic model. Replace - % points from 3500 Hz to 4000Hz with a sequence that joins without - % a step to points at the 0Hz end of the spectrum. This will make - % it more cyclical and make the DFT happier, less high freq - % energy. Yes, happier is an extremely technical term. - - L = length(maskdB); - anchor = floor(7*L/8); - xpts = [ anchor-1 anchor L+1 L+2]; - ypts = [ maskdB(anchor-1) maskdB(anchor) maskdB(1) maskdB(2)]; - mask_pp = splinefit(xpts, ypts, 1); - maskdB_cyclic = [maskdB(1:anchor) ppval(mask_pp, anchor+1:L)]; - - % Now DFT, truncating DFT coeffs to undersample - - if cyclic - D = fft(maskdB_cyclic)/L; - else - D = fft(maskdB)/L; - end - Dabs = abs(D); % this returned for plotting - - % truncate D to rate k, convert to 2k length real vector for quantisation and transmission - - Dk = [0 D(2:k-1) real(D(k)) D(L-k+1:L)]; - dk = real(ifft(Dk)); - D1 = D(1); - - % quantisation - - if nargin == 4 - [res tmp vq_ind] = mbest(vq, dk, 4); - D1_tab = 0:(60/15):60; - assert(length(D1_tab) == 16); - [tmp D1_ind] = quantise(D1_tab, D1); - ind = [vq_ind D1_ind]; - [dk_ D1_] = index_to_params(ind, vq); - %std(dk_ - dk) - else - dk_ = dk; - D1_ = D1; - end - - maskdB_ = params_to_mask(L, k, dk_, D1_); -endfunction - - - -function [dk_ D1_] = index_to_params(ind, vq) - [Nvec order stages] = size(vq); - dk_ = zeros(1,order); - for s=1:stages - dk_ = dk_ + vq(ind(s),:,s); - end - D1_tab = 0:(60/15):60; - D1_ = D1_tab(ind(stages+1)); -endfunction - - -% decoder side - -function maskdB_ = params_to_mask(L, k, dk_, D1_) - - anchor = floor(7*L/8); - - % convert quantised dk back to rate L magnitude spectrum - - Dk_ = fft(dk_); - D_ = zeros(1,L); - D_(1) = D1_; % energy seperately quantised - D_(2:k-1) = Dk_(2:k-1); - D_(L-k+1:L) = Dk_(k+1:2*k); - d_ = L*ifft(D_); % back to spectrum at rate L - maskdB_ = real(d_); - - % Finally fix up last 500Hz, taper down 10dB at 4000Hz - - xpts = [ anchor-1 anchor L]; - ypts = [ maskdB_(anchor-1) maskdB_(anchor) (maskdB_(anchor)-10)]; - mask_pp = splinefit(xpts, ypts, 1); - maskdB_ = [maskdB_(1:anchor) ppval(mask_pp, anchor+1:L)]; -endfunction - - - -% determine cumulative mask, using amplitude of each harmonic. Mask is -% sampled across L points in the linear domain - -function maskdB = determine_mask(masker_amps_dB, masker_freqs_kHz, mask_sample_freqs_kHz) - - % calculate and plot masking curve - - maskdB = zeros(1,length(mask_sample_freqs_kHz)); - for m=1:length(masker_freqs_kHz) - %maskdB = max(maskdB, schroeder(masker_freqs_kHz(m), mask_sample_freqs_kHz) + masker_amps_dB(m)); - maskdB = max(maskdB, parabolic_resonator(masker_freqs_kHz(m), mask_sample_freqs_kHz) + masker_amps_dB(m)); - end -end - - -% Sample mask as model for Am - -function [maskdB Am_freqs_kHz] = mask_model(AmdB, Wo, L) - - Am_freqs_kHz = (1:L)*Wo*4/pi; - maskdB = determine_mask(AmdB, Am_freqs_kHz, Am_freqs_kHz); -endfunction - - -% -% Masking functions from http://www.perceptualentropy.com/coder.html#C -% Thanks Jon Boley! -% - -% Calculate the Schroeder masking spectrum for a given frequency and SPL - -function maskdB = schroeder(freq_tone_kHz, mask_sample_freqs_kHz, bark_model=1) - f_kHz = mask_sample_freqs_kHz; - f_Hz = f_kHz*1000; - - % Schroeder Spreading Function - - if bark_model == 0 - dz = bark(freq_tone_kHz*1000)-bark(f_Hz); - end - - if bark_model == 1 - - % Modification by DR: Piecewise linear model that makes bands - % beneath 1.5kHz wider to match the width of F1 and - % "fill in" the spectra better for UV sounds. - - %x1 = 0.5; x2 = 2; - %y1 = 0.5; y2 = 1; - x1 = 0.5; x2 = 3; - y1 = 1; y2 = 3; - - grad = (y2 - y1)/(x2 - x1); - y_int = y1 - grad*x1; - - if freq_tone_kHz <= x1 - y = y1; - end - if (freq_tone_kHz > x1) && (freq_tone_kHz < x2) - y = grad*freq_tone_kHz + y_int; - end - if freq_tone_kHz >= x2 - y = y2; - end - dz = y*(bark(freq_tone_kHz*1000) - bark(f_Hz)); - end - - if bark_model == 2 - - % constant bandwidth model, useful for bg noise and UV - - %dz = bark(freq_tone_kHz*1000) - bark(f_Hz); - dz = 0.2*bark(freq_tone_kHz*1000-f_Hz); - end - - maskdB = 15.81 + 7.5*(dz+0.474) - 17.5*sqrt(1 + (dz+0.474).^2); -endfunction - - -% Converts frequency to bark scale -% Frequency should be specified in Hertz - -function b=bark(f) - b = 13*atan(0.76*f/1000) + 3.5*atan((f/7500).^2); -endfunction - - -% Alternative mask function that has a gentler slope than schroeder. -% Idea is to get sharp formant definition, but also fill in gaps so we -% dont get chunks of spectrum coming and going - -function [maskdB pp] = resonator(freq_tone_kHz, mask_sample_freqs_kHz) - % note all frequencies in kHz - - f1 = 0.1; f2 = 3; - bw1 = 0.1; bw2 = 0.1; - m = (bw2-bw1)/(log10(f2)-log10(f1)); - c = bw1 - m*log10(f1); - - Fs = 8; - slope = -12; % filter falls off by this slope/octave - - maskdB = zeros(1, length(mask_sample_freqs_kHz)); - - % frequency dependant bandwidth - - bw = m*log10(freq_tone_kHz) + c; - printf("freq_tone_kHz: %f bw: %f\n", freq_tone_kHz, bw); - - % Design spline to set shape based on current bandwidth - - x = [-Fs/2 -bw/2 0 +bw/2 +Fs/2]; - delta = slope*log2(Fs/bw); % gain is delta down from -3dB to Fs/2 - y = [-3 + delta, -3, 0, -3, -3 + delta]; - pp = splinefit(x, y, 4); - maskdB = ppval(pp, mask_sample_freqs_kHz - freq_tone_kHz); -endfunction - - -function maskdB = resonator_fast(freq_tone_kHz, mask_sample_freqs_kHz) - - % note all frequencies on kHz - - #{ - max_ind = length(pp_bw); - ind = round(freq_tone_kHz/0.1); - ind = min(ind, max_ind); - ind = max(ind, 1); - #} - %printf("freq_tone_kHz: %f ind: %d\n", freq_tone_kHz, ind); - [maskdB_res1 pp] = resonator(0.5, mask_sample_freqs_kHz); - - maskdB = ppval(pp, mask_sample_freqs_kHz - freq_tone_kHz); - %maskdB = ppval(pp_bw(ind), mask_sample_freqs_kHz - freq_tone_kHz); -endfunction - - -% Alternative mask function that uses parabolas for fast computation - -function maskdB = parabolic_resonator(freq_tone_kHz, mask_sample_freqs_kHz) - - % note all frequencies in kHz - - % bandwidth as a function of log(f) - - f1 = 0.5; f2 = 3; - bw1 = 0.1; bw2 = 0.3; - m = (bw2-bw1)/(log10(f2)-log10(f1)); - c = bw1 - m*log10(f1); - - Fs = 8; - slope = -18; - - % frequency dependant bandwidth - - if freq_tone_kHz < f1 - bw = bw1; - else - bw = m*log10(freq_tone_kHz) + c; - end - %printf("freq_tone_kHz: %f bw: %f\n", freq_tone_kHz, bw); - - % Design parabola to fit bandwidth - - a = -3/((bw/2)^2); - %printf("freq_tone_kHz: %f bw: %f a: %f\n", freq_tone_kHz, bw, a); - - % Design straight line to fit slope - - delta = slope*log2(Fs/bw); % gain is delta down from -3dB to Fs/2 - m1 = 2*delta/Fs; - - maskdB_par = a*((mask_sample_freqs_kHz - freq_tone_kHz).^2); - maskdB_line = m1*abs(mask_sample_freqs_kHz - freq_tone_kHz) - 10; - %indx = find(mask_sample_freqs_kHz < freq_tone_kHz); - %maskdB_line(indx) = -50; - - maskdB = max(maskdB_par, maskdB_line); -endfunction - - -% sampling the mask in one frame using an arbitrary set of samplng frequencies - -function maskdB = resample_mask(model, f, mask_sample_freqs_kHz) - max_amp = 80; - - Wo = model(f,1); - L = min([model(f,2) max_amp-1]); - Am = model(f,3:(L+2)); - AmdB = 20*log10(Am); - masker_freqs_kHz = (1:L)*Wo*4/pi; - maskdB = determine_mask(AmdB, masker_freqs_kHz, mask_sample_freqs_kHz); -endfunction - - -% decimate frame rate of mask, use linear interpolation in the log domain - -function maskdB_ = decimate_frame_rate(model, decimate, f, frames) - max_amp = 80; - - Wo = model(f,1); - L = min([model(f,2) max_amp]); - - % determine frames that bracket the one we need to interp - - left_f = decimate*floor((f-1)/decimate)+1; - right_f = left_f + decimate; - if right_f > frames - right_f = left_f; - end - - % determine fraction of each frame to use - - left_fraction = 1 - mod((f-1),decimate)/decimate; - right_fraction = 1 - left_fraction; - - printf("f: %d left_f: %d right_f: %d left_fraction: %3.2f right_fraction: %3.2f \n", f, left_f, right_f, left_fraction, right_fraction) - - % fit splines to left and right masks - - left_Wo = model(left_f,1); - left_L = min([model(left_f,2) max_amp]); - left_AmdB = 20*log10(model(left_f,3:(left_L+2))); - left_sample_freqs_kHz = (1:left_L)*left_Wo*4/pi; - - right_Wo = model(right_f,1); - right_L = min([model(right_f,2) max_amp]); - right_AmdB = 20*log10(model(right_f,3:(right_L+2))); - right_sample_freqs_kHz = (1:right_L)*right_Wo*4/pi; - - % determine mask for left and right frames, sampling at Wo for this frame - - sample_freqs_kHz = (1:L)*Wo*4/pi; - maskdB_left = interp1(left_sample_freqs_kHz, left_AmdB, sample_freqs_kHz, "extrap"); - maskdB_right = interp1(right_sample_freqs_kHz, right_AmdB, sample_freqs_kHz, "extrap"); - - maskdB_ = left_fraction*maskdB_left + right_fraction*maskdB_right; -endfunction - - -% plot some masking curves, used for working on masking filter changes - -function plot_masking - Fs = 8000; - - figure(1) - mask_sample_freqs_kHz = 0.1:0.025:(Fs/1000)/2; - #{ - maskdB_s0 = schroeder(0.5, mask_sample_freqs_kHz, 0); - plot(mask_sample_freqs_kHz, maskdB_s0,';schroeder 0;'); - maskdB_s1 = schroeder(0.5, mask_sample_freqs_kHz, 1); - plot(mask_sample_freqs_kHz, maskdB_s1,'g;schroeder 1;'); - #} - maskdB_res = parabolic_resonator(0.5, mask_sample_freqs_kHz); - plot(mask_sample_freqs_kHz, maskdB_res,'r;resonator;'); - hold on; - - for f=0.5:0.5:3 - #{ - maskdB_s0 = schroeder(f, mask_sample_freqs_kHz, 0); - plot(mask_sample_freqs_kHz, maskdB_s0); - maskdB_s1 = schroeder(f, mask_sample_freqs_kHz, 1); - plot(mask_sample_freqs_kHz, maskdB_s1,'g'); - #} - maskdB_res = parabolic_resonator(f, mask_sample_freqs_kHz); - plot(mask_sample_freqs_kHz, maskdB_res,'r;resonator;'); - end - hold off; - - axis([0.1 4 -30 0]) - grid - - #{ - %pp_bw = gen_pp_bw; - figure(2) - clf; - maskdB_res = resonator(0.5, mask_sample_freqs_kHz); - plot(mask_sample_freqs_kHz, maskdB_res); - hold on; - maskdB_res_fast = resonator_fast(0.5, mask_sample_freqs_kHz); - plot(mask_sample_freqs_kHz, maskdB_res_fast, "g"); - maskdB_par = parabolic_resonator(0.5, mask_sample_freqs_kHz); - plot(mask_sample_freqs_kHz, maskdB_par, "r"); - hold off; - axis([0 4 -80 0]); - grid - #} -endfunction - - -% produce a scatter diagram of amplitudes - -function amp_scatter(samname) - - model_name = strcat(samname,"_model.txt"); - model = load(model_name); - [frames nc] = size(model); - max_amp = 80; - - Am_out_name = sprintf("%s_am.out", samname); - freqs = []; - ampsdB = []; - - for f=1:frames - - L = min([model(f,2) max_amp-1]); - Wo = model(f,1); - Am = model(f,3:(L+2)); - AmdB = 20*log10(Am); - - maskdB = mask_model(AmdB, Wo, L); - mask_sample_freqs_kHz = (1:L)*Wo*4/pi; - [newmaskdB local_maxima] = make_newmask(maskdB, AmdB, Wo, L, mask_sample_freqs_kHz); - - [nlm tmp] = size(local_maxima); - freqs = [freqs (local_maxima(1:min(4,nlm),2)*Wo*4000/pi)']; - an_ampsdB = local_maxima(1:min(4,nlm),1)'; - ampsdB = [ampsdB an_ampsdB-mean(an_ampsdB)]; - end - - figure(1) - plot(freqs, ampsdB,'+'); - figure(2) - subplot(211) - hist(freqs,20) - subplot(212) - hist(ampsdB,20) -endfunction - - - -% AbyS returns f & a, this function plots values so we can consider quantisation - -function plot_f_a_stats(f,a) - - % freq pdfs - - [fsrt fsrt_ind] = sort(f,2); - fsrt /= 1000; - figure(1) - for i=1:4 - subplot(2,2,i) - hist(fsrt(:,i),50) - printf("%d min: %d max: %d\n", i, min(fsrt(:,i)), max(fsrt(:,i))) - an_axis = axis; - axis([0 4 an_axis(3) an_axis(4)]) - end - - % freq diff pdfs - - figure(2) - for i=1:4 - subplot(2,2,i) - if i == 1 - hist(fsrt(:,i),50) - else - hist(fsrt(:,i) - fsrt(:,i-1),50) - end - an_axis = axis; - axis([0 4 an_axis(3) an_axis(4)]) - end - - % amplitude PDFs - - l = length(a); - for i=1:l - asrt(i,:) = a(i, fsrt_ind(i,:)); - end - - figure(3) - for i=1:4 - subplot(2,2,i) - hist(asrt(:,i) - mean(asrt(:,:),2)) - an_axis = axis; - axis([-40 40 an_axis(3) an_axis(4)]) - end - - % find straight line fit - - for i=1:l - [gradient intercept] = linreg(1000*fsrt(i,:), asrt(i,:), 4); - alinreg(i,:) = gradient*1000*fsrt(i,:) + intercept; - alinregres(i,:) = asrt(i,:) - alinreg(i,:); - m(i) = gradient; c(i) = intercept; - end - - figure(4) - for i=1:4 - subplot(2,2,i) - hist(alinregres(:,i)) - an_axis = axis; - axis([-40 40 an_axis(3) an_axis(4)]) - end - - figure(5) - subplot(211) - m = m(find(m>-0.05)); - m = m(find(m<0.03)); - hist(m,50) - title('gradient'); - subplot(212) - c = c(find(c>0)); - hist(c,50) - title('y-int'); - -endfunction - -function D1_log = decode_from_bit_stream(samname, ber = 0, bit_error_mask = ones(28,1)) - max_amp = 80; - bits_per_param = [6 1 8 8 4 1]; - assert(sum(bits_per_param) == 28); - load vq; - k = 10; - dec_in_time = 1; - train = 0; - decimate = 4; - synth_phase = 1; - - Am_out_name = sprintf("%s_am.out", samname); - Aw_out_name = sprintf("%s_aw.out", samname); - bit_stream_name = strcat(samname,".bit"); - faw = fopen(Aw_out_name,"wb"); - fam = fopen(Am_out_name,"wb"); - faw = fopen(Aw_out_name,"wb"); - - Wo_out_name = sprintf("%s_Wo.out", samname); - fWo = fopen(Wo_out_name,"wb"); - - % read in bit stream and convert to ind_log[] - - ind_log = []; - fbit = fopen(bit_stream_name, "rb"); - bits_per_frame = sum(bits_per_param); - nind = length(bits_per_param); - nerr = 0; nbits = 0; - [frame nread] = fread(fbit, sum(bits_per_param), "uchar"); - while (nread == bits_per_frame) - - % optionally introduce bit errors - - error_bits = rand(sum(bits_per_param), 1) < ber; - error_bits_masked = bitand(error_bits, bit_error_mask); - frame = bitxor(frame, error_bits_masked); - nerr += sum(error_bits_masked); - nbits += sum(bits_per_param); - - % read a frame, convert to indexes - - nbit = 1; - ind = []; - for i=1:nind - field = frame(nbit:nbit+bits_per_param(i)-1); - nbit += bits_per_param(i); - ind = [ind bits_to_index(field, bits_per_param(i))]; - end - ind_log = [ind_log; ind]; - [frame nread] = fread(fbit, sum(bits_per_param), "uchar"); - endwhile - fclose(fbit); - printf("nerr: %d nbits: %d %f\n", nerr, nbits, nerr/nbits); - - % convert ind_log to modem params - - frames = 4*length(ind_log); - model_ = zeros(frames, max_amp+2); - v = zeros(frames,1); - D1_log = []; - - fdec = 1; - for f=1:4:frames - ind_Wo = ind_log(fdec,1); - - Wo = decode_log_Wo(ind_Wo, 6); - L = floor(pi/Wo); - L = min([L max_amp-1]); - model_(f,1) = Wo; - model_(f,2) = L; - - v1 = ind_log(fdec,2); - if (fdec+1) < length(ind_log) - v5 = ind_log(fdec+1,2); - else - v5 = 0; - end - v(f:f+3) = est_voicing_bits(v1, v5); - - ind_vq = ind_log(fdec,3:5) + 1; - [dk_ D1_] = index_to_params(ind_vq, vq); - D1_log = [D1_log; D1_]; - maskdB_ = params_to_mask(L, k, dk_, D1_); - Am_ = zeros(1,max_amp); - Am_ = 10 .^ (maskdB_(1:L)/20); - model_(f,3:(L+2)) = Am_; - - fdec += 1; - end - - % decoder loop ----------------------------------------------------- - - if train - % short circuit decoder - frames = 0; - end - - % run post filter ahead of time so dec in time has post filtered frames to work with - - for f=1:frames - model_(f,:) = post_filter(model_(f,:)); - end - - for f=1:frames - %printf("frame: %d\n", f); - L = min([model_(f,2) max_amp-1]); - Wo = model_(f,1); - Am_ = model_(f,3:(L+2)); - - maskdB_ = 20*log10(Am_); - - if dec_in_time - % decimate mask samples in time - - [maskdB_ Wo L] = decimate_frame_rate2(model_, decimate, f, frames); - model_(f,1) = Wo; - model_(f,2) = L; - end - - Am_ = zeros(1,max_amp); - Am_(2:L) = 10 .^ (maskdB_(1:L-1)/20); % C array doesnt use A[0] - fwrite(fam, Am_, "float32"); - fwrite(fWo, Wo, "float32"); - - if synth_phase - - % synthesis phase spectra from magnitiude spectra using minimum phase techniques - - fft_enc = 512; - model_(f,3:(L+2)) = 10 .^ (maskdB_(1:L)/20); - phase = determine_phase(model_, f); - assert(length(phase) == fft_enc); - Aw = zeros(1, fft_enc*2); - Aw(1:2:fft_enc*2) = cos(phase); - Aw(2:2:fft_enc*2) = -sin(phase); - fwrite(faw, Aw, "float32"); - end - end - - fclose(fam); - fclose(fWo); - if synth_phase - fclose(faw); - end - - % save voicing file - - v_out_name = sprintf("%s_v.txt", samname); - fv = fopen(v_out_name,"wt"); - for f=1:length(v) - fprintf(fv,"%d\n", v(f)); - end - fclose(fv); - -endfunction - - - -% decimate frame rate of mask, use linear interpolation in the log domain - -function [maskdB_ Wo L] = decimate_frame_rate2(model, decimate, f, frames) - max_amp = 80; - - % determine frames that bracket the one we need to interp - - left_f = decimate*floor((f-1)/decimate)+1; - right_f = left_f + decimate; - if right_f > frames - right_f = left_f; - end - - % determine fraction of each frame to use - - left_fraction = 1 - mod((f-1),decimate)/decimate; - right_fraction = 1 - left_fraction; - - % printf("f: %d left_f: %d right_f: %d left_fraction: %3.2f right_fraction: %3.2f \n", f, left_f, right_f, left_fraction, right_fraction) - - % fit splines to left and right masks - - left_Wo = model(left_f,1); - left_L = min([model(left_f,2) max_amp]); - left_AmdB = 20*log10(model(left_f,3:(left_L+2))); - left_mask_sample_freqs_kHz = (1:left_L)*left_Wo*4/pi; - - right_Wo = model(right_f,1); - right_L = min([model(right_f,2) max_amp]); - right_AmdB = 20*log10(model(right_f,3:(right_L+2))); - right_mask_sample_freqs_kHz = (1:right_L)*right_Wo*4/pi; - - % printf(" right_Wo: %f left_Wo: %f right_L: %d left_L %d\n",right_Wo,left_Wo,right_L,left_L); - printf("%f %f\n", left_AmdB(left_L), right_AmdB(right_L)); - - maskdB_left_pp = splinefit(left_mask_sample_freqs_kHz, left_AmdB, left_L); - maskdB_right_pp = splinefit(right_mask_sample_freqs_kHz, right_AmdB, right_L); - - % determine mask for left and right frames, sampling at Wo for this frame - - Wo = left_fraction*left_Wo + right_fraction*right_Wo; - L = floor(pi/Wo); - %Wo = model(f,1); L = model(f,2); - - mask_sample_freqs_kHz = (1:L)*Wo*4/pi; - maskdB_left = ppval(maskdB_left_pp, mask_sample_freqs_kHz); - maskdB_right = ppval(maskdB_right_pp, mask_sample_freqs_kHz); - - maskdB_ = left_fraction*maskdB_left + right_fraction*maskdB_right; -endfunction - -#{ -function amodel = post_filter(amodel) - max_amp = 80; - - % post filter - - L = min([amodel(2) max_amp-1]); - Wo = amodel(1); - Am_ = amodel(3:(L+2)); - AmdB_ = 20*log10(Am_); - AmdB_pf = AmdB_*1.5; - AmdB_pf += max(AmdB_) - max(AmdB_pf); - amodel(3:(L+2)) = 10 .^ (AmdB_pf(1:L)/20); -endfunction -#} - - -% Given a matrix with indexes on each row, convert to a bit stream and -% write to file. We only write every 4th frame due to DIT - -function write_bit_stream_file(fn, ind_log, bits_per_param) - fbit = fopen(fn,"wb"); - decimate = 4; - - % take a row of quantiser indexes, convert to bits, save to file - - [frames nind] = size(ind_log); - for f=1:decimate:frames - frame_of_bits = []; - arow = ind_log(f,:); - for i=1:nind - %printf("i: %d bits_per_param: %d\n", i, bits_per_param(i)); - some_bits = index_to_bits(arow(i), bits_per_param(i)); - frame_of_bits = [frame_of_bits some_bits]; - end - fwrite(fbit, frame_of_bits, "uchar"); - end - fclose(fbit); -endfunction - - - -% determine 4 voicing bits based on 2 decimated voicing bits - -function [v] = est_voicing_bits(v1, v5) - if v1 == v5 - v(1:4) = v1; - else - v(1:2) = v1; - v(3:4) = v5; - end -endfunction - - -function [AmdB_ residual fvec fvec_ amps] = piecewise_model(AmdB, Wo, vq, vq_m) - L = length(AmdB); - l1000 = floor(L/4); - AmdB_ = ones(1,L); - mask_sample_freqs_kHz = (1:L)*Wo*4/pi; - - % fit a resonator to max of first 300 - 1000 Hz - - fmin = 0.150; - lmin = floor(L*fmin/4); - [mx mx_ind] = max(AmdB(lmin+1:l1000)); - amp(1) = mx; - mx_ind += lmin; - AmdB_ = parabolic_resonator(mx_ind*Wo*4/pi, mask_sample_freqs_kHz) + mx; - fr1 = mx_ind*Wo*4/pi; - - % fit a 2nd resonator, must be above 1000Hz - - fmin = 1; - lmin = round(fmin*L/4); - - [mx mx_ind] = max(AmdB(lmin+1:L)); - amp(2) = mx; - mx_ind += lmin; - AmdB_ = max(AmdB_, parabolic_resonator(mx_ind*Wo*4/pi, mask_sample_freqs_kHz) + mx); - fr2 = mx_ind*Wo*4/pi; - - % fit a third resonator, must be +/- 300 Hz after 2nd resonator - - residual = AmdB - AmdB_; - keep_out = [1:lmin]; - lmax = round(L*3500/4000); - keep_out = [1:lmin lmax:L]; - residual(keep_out) = -40; - - fr2 = mx_ind*Wo*4/pi; - fmin = fr2 - 0.300; - fmax = fr2 + 0.300; - lmin = max(1, round(L*fmin/4)); - lmax = min(L, round(L*fmax/4)); - keep_out = [keep_out lmin:lmax]; - - residual = AmdB; - residual(keep_out) = -40; - - if 0 - figure(3); clf; - subplot(211) - plot(mask_sample_freqs_kHz, residual); - end - - [mx mx_ind] = max(residual); - amp(3) = AmdB(mx_ind); - AmdB_ = max(AmdB_, parabolic_resonator(mx_ind*Wo*4/pi, mask_sample_freqs_kHz) + amp(3)); - fr3 = mx_ind*Wo*4/pi; - - % 4th resonator - - fmin = fr3 - 0.300; - fmax = fr3 + 0.300; - - lmin = max(1, round(L*fmin/4)); - lmax = min(L, round(L*fmax/4)); - keep_out = [keep_out lmin:lmax]; - - residual = AmdB - AmdB_; - residual(keep_out) = -40; - - [mx mx_ind] = max(residual); - amp(4) = AmdB(mx_ind); - AmdB_ = max(AmdB_, parabolic_resonator(mx_ind*Wo*4/pi, mask_sample_freqs_kHz) + amp(4)); - fr4 = mx_ind*Wo*4/pi; - - if 0 - subplot(212) - plot(mask_sample_freqs_kHz, residual); - end - - %printf("\nfr1: %f fr2: %f fr3: %f fr4: %f\n", fr1, fr2, fr3, fr4); - [fvec fvec_ind] = sort([fr1 fr2 fr3 fr4]); - amps = amp(fvec_ind(1:4)); - - fvec_ = zeros(1, 4); - - #{ - % optional VQ of frequencies - - if nargin == 4 - AmdB_ = ones(1,L); - [mes fvec_ ind] = mbest(vq, fvec, vq_m); - for i=1:4 - an_amp = amp(fvec_ind(i)); - AmdB_ = max(AmdB_, parabolic_resonator(fvec_(i), mask_sample_freqs_kHz) + an_amp); - end - end - #} - - % optional VQ of amplitudes - - if nargin == 4 - AmdB_ = ones(1,L); - %amps_(1) = amps(1); - %[mes tmp ind] = mbest(vq, amps(2:4) - amps_(1), vq_m); - %amps_(2:4) = amps_(1) + tmp; - [mes amps_ ind] = mbest(vq, amps, vq_m); - amps-amps_ - for i=1:4 - AmdB_ = max(AmdB_, parabolic_resonator(fvec(i), mask_sample_freqs_kHz) + amps_(i)); - end - end - - %amps = amps(2:4) - amps(1); -endfunction - - -% find best place for resonator by closed loop min MSE search - -function lmin = abys(AmdB_, AmdB, Wo, L, mask_sample_freqs_kHz) - lstart = round(L/4); - lmin = lstart; - emin = 1E6; - - printf("lstart: %d L: %d\n", lstart, L); - - figure(3); - subplot(211) - plot(mask_sample_freqs_kHz*1000, AmdB,'r+-'); - - e = zeros(1,L); - for l=lstart:L - - % calc mse - - f_l = l*Wo*4/pi; - AmdB_l = max(AmdB_, parabolic_resonator(f_l, mask_sample_freqs_kHz) + AmdB(l)); - hold on; - if l == 23 - plot(mask_sample_freqs_kHz*1000, AmdB_l,'c'); - end - hold off; - e(l) = sum((AmdB_l - AmdB) .^ 2); - %printf("l: %5d f_l: %4.3f e: %4.0f emin: %4.0f lmin: %5d\n", l, f_l, emin, lmin); - printf("l: %5d f_l: %4.3f e: %4.0f emin: %4.0f lmin: %5d\n", l, f_l, e(l), emin, lmin); - if e(l) < emin - emin = e(l); - lmin = l; - end - end - - subplot(212) - plot(mask_sample_freqs_kHz*1000, e) -endfunction -#} - - diff --git a/octave/tnewamp1.m b/octave/tnewamp1.m index 80a99dc1..f2edd04e 100644 --- a/octave/tnewamp1.m +++ b/octave/tnewamp1.m @@ -129,6 +129,7 @@ function tnewamp1(input_prefix="../build_linux/src/hts1a") voicing_right = voicing(f); [Wo_ avoicing_] = interp_Wo_v(Wo_left, Wo_right, voicing_left, voicing_right); + #{ for i=1:4 fprintf(stderr, " Wo: %4.3f L: %d v: %d\n", Wo_(i), floor(pi/Wo_(i)), avoicing_(i)); end @@ -137,6 +138,7 @@ function tnewamp1(input_prefix="../build_linux/src/hts1a") fprintf(stderr,"%5.3f ", rate_K_surface_(f,i)); end fprintf(stderr,"\n"); + #} if f > M model_(f-M:f-1,1) = Wo_; @@ -189,7 +191,8 @@ function tnewamp1(input_prefix="../build_linux/src/hts1a") passes += check(model_(:,3:max_amp+2), model__c(:,3:max_amp+2), 'rate L Am surface ', 0.1); passes += check(H, H_c(:,1:max_amp), 'phase surface'); printf("passes: %d\n", passes); - + + #{ % Save to disk to check synthesis is OK with c2sim output_prefix = input_prefix; @@ -243,7 +246,8 @@ function tnewamp1(input_prefix="../build_linux/src/hts1a") fprintf(fv,"%d\n", voicing__c(f)); end fclose(fv); - + #} + endfunction diff --git a/unittest/tnewamp1.c b/unittest/tnewamp1.c index 3130beac..e17b2f13 100644 --- a/unittest/tnewamp1.c +++ b/unittest/tnewamp1.c @@ -159,6 +159,7 @@ int main(int argc, char *argv[]) { &mean_[f], &indexes[f][0], NULL, 1); + #ifdef VERBOSE fprintf(stderr,"f: %d Wo: %4.3f L: %d v: %d\n", f, model.Wo, model.L, model.voiced); if ((f % M) == 0) { for(i=0; i<5; i++) { @@ -167,6 +168,7 @@ int main(int argc, char *argv[]) { fprintf(stderr,"\n"); fprintf(stderr," %d %d %d %d\n", indexes[f][0], indexes[f][1], indexes[f][2], indexes[f][3]); } + #endif /* log vectors */ model_octave[f][0] = model.Wo; @@ -212,6 +214,7 @@ int main(int argc, char *argv[]) { &indexes[f][0], NULL, 1); + #ifdef VERBOSE fprintf(stderr,"f: %d\n", f); fprintf(stderr," %d %d %d %d\n", indexes[f][0], indexes[f][1], indexes[f][2], indexes[f][3]); for(i=0; i Date: Sun, 21 Jul 2019 18:04:07 +0930 Subject: [PATCH 15/20] debugging ctest on Travis --- .travis.yml | 1 + octave/newamp_700c.m | 2 +- octave/tnewamp1.m | 3 ++- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0efb3ff6..22576274 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,6 +30,7 @@ script: - mkdir -p $BUILDSTD - cd $BUILDSTD - cmake $CODEC2DEV +- make -j4 - ctest -V -R test_codec2_700c_octave_port #- CTEST_OUTPUT_ON_FAILURE=1 make -j4 all test - mkdir -p $BUILDSTM diff --git a/octave/newamp_700c.m b/octave/newamp_700c.m index 1aee04bb..5b76bcce 100644 --- a/octave/newamp_700c.m +++ b/octave/newamp_700c.m @@ -346,6 +346,6 @@ function save_vq(vqset, filenameprefix) endfunction -function [rate_K_vec eq] = front_eq(rate_vec, eq) +function [rate_K_vec eq] = front_eq(rate_K_vec, eq) endfunction diff --git a/octave/tnewamp1.m b/octave/tnewamp1.m index f2edd04e..3bdcb888 100644 --- a/octave/tnewamp1.m +++ b/octave/tnewamp1.m @@ -77,7 +77,8 @@ function tnewamp1(input_prefix="../build_linux/src/hts1a") for f=1:frames mean_f(f) = mean(rate_K_surface(f,:)); rate_K_surface_no_mean(f,:) = rate_K_surface(f,:) - mean_f(f); - % [rate_K_surface_no_mean(f,:) eq] = front_eq(rate_K_surface_no_mean(f,:), eq); + [rate_K_vec eq] = front_eq(rate_K_surface_no_mean(f,:), eq); + rate_K_surface_no_mean(f,:) = rate_K_vec; end [res rate_K_surface_no_mean_ ind] = mbest(train_120_vq, rate_K_surface_no_mean, m); From 31477208f12c8f13dab6c998fd63826a84c05d95 Mon Sep 17 00:00:00 2001 From: David Date: Sun, 21 Jul 2019 18:12:45 +0930 Subject: [PATCH 16/20] adding octave version of EQ --- .travis.yml | 1 + CMakeLists.txt | 2 +- octave/newamp_700c.m | 8 ++++++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 22576274..fcd523b6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,6 +32,7 @@ script: - cmake $CODEC2DEV - make -j4 - ctest -V -R test_codec2_700c_octave_port +- ctest -V -R test_FDMDV_modem_octave_port #- CTEST_OUTPUT_ON_FAILURE=1 make -j4 all test - mkdir -p $BUILDSTM - cd $BUILDSTM diff --git a/CMakeLists.txt b/CMakeLists.txt index ecc6672b..8de9d6a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -301,7 +301,7 @@ if(UNITTEST) ./c2sim ../../raw/hts1a.raw --phase0 --postfilter --dump hts1a --lpc 10 --dump_pitch_e hts1a_pitche.txt; \ cd ${CMAKE_CURRENT_BINARY_DIR}/unittest; ./tnewamp1 ../../raw/hts1a.raw; \ cd ${CMAKE_CURRENT_SOURCE_DIR}/octave; pwd; \ - octave --no-gui -qf tnewamp1.m") + octave --no-gui -qf ${CMAKE_CURRENT_SOURCE_DIR}/octave/tnewamp1.m") set_tests_properties(test_codec2_700c_octave_port PROPERTIES PASS_REGULAR_EXPRESSION "passes: 8") add_test(NAME test_FDMDV_modem_octave_port diff --git a/octave/newamp_700c.m b/octave/newamp_700c.m index 5b76bcce..ff5c6625 100644 --- a/octave/newamp_700c.m +++ b/octave/newamp_700c.m @@ -346,6 +346,14 @@ function save_vq(vqset, filenameprefix) endfunction +% Equaliser in front of EQ, see vq_70c_eq.m for development version + function [rate_K_vec eq] = front_eq(rate_K_vec, eq) + [tmp K] = size(rate_K_vec); + ideal = [ 8 10 12 14 14*ones(1,K-1-4) -20]; + gain = 0.02; + update = rate_K_vec - ideal; + eq = (1-gain)*eq + gain*update; + eq(find(eq < 0)) = 0; endfunction From 637bf52d8d0b491c5fce89c8e83fc74a301ea1ac Mon Sep 17 00:00:00 2001 From: David Date: Sun, 21 Jul 2019 18:20:07 +0930 Subject: [PATCH 17/20] trying a non function script --- CMakeLists.txt | 2 +- octave/run_tnewamp1.m | 1 + octave/tnewamp1.m | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 octave/run_tnewamp1.m diff --git a/CMakeLists.txt b/CMakeLists.txt index 8de9d6a3..019e37e1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -301,7 +301,7 @@ if(UNITTEST) ./c2sim ../../raw/hts1a.raw --phase0 --postfilter --dump hts1a --lpc 10 --dump_pitch_e hts1a_pitche.txt; \ cd ${CMAKE_CURRENT_BINARY_DIR}/unittest; ./tnewamp1 ../../raw/hts1a.raw; \ cd ${CMAKE_CURRENT_SOURCE_DIR}/octave; pwd; \ - octave --no-gui -qf ${CMAKE_CURRENT_SOURCE_DIR}/octave/tnewamp1.m") + octave --no-gui -qf run_tnewamp1.m") set_tests_properties(test_codec2_700c_octave_port PROPERTIES PASS_REGULAR_EXPRESSION "passes: 8") add_test(NAME test_FDMDV_modem_octave_port diff --git a/octave/run_tnewamp1.m b/octave/run_tnewamp1.m new file mode 100644 index 00000000..2cc1ed3a --- /dev/null +++ b/octave/run_tnewamp1.m @@ -0,0 +1 @@ +tnewamp1("../build_linux/src/hts1a") diff --git a/octave/tnewamp1.m b/octave/tnewamp1.m index 3bdcb888..c0ff337a 100644 --- a/octave/tnewamp1.m +++ b/octave/tnewamp1.m @@ -34,7 +34,7 @@ | play -q -t raw -r 8000 -s -2 - #} -function tnewamp1(input_prefix="../build_linux/src/hts1a") +function tnewamp1(input_prefix) printf("starting tnewamp1.c input_prefix: %s\n", input_prefix); newamp_700c; From 3cbc01cce050b036cc5b0e592681b638fc2ebc07 Mon Sep 17 00:00:00 2001 From: David Date: Sun, 21 Jul 2019 18:57:19 +0930 Subject: [PATCH 18/20] first pass at equaliser in C --- .travis.yml | 4 +--- CMakeLists.txt | 8 ++++---- octave/run_tnewamp1.m | 6 +++++- octave/tnewamp1.m | 23 ++++++++++++----------- src/codec2.c | 3 ++- src/codec2_internal.h | 1 + src/newamp1.c | 20 ++++++++++++++++++-- src/newamp1.h | 3 ++- unittest/tnewamp1.c | 12 +++++++++--- 9 files changed, 54 insertions(+), 26 deletions(-) diff --git a/.travis.yml b/.travis.yml index fcd523b6..f13cf45e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,9 +31,7 @@ script: - cd $BUILDSTD - cmake $CODEC2DEV - make -j4 -- ctest -V -R test_codec2_700c_octave_port -- ctest -V -R test_FDMDV_modem_octave_port -#- CTEST_OUTPUT_ON_FAILURE=1 make -j4 all test +- CTEST_OUTPUT_ON_FAILURE=1 make -j4 all test - mkdir -p $BUILDSTM - cd $BUILDSTM - if [ -e $STDLIBDIR ]; then (ln -s $STDLIBDIR . && cmake $CODEC2DEV/stm32 -DPERIPHLIBDIR="$STDLIBDIR" diff --git a/CMakeLists.txt b/CMakeLists.txt index 019e37e1..3ae166d3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -298,11 +298,11 @@ if(UNITTEST) add_test(NAME test_codec2_700c_octave_port COMMAND sh -c "cd ${CMAKE_CURRENT_BINARY_DIR}/src; - ./c2sim ../../raw/hts1a.raw --phase0 --postfilter --dump hts1a --lpc 10 --dump_pitch_e hts1a_pitche.txt; \ - cd ${CMAKE_CURRENT_BINARY_DIR}/unittest; ./tnewamp1 ../../raw/hts1a.raw; \ - cd ${CMAKE_CURRENT_SOURCE_DIR}/octave; pwd; \ + ./c2sim ../../raw/cq_ref.raw --phase0 --postfilter --dump cq_ref --lpc 10 --dump_pitch_e cq_ref_pitche.txt; \ + cd ${CMAKE_CURRENT_BINARY_DIR}/unittest; ./tnewamp1 ../../raw/cq_ref.raw; \ + cd ${CMAKE_CURRENT_SOURCE_DIR}/octave; \ octave --no-gui -qf run_tnewamp1.m") - set_tests_properties(test_codec2_700c_octave_port PROPERTIES PASS_REGULAR_EXPRESSION "passes: 8") + set_tests_properties(test_codec2_700c_octave_port PROPERTIES PASS_REGULAR_EXPRESSION "fails: 0") add_test(NAME test_FDMDV_modem_octave_port COMMAND sh -c "$ && octave --no-gui -qf ${CMAKE_CURRENT_SOURCE_DIR}/octave/tfdmdv.m" diff --git a/octave/run_tnewamp1.m b/octave/run_tnewamp1.m index 2cc1ed3a..8972f0ca 100644 --- a/octave/run_tnewamp1.m +++ b/octave/run_tnewamp1.m @@ -1 +1,5 @@ -tnewamp1("../build_linux/src/hts1a") +% Needed this to keep Travis happy, I guess on that version of +% Linux/Octave, octave functions can't be invoked from the command +% line, just scripts + +tnewamp1("../build_linux/src/cq_ref") diff --git a/octave/tnewamp1.m b/octave/tnewamp1.m index c0ff337a..92094f48 100644 --- a/octave/tnewamp1.m +++ b/octave/tnewamp1.m @@ -80,7 +80,7 @@ function tnewamp1(input_prefix) [rate_K_vec eq] = front_eq(rate_K_surface_no_mean(f,:), eq); rate_K_surface_no_mean(f,:) = rate_K_vec; end - + [res rate_K_surface_no_mean_ ind] = mbest(train_120_vq, rate_K_surface_no_mean, m); for f=1:frames @@ -182,16 +182,17 @@ function tnewamp1(input_prefix) figure(3); clf; mesh(abs(H - H_c(:,1:max_amp))); - passes = 0; - passes += check(rate_K_surface, rate_K_surface_c, 'rate_K_surface', 0.01); - passes += check(mean_f, mean_c, 'mean', 0.01); - passes += check(rate_K_surface_, rate_K_surface__c, 'rate_K_surface_', 0.01); - passes += check(interpolated_surface_, interpolated_surface__c, 'interpolated_surface_', 0.01); - passes += check(model_(:,1), model__c(:,1), 'interpolated Wo_', 0.001); - passes += check(voicing_, voicing__c, 'interpolated voicing'); - passes += check(model_(:,3:max_amp+2), model__c(:,3:max_amp+2), 'rate L Am surface ', 0.1); - passes += check(H, H_c(:,1:max_amp), 'phase surface'); - printf("passes: %d\n", passes); + passes = 0; tests = 0; + passes += check(eq, eq_c, 'Equaliser', 0.01); tests++; + passes += check(rate_K_surface, rate_K_surface_c, 'rate_K_surface', 0.01); tests++; + passes += check(mean_f, mean_c, 'mean', 0.01); tests++; + passes += check(rate_K_surface_, rate_K_surface__c, 'rate_K_surface_', 0.01); tests++; + passes += check(interpolated_surface_, interpolated_surface__c, 'interpolated_surface_', 0.01); tests++; + passes += check(model_(:,1), model__c(:,1), 'interpolated Wo_', 0.001); tests++; + passes += check(voicing_, voicing__c, 'interpolated voicing'); tests++; + passes += check(model_(:,3:max_amp+2), model__c(:,3:max_amp+2), 'rate L Am surface ', 0.1); tests++; + passes += check(H, H_c(:,1:max_amp), 'phase surface'); tests++; + printf("passes: %d fails: %d\n", passes, tests - passes); #{ % Save to disk to check synthesis is OK with c2sim diff --git a/src/codec2.c b/src/codec2.c index 840fe213..1bd8076a 100644 --- a/src/codec2.c +++ b/src/codec2.c @@ -221,6 +221,7 @@ struct CODEC2 * codec2_create(int mode) int k; for(k=0; kprev_rate_K_vec_[k] = 0.0; + c2->eq[k] = 0.0; } c2->Wo_left = 0.0; c2->voicing_left = 0;; @@ -1987,7 +1988,7 @@ void codec2_encode_700c(struct CODEC2 *c2, unsigned char * bits, short speech[]) K, &mean, rate_K_vec_no_mean, - rate_K_vec_no_mean_, &c2->se); + rate_K_vec_no_mean_, &c2->se, c2->eq); c2->nse += K; #ifndef CORTEX_M4 diff --git a/src/codec2_internal.h b/src/codec2_internal.h index 498a6c4a..e6cfde1f 100644 --- a/src/codec2_internal.h +++ b/src/codec2_internal.h @@ -82,6 +82,7 @@ struct CODEC2 { unsigned int nse; /* number of terms in sum */ float *user_rate_K_vec_no_mean_; /* optional, user supplied vector for quantisation experiments */ int post_filter_en; + float eq[NEWAMP1_K]; /* optional equaliser */ /*newamp2 states (also uses newamp1 states )*/ float energy_prev; diff --git a/src/newamp1.c b/src/newamp1.c index 575620ab..d89e282d 100644 --- a/src/newamp1.c +++ b/src/newamp1.c @@ -415,7 +415,8 @@ void newamp1_model_to_indexes(C2CONST *c2const, float *mean, float rate_K_vec_no_mean[], float rate_K_vec_no_mean_[], - float *se + float *se, + float *eq ) { int k; @@ -429,9 +430,24 @@ void newamp1_model_to_indexes(C2CONST *c2const, float sum = 0.0; for(k=0; k Date: Sun, 21 Jul 2019 19:55:35 +0930 Subject: [PATCH 19/20] VQEQ working in C code, C output samples sound very similar to Octave simulation, doing a reasonable job at making speech sound better --- octave/vq_700c_eq.m | 3 ++- src/c2enc.c | 11 ++++++++--- src/codec2.c | 7 ++++++- src/codec2.h | 5 ++++- src/codec2_internal.h | 1 + src/newamp1.c | 33 +++++++++++++++------------------ src/newamp1.h | 3 ++- unittest/tnewamp1.c | 2 +- 8 files changed, 39 insertions(+), 26 deletions(-) diff --git a/octave/vq_700c_eq.m b/octave/vq_700c_eq.m index 76fa3f37..0a73509b 100644 --- a/octave/vq_700c_eq.m +++ b/octave/vq_700c_eq.m @@ -2,7 +2,7 @@ % David Rowe May 2019 % % Researching Codec 2 700C VQ equaliser ideas -% See also scripts/train_700c_quant.sh +% See also scripts/train_700c_quant.sh, tnewamp1.m melvq; @@ -190,6 +190,7 @@ function save_f32(fn, m) [targets e] = load_targets(fn_targets{i}); eq1 = est_eq(vq1, targets); eq2s = est_eq_front(targets); + % for these simulation uses fixed EQ sample, rather than letting it vary frame by frame eq2 = eq2s(end,:); % first stage VQ ----------------- diff --git a/src/c2enc.c b/src/c2enc.c index d378d790..c33d3310 100644 --- a/src/c2enc.c +++ b/src/c2enc.c @@ -48,9 +48,10 @@ int main(int argc, char *argv[]) char *unpacked_bits_char; int bit, byte,i; int report_var = 0; + int eq = 0; if (argc < 4) { - printf("usage: c2enc 3200|2400|1600|1400|1300|1200|700|700B|700C|450|450PWB InputRawspeechFile OutputBitFile [--natural] [--softdec] [--bitperchar] [--mlfeat] [--loadcb stageNum Filename] [--var]\n"); + printf("usage: c2enc 3200|2400|1600|1400|1300|1200|700|700B|700C|450|450PWB InputRawspeechFile OutputBitFile [--natural] [--softdec] [--bitperchar] [--mlfeat] [--loadcb stageNum Filename] [--var] [--eq]\n"); printf("e.g c2enc 1400 ../raw/hts1a.raw hts1a.c2\n"); printf("e.g c2enc 1300 ../raw/hts1a.raw hts1a.c2 --natural\n"); exit(1); @@ -144,10 +145,14 @@ int main(int argc, char *argv[]) if (strcmp(argv[i], "--var") == 0) { report_var = 1; } - + if (strcmp(argv[i], "--eq") == 0) { + eq = 1; + } } codec2_set_natural_or_gray(codec2, gray); + codec2_700c_eq(codec2, eq); + //fprintf(stderr,"gray: %d softdec: %d\n", gray, softdec); while(fread(buf, sizeof(short), nsam, fin) == (size_t)nsam) { @@ -186,7 +191,7 @@ int main(int argc, char *argv[]) if (report_var) { float var = codec2_get_var(codec2); - fprintf(stderr, "%s var: %f std: %f\n", argv[2], var, sqrt(var)); + fprintf(stderr, "%s var: %5.2f std: %5.2f\n", argv[2], var, sqrt(var)); } codec2_destroy(codec2); diff --git a/src/codec2.c b/src/codec2.c index 1bd8076a..6735dc28 100644 --- a/src/codec2.c +++ b/src/codec2.c @@ -223,6 +223,7 @@ struct CODEC2 * codec2_create(int mode) c2->prev_rate_K_vec_[k] = 0.0; c2->eq[k] = 0.0; } + c2->eq_en = 0; c2->Wo_left = 0.0; c2->voicing_left = 0;; c2->phase_fft_fwd_cfg = codec2_fft_alloc(NEWAMP1_PHASE_NFFT, 0, NULL, NULL); @@ -1988,7 +1989,7 @@ void codec2_encode_700c(struct CODEC2 *c2, unsigned char * bits, short speech[]) K, &mean, rate_K_vec_no_mean, - rate_K_vec_no_mean_, &c2->se, c2->eq); + rate_K_vec_no_mean_, &c2->se, c2->eq, c2->eq_en); c2->nse += K; #ifndef CORTEX_M4 @@ -2720,3 +2721,7 @@ float *codec2_enable_user_ratek(struct CODEC2 *codec2_state, int *K) { void codec2_700c_post_filter(struct CODEC2 *codec2_state, int en) { codec2_state->post_filter_en = en; } + +void codec2_700c_eq(struct CODEC2 *codec2_state, int en) { + codec2_state->eq_en = en; +} diff --git a/src/codec2.h b/src/codec2.h index 1bd4289a..5af94003 100644 --- a/src/codec2.h +++ b/src/codec2.h @@ -111,13 +111,16 @@ int codec2_rebuild_spare_bit(struct CODEC2 *codec2_state, int unpacked_bits[]); void codec2_set_natural_or_gray(struct CODEC2 *codec2_state, int gray); void codec2_set_softdec(struct CODEC2 *c2, float *softdec); float codec2_get_energy(struct CODEC2 *codec2_state, const unsigned char *bits); - + // support for ML and VQ experiments void codec2_open_mlfeat(struct CODEC2 *codec2_state, char *filename); void codec2_load_codebook(struct CODEC2 *codec2_state, int num, char *filename); float codec2_get_var(struct CODEC2 *codec2_state); float *codec2_enable_user_ratek(struct CODEC2 *codec2_state, int *K); + +// 700C post filter and equaliser void codec2_700c_post_filter(struct CODEC2 *codec2_state, int en); +void codec2_700c_eq(struct CODEC2 *codec2_state, int en); #endif diff --git a/src/codec2_internal.h b/src/codec2_internal.h index e6cfde1f..400249c2 100644 --- a/src/codec2_internal.h +++ b/src/codec2_internal.h @@ -83,6 +83,7 @@ struct CODEC2 { float *user_rate_K_vec_no_mean_; /* optional, user supplied vector for quantisation experiments */ int post_filter_en; float eq[NEWAMP1_K]; /* optional equaliser */ + int eq_en; /*newamp2 states (also uses newamp1 states )*/ float energy_prev; diff --git a/src/newamp1.c b/src/newamp1.c index d89e282d..8980ac60 100644 --- a/src/newamp1.c +++ b/src/newamp1.c @@ -416,17 +416,16 @@ void newamp1_model_to_indexes(C2CONST *c2const, float rate_K_vec_no_mean[], float rate_K_vec_no_mean_[], float *se, - float *eq + float *eq, + int eq_en ) { int k; /* convert variable rate L to fixed rate K */ - resample_const_rate_f(c2const, model, rate_K_vec, rate_K_sample_freqs_kHz, K); - /* remove mean and two stage VQ */ - + /* remove mean */ float sum = 0.0; for(k=0; kvoiced) { int index = encode_log_Wo(c2const, model->Wo, 6); if (index == 0) { diff --git a/src/newamp1.h b/src/newamp1.h index b8c461ed..8c188138 100644 --- a/src/newamp1.h +++ b/src/newamp1.h @@ -56,7 +56,8 @@ void newamp1_model_to_indexes(C2CONST *c2const, float rate_K_vec_no_mean[], float rate_K_vec_no_mean_[], float *se, - float *eq); + float *eq, + int eq_en); void newamp1_indexes_to_rate_K_vec(float rate_K_vec_[], float rate_K_vec_no_mean_[], float rate_K_sample_freqs_kHz[], diff --git a/unittest/tnewamp1.c b/unittest/tnewamp1.c index f2281b1e..e0ed5341 100644 --- a/unittest/tnewamp1.c +++ b/unittest/tnewamp1.c @@ -155,7 +155,7 @@ int main(int argc, char *argv[]) { &rate_K_surface_no_mean[f][0], &rate_K_surface_no_mean_[f][0], &se, - eq); + eq, 0); newamp1_indexes_to_rate_K_vec(&rate_K_surface_[f][0], &rate_K_surface_no_mean_[f][0], From 66fe72315c2d5e0927ca94a20ea7fc72475e307d Mon Sep 17 00:00:00 2001 From: David Date: Wed, 24 Jul 2019 06:36:44 +0930 Subject: [PATCH 20/20] updated fig for blog post --- octave/vq_700c_eq.m | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/octave/vq_700c_eq.m b/octave/vq_700c_eq.m index 0a73509b..2334f50d 100644 --- a/octave/vq_700c_eq.m +++ b/octave/vq_700c_eq.m @@ -306,7 +306,8 @@ function experiment_iterate_block(fn_vq_txt, fn_target_f32) endfunction % Experiment to test EQ of input (before) VQ. We set a threshold on -% when to equalise, so we don't upset already flat-ish samples. +% when to equalise, so we don't upset already flat-ish samples. This +% is the algorithm used for C at the time of writing (newamp1.c, newamp_700c.m) function experiment_front_eq(fn_vq_txt, fn_target_f32) K = 20; @@ -323,7 +324,8 @@ function experiment_front_eq(fn_vq_txt, fn_target_f32) plot(mean(targets)-eqs(end,:), 'c;equalised;'); plot(mean(vq),'b--;mean(vq);'); hold off; - figure(2); clf; mesh(eqs); + figure(2); clf; mesh(eqs(1:100,:)); title('EQ weights over time'); + ylabel('Time (frames'); xlabel('Freq (mel)'); endfunction more off @@ -332,9 +334,9 @@ function experiment_front_eq(fn_vq_txt, fn_target_f32) % You'll need to run scripts/train_700C_quant.sh first to generate the .f32 files %interactive("train_120_1.txt", "cq_freedv_8k_lfboost.f32") -table_across_samples; +%table_across_samples; %vq_700c_plots({"hts1a.f32" "hts2a.f32" "ve9qrp_10s.f32" "ma01_01.f32" "train_120_1.txt"}) %vq_700c_plots({"ve9qrp_10s.f32" "cq_freedv_8k_lfboost.f32" "cq_ref.f32" "hts1a.f32" "vk5qi.f32"}) %experiment_iterate_block("train_120_1.txt", "ve9qrp_10s.f32") %experiment_iterate_block("train_120_1.txt", "cq_freedv_8k_lfboost.f32") -%experiment_front_eq("train_120_1.txt", "cq_freedv_8k_lfboost.f32") +experiment_front_eq("train_120_1.txt", "cq_freedv_8k_lfboost.f32")