From c07e9082f41df81156c9b5a4f9874a9f809be9ad Mon Sep 17 00:00:00 2001 From: drowe67 Date: Sat, 9 Apr 2016 01:32:43 +0000 Subject: [PATCH] think I have bit stream working, sounds OK git-svn-id: https://svn.code.sf.net/p/freetel/code@2776 01035d8c-6547-0410-b346-abe4f91aad63 --- codec2-dev/octave/newamp.m | 13 +-- codec2-dev/octave/newamp_batch.m | 174 ++++++++++++++++++++++++++++--- codec2-dev/src/c2sim.c | 16 ++- 3 files changed, 179 insertions(+), 24 deletions(-) diff --git a/codec2-dev/octave/newamp.m b/codec2-dev/octave/newamp.m index f51ebd3b..4e9133b4 100644 --- a/codec2-dev/octave/newamp.m +++ b/codec2-dev/octave/newamp.m @@ -70,7 +70,7 @@ function [maskdB_ maskdB_cyclic Dabs dk_ D1 ind] = decimate_in_freq(maskdB, cycl [tmp D1_ind] = quantise(0:(2000/15):2500, D1); ind = [vq_ind D1_ind]; [dk_ D1_] = index_to_params(ind, vq); - printf(" vq: %4.1f D1: %4.1f\n", std(dk_ - dk), D1_- D1); + %printf(" vq: %4.1f D1: %4.1f\n", std(dk_ - dk), D1_- D1); else dk_ = dk; D1_ = D1; @@ -117,7 +117,7 @@ function maskdB_ = params_to_mask(L, k, dk_, D1_) Dk_ = fft(dk_); D_ = zeros(1,L); - D_(1) = D1_; % energy seprately quantised + 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_ = ifft(D_); % back to spectrum at rate L @@ -131,6 +131,7 @@ function maskdB_ = params_to_mask(L, k, dk_, D1_) maskdB_ = [maskdB_(1:anchor) ppval(mask_pp, anchor+1:L)]; endfunction + function index = encode_log_Wo(Wo, bits) Wo_levels = 2.^bits; Wo_min = 2*pi/160; @@ -799,12 +800,9 @@ endfunction % decimate frame rate of mask, use linear interpolation in the log domain -function maskdB_ = decimate_frame_rate(model, decimate, f, frames, mask_sample_freqs_kHz) +function [maskdB_ Wo L] = decimate_frame_rate(model, decimate, f, frames, mask_sample_freqs_kHz) 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; @@ -837,6 +835,9 @@ function maskdB_ = decimate_frame_rate(model, decimate, f, frames, mask_sample_f % 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); + 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); diff --git a/codec2-dev/octave/newamp_batch.m b/codec2-dev/octave/newamp_batch.m index 65d019d7..eb9fa540 100644 --- a/codec2-dev/octave/newamp_batch.m +++ b/codec2-dev/octave/newamp_batch.m @@ -12,6 +12,13 @@ % $ cd ~/codec2-dev/octave % octave:14> newamp_batch("../build_linux/src/hts1a") % ~/codec2-dev/build_linux/src$ ./c2sim ../../raw/hts1a.raw --amread hts1a_am.out -o - | play -t raw -r 8000 -s -2 - +% + +% Generate voicing file: +% $ ./c2sim ../../raw/hts2a.raw --dump hts2a --lpc 10 --phase0 --dump_pitch_e hts2a_pitche.txt + +% Bit stream decode: +% $ ./c2sim ../../raw/hts2a.raw --amead hts2a_am.out --awread hts2a_aw.out --Woread hts2a_Wo.out --phase0 --postfilter -o - | play -t raw -r 8000 -s -2 - % process a whole file and write results @@ -32,6 +39,13 @@ function [dk_log D1_log] = newamp_batch(samname, optional_Am_out_name, optional_ model_name = strcat(samname,"_model.txt"); model = load(model_name); [frames nc] = size(model); + %frames = 5; + + voicing_name = strcat(samname,"_pitche.txt"); + if exist(voicing_name, "file") == 2 + pitche = load(voicing_name); + voicing = pitche(:, 3); + end model_ = zeros(frames, nc); non_masked_m = zeros(frames,max_amp); @@ -57,8 +71,7 @@ function [dk_log D1_log] = newamp_batch(samname, optional_Am_out_name, optional_ sd_sum = 0; for f=1:frames printf("%d ", f); - model_(f,2) = L = min([model(f,2) max_amp-1]); - model_(f,1) = Wo = model(f,1); + Wo = model(f,1); L = model(f,2); model_(f,3:(L+2)) = Am = model(f,3:(L+2)); AmdB = 20*log10(Am); @@ -91,8 +104,7 @@ function [dk_log D1_log] = newamp_batch(samname, optional_Am_out_name, optional_ AmdB_ = AmdB; if dec_in_freq if vq_en - [AmdB_ tmp1 Dabs dk_ D1 ind] = decimate_in_freq(maskdB, 1, 10, vq); - ind_log = [ind_log; ind]; + [AmdB_ tmp1 Dabs dk_ D1 ind_vq] = decimate_in_freq(maskdB, 1, 10, vq); else [AmdB_ tmp1 D dk_ D1] = decimate_in_freq(maskdB, 0, 10); end @@ -103,13 +115,26 @@ function [dk_log D1_log] = newamp_batch(samname, optional_Am_out_name, optional_ end sd_sum += std(maskdB - AmdB_); + ind_Wo = encode_log_Wo(Wo, 6); + if vq_en + ind_log = [ind_log; ind_Wo voicing(f) (ind_vq-1) 0]; + end + model_(f,1) = Wo_ = decode_log_Wo(ind_Wo, 6); + L_ = floor(pi/Wo); + model_(f,2) = L_ = min([L_ max_amp-1]); + L_ = min(L_, length(AmdB_)); Am_ = zeros(1,max_amp); - Am_ = 10 .^ (AmdB_(1:L-1)/20); - model_(f,3:(L+1)) = Am_; + Am_ = 10 .^ (AmdB_(1:L_)/20); + model_(f,3:(L_+2)) = Am_; + printf("Wo: %f Wo_: %f L: %d L_: %d\n", Wo, Wo_, L, L_); end if train == 0 - decode_model(model_, Am_out_name, Aw_out_name, synth_phase, dec_in_time); + bit_stream_name = strcat(samname,".bit"); + bits_per_param = [6 1 8 8 4 1]; + write_bit_stream_file(bit_stream_name, ind_log, bits_per_param); + %decode_model(model_, samname, synth_phase, dec_in_time); + decode_bit_stream_file(samname, bits_per_param); end printf("\nsd_sum: %5.2f\n", sd_sum/frames); @@ -117,24 +142,136 @@ function [dk_log D1_log] = newamp_batch(samname, optional_Am_out_name, optional_ endfunction -% generate array of indexes -% convert to bits and save to file of one char/bit -% function to encode and save to file of bits -% function to decode from file of bits -% quantise Wo -% move voicing bit through, move Wo through, maybe just load Wo and L and v? +% 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"); + arow + frame_of_bits + + end + + fclose(fbit); +endfunction + + +% Decode from a bit stream file + +function decode_bit_stream_file(samname, bits_per_param) + max_amp = 80; + nc = max_amp + 3; + load vq; + [tmp1 k2 tmp2] = size(vq) + k = k2/2; + + bit_stream_name = strcat(samname,".bit") + fbit = fopen(bit_stream_name, "rb"); + + model_= []; log_v = []; + nind = length(bits_per_param); + bits_per_frame = sum(bits_per_param); + + % read a frame, decode to indexes, fill in model_ array + + [frame nread] = fread(fbit, sum(bits_per_param), "uchar"); + while (nread == bits_per_frame) + + % 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 + + % convert index to model parameters + + amodel_ = zeros(1,nc); + amodel_(1) = Wo_ = decode_log_Wo(ind(1), 6); + L_ = floor(pi/Wo_); + amodel_(2) = L_ = min([L_ max_amp-1]); + + [dk_ D1_] = index_to_params(ind(3:5)+1, vq); + AmdB_ = params_to_mask(L_, k, dk_, D1_); + + Am_ = zeros(1,max_amp); + Am_ = 10 .^ (AmdB_(1:L_)/20); + amodel_(3:(L_+2)) = Am_; + model_ = [ model_; amodel_; zeros(3,nc)]; + + log_v = [log_v ind(2)]; + + % read next frame + + [frame nread] = fread(fbit, sum(bits_per_param), "uchar"); + endwhile + + % decode entire array of model parameters + + decode_model(model_, samname, 1, 1); + + % save voicing file + + v_out_name = sprintf("%s_v.txt", samname); + fv = fopen(v_out_name,"wt"); + for f=1:length(log_v) + for i=1:4 + fprintf(fv,"%d\n",log_v(f)); + end + end + fclose(fv); +endfunction + + +% convert index to binary bits + +function bits = index_to_bits(value, numbits) + levels = 2.^numbits; + bits = zeros(1, numbits); + for b=1:numbits + bits(b) = bitand(value,2^(numbits-b)) != 0; + end +end + + +function value = bits_to_index(bits, numbits) + value = 2.^(numbits-1:-1:0) * bits; +endfunction + -function decode_model(model_, Am_out_name, Aw_out_name, synth_phase, dec_in_time) +function decode_model(model_, samname, synth_phase, dec_in_time) max_amp = 80; + Am_out_name = sprintf("%s_am.out", samname); + Aw_out_name = sprintf("%s_aw.out", samname); + Wo_out_name = sprintf("%s_Wo.out", samname); fam = fopen(Am_out_name,"wb"); + fWo = fopen(Wo_out_name,"wb"); if synth_phase faw = fopen(Aw_out_name,"wb"); end % decoder loop ----------------------------------------------------- - [frames tmp] = size(model_); + [frames tmp] = size(model_) + for f=1:frames %printf("frame: %d\n", f); L = min([model_(f,2) max_amp-1]); @@ -142,6 +279,7 @@ function decode_model(model_, Am_out_name, Aw_out_name, synth_phase, dec_in_time Am_ = model_(f,3:(L+2)); AmdB_ = 20*log10(Am_); sample_freqs_kHz = (1:L)*Wo*4/pi; + %printf("Wo: %f Wo_: %f L: %d L_: %d\n", Wo, Wo_, L, L_); % run post filter ahead of time so dec in time has post filtered frames to work with @@ -153,18 +291,21 @@ function decode_model(model_, Am_out_name, Aw_out_name, synth_phase, dec_in_time % decimate mask samples in time decimate = 4; - AmdB_ = decimate_frame_rate(model_, decimate, f, frames, sample_freqs_kHz); + [AmdB_ Wo L] = decimate_frame_rate(model_, decimate, f, frames, sample_freqs_kHz); end Am_ = zeros(1,max_amp); Am_(2:L) = 10 .^ (AmdB_(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,1) = Wo; + model_(f,2) = L; model_(f,3:(L+2)) = 10 .^ (AmdB_(1:L)/20); phase = determine_phase(model_, f); assert(length(phase) == fft_enc); @@ -177,6 +318,7 @@ function decode_model(model_, Am_out_name, Aw_out_name, synth_phase, dec_in_time end fclose(fam); + fclose(fWo); fclose(faw); endfunction diff --git a/codec2-dev/src/c2sim.c b/codec2-dev/src/c2sim.c index bebb7288..523f2ffb 100644 --- a/codec2-dev/src/c2sim.c +++ b/codec2-dev/src/c2sim.c @@ -142,8 +142,8 @@ int main(int argc, char *argv[]) int bpfb_en = 0; float bpf_buf[BPF_N+N]; float lspmelvq_mse = 0.0; - int amread; - FILE *fam; + int amread, Woread; + FILE *fam, *fWo; int awread; FILE *faw; @@ -182,6 +182,7 @@ int main(int argc, char *argv[]) { "bpfb", no_argument, &bpfb_en, 1 }, { "amread", required_argument, &amread, 1 }, { "awread", required_argument, &awread, 1 }, + { "Woread", required_argument, &Woread, 1 }, #ifdef DUMP { "dump", required_argument, &dump, 1 }, #endif @@ -278,6 +279,12 @@ int main(int argc, char *argv[]) optarg, strerror(errno)); exit(1); } + } else if(strcmp(long_options[option_index].name, "Woread") == 0) { + if ((fWo = fopen(optarg,"rb")) == NULL) { + fprintf(stderr, "Error opening float Wo file: %s: %s.\n", + optarg, strerror(errno)); + exit(1); + } } else if(strcmp(long_options[option_index].name, "amread") == 0) { if ((fam = fopen(optarg,"rb")) == NULL) { fprintf(stderr, "Error opening float Am file: %s: %s.\n", @@ -756,6 +763,11 @@ int main(int argc, char *argv[]) assert(ret == MAX_AMP); } + if (Woread) { + int ret = fread(&model.Wo, sizeof(float), 1, fWo); + assert(ret == 1); + } + /*------------------------------------------------------------*\ Synthesise and optional decimation to 20 or 40ms frame rate -- 2.25.1