melvq; % mbest VQ functions
% --------------------------------------------------------------------------------
-% Function used by rate K mel work
+% Functions used by rate K mel work
% --------------------------------------------------------------------------------
+% General 2nd order parabolic interpolator. Used splines orginally,
+% but this is much simpler and we don't need much accuracy. Given two
+% vectors of points xp and yp, find interpolated values y at points x
+
+function y = interp_para(xp, yp, x)
+ assert( (length(xp) >=3) && (length(yp) >= 3) );
+
+ y = zeros(1,length(x));
+ for i=1:length(x)
+ xi = x(i);
+
+ % k is index into xp of where we start 3 points used to form parabola
+
+ k = 1;
+ while ((xp(k+1) < xi) && (k < (length(xp)-2)))
+ k++;
+ end
+
+ x1 = xp(k); y1 = yp(k); x2 = xp(k+1); y2 = yp(k+1); x3 = xp(k+2); y3 = yp(k+2);
+
+ a = ((y3-y2)/(x3-x2)-(y2-y1)/(x2-x1))/(x3-x1);
+ b = ((y3-y2)/(x3-x2)*(x2-x1)+(y2-y1)/(x2-x1)*(x3-x2))/(x3-x1);
+
+ y(i) = a*(xi-x2)^2 + b*(xi-x2) + y2;
+ end
+endfunction
+
% quantise input sample to nearest value in table, optionally return binary code
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]);
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", "extrap");
-
+ %rate_K_surface(f,:) = interp1(rate_L_sample_freqs_kHz, AmdB, rate_K_sample_freqs_kHz, "spline", "extrap");
+ rate_K_surface(f,:) = interp_para(rate_L_sample_freqs_kHz, AmdB, rate_K_sample_freqs_kHz);
+
%printf("\r%d/%d", f, frames);
end
%printf("\n");
% back down to rate L
- AmdB_ = interp1(rate_K_sample_freqs_kHz, rate_K_surface(f,:), rate_L_sample_freqs_kHz, "spline", 0);
+ % AmdB_ = interp1(rate_K_sample_freqs_kHz, rate_K_surface(f,:), rate_L_sample_freqs_kHz, "spline", 0);
+ AmdB_ = interp_para([ 0 rate_K_sample_freqs_kHz 4], [0 rate_K_surface(f,:) 0], rate_L_sample_freqs_kHz);
model_(f,1) = Wo; model_(f,2) = L; model_(f,3:(L+2)) = 10 .^ (AmdB_(1:L)/20);
end
Usage:
+ build codec2 with -DDUMP - see codec2-dev/README, then:
+
~/codec2-dev/build_linux/src$ ./c2sim ../../raw/hts1a.raw --dump hts1a
$ cd ~/codec2-dev/octave
octave:14> newamp1_batch("../build_linux/src/hts1a")
% -----------------------------------------------------------------------------------------
% Linear decimator/interpolator that operates at rate K, includes VQ, post filter, and Wo/E
% quantisation. Evolved from abys decimator below. Simulates the entire encoder/decoder.
-
+
+#{
+ todo:
+ [ ] M=8 nomenclature, make it closer to existing 25ms C modes
+ [ ] frame by frame-ish operation, close to C implementations
+#}
+
function [model_ voicing_ indexes] = experiment_rate_K_dec(model, voicing)
max_amp = 80;
[frames nc] = size(model);
[surface sample_freqs_kHz] = resample_const_rate_f_mel(model, K);
target_surface = surface;
+ figure(1);
+ mesh(surface);
+
% VQ rate K surface. TODO: If we are decimating by M/2=4 we really
% only need to do this every 4th frame.
mean_f(f) = mean(surface(f,:));
surface_no_mean(f,:) = surface(f,:) - mean_f(f);
end
+ figure(2);
+ mesh(surface_no_mean);
[res surface_no_mean_ ind] = mbest(train_120_vq, surface_no_mean, m);
indexes(:,1:2) = ind;
for f=1:frames
surface_no_mean_(f,:) = post_filter(surface_no_mean_(f,:), sample_freqs_kHz, 1.5);
end
+ figure(3);
+ mesh(surface_no_mean_);
surface_ = zeros(frames, K);
energy_q = 10 + 40/16*(0:15);
surface_(f,:) = surface_no_mean_(f,:) + mean_f_;
end
+ figure();
+ mesh(surface_);
+
% break into segments of M frames. We have 3 samples in M frame
% segment spaced M/2 apart and interpolate the rest. This evolved
% from AbyS scheme below but could be simplified to simple linear