From: drowe67 Date: Mon, 12 Dec 2016 20:34:31 +0000 (+0000) Subject: 15 element mel sampled vector 300-3000Hz, mean removed 256x2 VQ, works reasonably... X-Git-Url: http://git.whiteaudio.com/gitweb/?a=commitdiff_plain;h=0b533d8ef40a7c512a6b44e780c3b0f63b25709c;p=freetel-svn-tracking.git 15 element mel sampled vector 300-3000Hz, mean removed 256x2 VQ, works reasonably well on 10ms frames git-svn-id: https://svn.code.sf.net/p/freetel/code@2931 01035d8c-6547-0410-b346-abe4f91aad63 --- diff --git a/codec2-dev/octave/newamp1_batch.m b/codec2-dev/octave/newamp1_batch.m index 8a1d2432..f5c22389 100644 --- a/codec2-dev/octave/newamp1_batch.m +++ b/codec2-dev/octave/newamp1_batch.m @@ -28,17 +28,25 @@ % In general, this function processes a bunch of amplitudes, we then % use c2sim to hear the results -function [fvec_log amps_log] = newamp1_batch(samname, optional_Am_out_name, optional_Aw_out_name) +function surface = newamp1_batch(samname, optional_Am_out_name, optional_Aw_out_name) newamp; more off; max_amp = 80; + postfilter = 0; model_name = strcat(samname,"_model.txt"); model = load(model_name); [frames nc] = size(model); - model_ = experiment_filter(model); + % Choose experiment to run test here ----------------------- + + %model_ = experiment_dec_linear(model); + %model_ = experiment_filter(model); + %model_ = experiment_filter_dec_filter(model); + [model_ surface] = experiment_mel_freq(model, 1); + + % ---------------------------------------------------- if nargin == 2 Am_out_name = optional_Am_out_name; @@ -59,6 +67,17 @@ function [fvec_log amps_log] = newamp1_batch(samname, optional_Am_out_name, opti Am_ = zeros(1,max_amp); Am_(2:L) = Am(1:L-1); + + % post filter, boosts higher amplitudes more than lower, improving + % shape of formants and reducing muffling. Note energy normalisation + + if postfilter + e1 = sum(Am_(2:L).^2); + Am_(2:L) = Am_(2:L) .^ 1.5; + e2 = sum(Am_(2:L).^2); + Am_(2:L) *= sqrt(e1/e2); + end + fwrite(fam, Am_, "float32"); fwrite(fWo, Wo, "float32"); end @@ -69,27 +88,121 @@ function [fvec_log amps_log] = newamp1_batch(samname, optional_Am_out_name, opti endfunction +% Non linear sampling of frequency axis, reducing the "rate" is a +% first step before VQ + +function mel = ftomel(fHz) + mel = floor(2595*log10(1+fHz/700)+0.5); +endfunction + +function [model_ rate_K_surface] = experiment_mel_freq(model, vq_en=0) + [frames nc] = size(model); + K = 15; + mel_start = ftomel(300); mel_end = ftomel(3000); + step = (mel_end-mel_start)/(K-1); + mel = mel_start:step:mel_end; + rate_K_sample_freqs_Hz = 700*((10 .^ (mel/2595)) - 1); + rate_K_sample_freqs_kHz = rate_K_sample_freqs_Hz/1000; + + rate_K_surface = resample_const_rate_f(model, rate_K_sample_freqs_kHz); + + figure(1); clf; mesh(rate_K_surface); + + if vq_en + melvq; + load surface_vq; m=5; + + for f=1:frames + mean_f(f) = mean(rate_K_surface(f,:)); + rate_K_surface(f,:) -= mean_f(f); + end + + [res rate_K_surface_ ind] = mbest(surface_vq, rate_K_surface, m); + + for f=1:frames + rate_K_surface_(f,:) += mean_f(f); + end + + rate_K_surface = rate_K_surface_; + + #{ + Nf = 4; Nf2 = 6; + [b a]= cheby1(4, 1, 0.20); + for k=1:K + rate_K_surface_(:,k) = filter(b, a, rate_K_surface_(:,k)); + end + rate_K_surface_ = [rate_K_surface_(Nf2:frames,:); zeros(Nf2, K)]; + #} + end + + model_ = resample_rate_L(model, rate_K_surface, rate_K_sample_freqs_kHz); + + %figure(2); clf; mesh(model_); + + + for f=1:frames + rate_K_surface(f,:) -= mean(rate_K_surface(f,:)); + end + + +endfunction + +% conventional decimation in time without any filtering, then linear +% interpolation. Linear interpolation is a two-tap (weak) form of fir +% filtering that may have problems with signals with high freq +% components, for example after quantisation noise is added. Need to +% look into this some more. +function model_ = experiment_dec_linear(model) + newamp; + max_amp = 80; + + [frames nc] = size(model); + model_ = zeros(frames, max_amp+3); + decimate = 4; + for f=1:frames + AmdB_ = decimate_frame_rate(model, decimate, f, frames); + L = length(AmdB_); + model_(f,1) = model(f,1); model_(f,2) = L; model_(f,3:(L+2)) = 10 .^ (AmdB_(1:L)/20); + end +endfunction + #{ Filtering time axis or surface, as a first step before decimation. So given surface, lets look at spectral content and see if we can reduce it while maintaining speech quality. First step is to dft across time and plot. + + This just has one filtering step, which may help quantisation. In practice + we may need filtering before decimation and at the inerpolation stage #} function model_ = experiment_filter(model) [frames nc] = size(model); - K = 40; - [rate_K_surface rate_K_sample_freqs_kHz] = resample_const_rate_f(model, K); + K = 40; rate_K_sample_freqs_kHz = (1:K)*4/K; + [rate_K_surface rate_K_sample_freqs_kHz] = resample_const_rate_f(model, rate_K_sample_freqs_kHz); - Nf = 4; Nf2 = 5; + Nf = 4; Nf2 = 6; [b a]= cheby1(4, 1, 0.20); + %Nf = 20; Nf2 = 10; + %b = fir1(Nf, 0.25); a = [1 zeros(1, Nf)]; + %Nf = 1; Nf2 = 1; + %b = 1; a = [1 zeros(1, Nf)]; + + %Nf = 2; Nf2 = 1; + %beta = 0.99; w = pi/4; + %b = [1 -2*beta*cos(w) beta*beta]; a = [1 zeros(1, Nf)]; + %Nf = 10; Nf2 = 10; + %b = fir2(10, [0 0.2 0.3 1], [1 1 0.1 0.1]); a = [1 zeros(1, Nf)]; + + %Nf = 1; Nf2 = 1; dft_surface = zeros(frames,K); rate_K_surface_filt = zeros(frames,K); dft_surface_filt = zeros(frames,K); for k=1:K dft_surface(:,k) = fft(rate_K_surface(:,k).*hanning(frames)); - rate_K_surface_filt(:,k) = filter(b, a, rate_K_surface(:,k)); + %rate_K_surface_filt(:,k) = filter(b, a, rate_K_surface(:,k)); + rate_K_surface_filt(:,k) = filter(b, a, rate_K_surface(:,k)); dft_surface_filt(:,k) = fft(rate_K_surface_filt(:,k).*hanning(frames)); end figure(1); clf; @@ -102,7 +215,7 @@ function model_ = experiment_filter(model) subplot(211); h = freqz(b,a,Fs/2); plot(1:Fs/2, 20*log10(abs(h))) - axis([1 Fs/2 -80 0]) + axis([1 Fs/2 -40 0]) ylabel('Gain (dB)') grid; subplot(212) @@ -125,6 +238,64 @@ function model_ = experiment_filter(model) endfunction +% filter, decimate, zero insert, filter, simulates decimation and re-interpolation, as +% an alternative to simple linear interpolation. + +function model_ = experiment_filter_dec_filter(model) + [frames nc] = size(model); + + % rate K surface + + K = 40; rate_K_sample_freqs_kHz = (1:K)*4/K; + [rate_K_surface rate_K_sample_freqs_kHz] = resample_const_rate_f(model, rate_K_sample_freqs_kHz); + + % filter, not we run across each of the K bins, treating them as a 1-D sequence + + Nf = 4; filter_delay = 12; + [b a]= cheby1(4, 1, 0.20); + %Nf = 10; Nf2 = Nf/2; filter_delay = Nf2*2; + %b = fir1(Nf, 0.25); a = [1 zeros(1, Nf)]; + %Nf = 10; Nf2 = 2; filter_delay = 2*Nf2; + %b = fir2(10, [0 0.2 0.3 1], [1 1 0.1 0.1]); a = [1 zeros(1, Nf)]; + + rate_K_surface_filt = zeros(frames,K); + for k=1:K + rate_K_surface_filt(:,k) = filter(b, a, rate_K_surface(:,k)); + end + + % decimate from 100 to 25Hz, and zero pad, which we simulate by + % setting all K samples in 3 out of 4 time-samples to zero + + M = 4; + + for f=1:frames + if mod(f,M) + rate_K_surface_filt(f,:) = zeros(1,K); + end + end + + % filter to reconstruct 100 Hz frame rate + + rate_K_surface_filt_recon = zeros(frames,K); + for k=1:K + rate_K_surface_filt_recon(:,k) = filter(b, a, M*rate_K_surface_filt(:,k)); + end + + figure(1); clf; + mesh(rate_K_surface_filt) + figure(2); clf; + mesh(rate_K_surface_filt_recon) + + % adjust for time offset due to 2 lots of filtering + + rate_K_surface_filt_recon = [rate_K_surface_filt_recon(filter_delay:frames,:); zeros(filter_delay, K)]; + + % back down to rate L + + model_ = resample_rate_L(model, rate_K_surface_filt_recon, rate_K_sample_freqs_kHz); +endfunction + + #{ todo: get this working again @@ -175,8 +346,7 @@ endfunction % Resample Am from time-varying rate L=floor(pi/Wo) to fixed rate K. This can be viewed -% as a 3D surface with tim, freq, nd ampitude axis. - +% as a 3D surface with time, freq, and ampitude axis. function [rate_K_surface rate_K_sample_freqs_kHz] = resample_const_rate_f(model, K=50) @@ -199,31 +369,51 @@ function [rate_K_surface rate_K_sample_freqs_kHz] = resample_const_rate_f(model, endfunction +function [rate_K_surface rate_K_sample_freqs_kHz] = resample_const_rate_f(model, rate_K_sample_freqs_kHz) + + % convert rate L=pi/Wo amplitude samples to fixed rate K + + max_amp = 80; + [frames col] = size(model); + K = length(rate_K_sample_freqs_kHz); + rate_K_surface = zeros(frames, K); + + for f=1:frames + Wo = model(f,1); + L = min([model(f,2) max_amp-1]); + Am = model(f,3:(L+2)); + AmdB = 20*log10(Am); + rate_L_sample_freqs_kHz = (1:L)*Wo*4/pi; + + rate_K_surface(f,:) = interp1(rate_L_sample_freqs_kHz, AmdB, rate_K_sample_freqs_kHz, "spline", 0); + end +endfunction + + % Take a rate K surface and convert back to time varying rate L -function model_ = resample_rate_L(model, rate_K_surface, rate_K_sample_freqs_kHz, K=50) +function model_ = resample_rate_L(model, rate_K_surface, rate_K_sample_freqs_kHz) max_amp = 80; [frames col] = size(model); model_ = zeros(frames, max_amp+3); for f=1:frames-1 - Wo = (model(f,1) + model(f+1,1))/2; + Wo = model(f,1); L = min(pi/Wo, max_amp-1); rate_L_sample_freqs_kHz = (1:L)*Wo*4/pi; % back down to rate L - AmdB_ = interp1(rate_K_sample_freqs_kHz, rate_K_surface(f,:), rate_L_sample_freqs_kHz, "spline", "extrap"); - - % todo a way to save all model params ... Am, Wo, L, (v?) Start with current facility then - % make it better + AmdB_ = interp1(rate_K_sample_freqs_kHz, rate_K_surface(f,:), rate_L_sample_freqs_kHz, "spline", 0); model_(f,1) = Wo; model_(f,2) = L; model_(f,3:(L+2)) = 10 .^ (AmdB_(1:L)/20); end endfunction -function model_ = resample_half_frame_offset(model, rate_K_surface, rate_K_sample_freqs_kHz, K=50) +% early test, devised to test rate K<->L changes along frequency axis + +function model_ = resample_half_frame_offset(model, rate_K_surface, rate_K_sample_freqs_kHz) max_amp = 80; [frames col] = size(model);