711 lines
22 KiB
C
711 lines
22 KiB
C
/*---------------------------------------------------------------------------*\
|
|
|
|
FILE........: c2wideband.c
|
|
AUTHOR......: David Rowe & Phil Ayres
|
|
DATE CREATED: July 2017
|
|
|
|
* TODO - what is this file doing?
|
|
*
|
|
\*---------------------------------------------------------------------------*/
|
|
|
|
/*
|
|
Copyright David Rowe 2017
|
|
|
|
All rights reserved.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU Lesser General Public License version 2.1, as
|
|
published by the Free Software Foundation. This program is
|
|
distributed in the hope that it will be useful, but WITHOUT ANY
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
|
License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public License
|
|
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
#include <assert.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
#include <unistd.h>
|
|
|
|
#include "defines.h"
|
|
#include "codec2_fft.h"
|
|
#include "sine.h"
|
|
#include "nlp.h"
|
|
#include "dump.h"
|
|
#include "lpc.h"
|
|
#include "quantise.h"
|
|
#include "phase.h"
|
|
#include "interp.h"
|
|
#include "postfilter.h"
|
|
#include "codec2.h"
|
|
#include "lsp.h"
|
|
#include "codec2_internal.h"
|
|
#include "machdep.h"
|
|
#include "codec2.h"
|
|
#include "newamp1.h"
|
|
#include "dct2.h"
|
|
|
|
#include "c2wideband.h"
|
|
#include "c2wideband_map.h"
|
|
|
|
float mean(float data[], int n);
|
|
int unit_test();
|
|
float std(float data[], int rows);
|
|
void diff_de(int rows, int cols, float D[rows][cols], float E[rows][cols], float diff_de[rows][cols]);
|
|
void array_col_to_row(int rows, int cols, float data[rows][cols], int col, float res[]);
|
|
void std_on_cols(int rows, int cols, float data[rows][cols], float res[]);
|
|
void setup_map(WIDEBAND_MAP * wb_map, int Nt, int K);
|
|
|
|
#define C2WB_PLOT
|
|
|
|
|
|
//TODO: move all this to the standard codec2.c functions
|
|
#ifdef IGNORE
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
struct CODEC2 *codec2;
|
|
FILE *fin;
|
|
FILE *fout;
|
|
short *buf;
|
|
unsigned char *bits;
|
|
int nsam, nbit, i, r;
|
|
int errno = -1;
|
|
for (i = 0; i < 10; i++) {
|
|
r = codec2_rand();
|
|
printf("[%d] r = %d\n", i, r);
|
|
}
|
|
|
|
if (argc != 3) {
|
|
printf("usage: %s InputRawSpeechFile OutputRawSpeechFile\n", argv[0]);
|
|
exit(1);
|
|
}
|
|
|
|
if ((fin = fopen(argv[1], "rb")) == NULL) {
|
|
fprintf(stderr, "Error opening input speech file: %s: %s.\n",
|
|
argv[1], strerror(errno));
|
|
exit(1);
|
|
}
|
|
|
|
if ((fout = fopen(argv[2], "wb")) == NULL) {
|
|
fprintf(stderr, "Error opening output speech file: %s: %s.\n",
|
|
argv[2], strerror(errno));
|
|
exit(1);
|
|
}
|
|
|
|
#ifdef DUMP
|
|
dump_on("c2demo");
|
|
#endif
|
|
|
|
/* Note only one set of Codec 2 states is required for an encoder
|
|
and decoder pair. */
|
|
|
|
codec2 = codec2_create(CODEC2_MODE_WB);
|
|
nsam = C2WB_SPERF; //codec2_samples_per_frame(codec2);
|
|
buf = (short*) malloc(nsam * sizeof (short));
|
|
nbit = C2WB_BPERF; //codec2_bits_per_frame(codec2);
|
|
bits = (unsigned char*) malloc(nbit * sizeof (char));
|
|
|
|
while (fread(buf, sizeof (short), nsam, fin) == (size_t) nsam) {
|
|
codec2_encode_wb(codec2, bits, buf);
|
|
codec2_decode_wb(codec2, buf, bits);
|
|
fwrite(buf, sizeof (short), nsam, fout);
|
|
}
|
|
|
|
free(buf);
|
|
free(bits);
|
|
codec2_destroy(codec2);
|
|
|
|
fclose(fin);
|
|
fclose(fout);
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
void codec2_encode_wb(struct CODEC2 *c2, unsigned char * bits, short speech[])
|
|
{
|
|
return;
|
|
}
|
|
|
|
void codec2_decode_wb(struct CODEC2 *c2, short speech[], const unsigned char * bits)
|
|
{
|
|
return;
|
|
}
|
|
|
|
void calculate_Am_freqs_kHz(float Wo, int L, float Am_freqs_kHz[L])
|
|
{
|
|
//(1:L)*Wo*4/pi;
|
|
int i;
|
|
for (i = 0; i < L; i++) {
|
|
Am_freqs_kHz[i] = i * Wo * 4 / PI;
|
|
}
|
|
}
|
|
|
|
|
|
// Adapted from newamp.m
|
|
|
|
void resample_const_rate_f_mel(C2CONST *c2const, MODEL * model, float K, float* rate_K_surface, float* rate_K_sample_freqs_kHz)
|
|
{
|
|
mel_sample_freqs_kHz(rate_K_sample_freqs_kHz, K, 100, 0.95 * c2const->Fs / 2);
|
|
resample_const_rate_f(c2const, model, rate_K_surface, rate_K_sample_freqs_kHz, K);
|
|
}
|
|
|
|
|
|
// Updates rate_K_vec with the corrected values
|
|
// function [rate_K_vec_corrected orig_error error nasty_error_log nasty_error_m_log] = correct_rate_K_vec(rate_K_vec, rate_K_sample_freqs_kHz, AmdB, AmdB_, K, Wo, L, Fs)
|
|
|
|
void correct_rate_K_vec(MODEL *model, float rate_K_vec[], float rate_K_sample_freqs_kHz[], float Am_freqs_kHz[], float orig_AmdB[], int K, float Wo, int L, int Fs, float rate_K_vec_corrected[])
|
|
{
|
|
|
|
/*
|
|
% aliasing correction --------------------------------------
|
|
|
|
% The mel sample rate decreases as frequency increases. Look for
|
|
% any regions above 1000Hz where we have missed definition of a
|
|
% spectral peak (formant) due to aliasing. Adjust the rate K
|
|
% sample levels to restore peaks. Theory is that correct
|
|
% definition of a formant is less important than the frequency of
|
|
% the formant. As long as we define a formant in that general
|
|
% frequency area it will sound OK.
|
|
*/
|
|
|
|
|
|
// this is passed in
|
|
//Am_freqs_kHz = (1:L)*Wo*4/pi;
|
|
|
|
//% Lets see where we have made an error
|
|
float error[MAX_AMP + 1];
|
|
//float orig_error[MAX_AMP+1];
|
|
float AmdB_[MAX_AMP + 1];
|
|
|
|
float nasty_error_freq;
|
|
float rate_K_prev_sample_kHz;
|
|
float rate_K_next_sample_kHz;
|
|
|
|
int Ncorrections = 3; //% maximum number of rate K samples to correct
|
|
int error_thresh = 3; //% only worry about errors larger than thresh
|
|
|
|
int closest_k = 0;
|
|
int i;
|
|
|
|
// regenerate the AmdB values from the updated model
|
|
for (i = 0; i < MAX_AMP + 1; i++) {
|
|
AmdB_[i] = 20 * log10(model->A[i]);
|
|
}
|
|
|
|
// calculate error between original AmdB and the new values
|
|
for (i = 0; i < MAX_AMP + 1; i++) {
|
|
int a = orig_AmdB[i] - AmdB_[i];
|
|
error[i] = a;
|
|
// orig_error[i] = a;
|
|
}
|
|
|
|
|
|
|
|
//% first 1000Hz is densely sampled so ignore
|
|
int start_m = floor(L * 1000 / (Fs / 2));
|
|
for (i = 0; i < start_m; i++) {
|
|
error[i] = 0;
|
|
}
|
|
//start_m = floor(L*1000/(Fs/2));
|
|
//error(1:start_m) = 0; % first 1000Hz is densly sampled so ignore
|
|
|
|
// ignore these
|
|
//float nasty_error_m_log = [];
|
|
//float nasty_error_log = [];
|
|
|
|
|
|
// could probably memcpy this, but I need to think about it...
|
|
// TODO copy??
|
|
for (i = 0; i < K; i++) {
|
|
//rate_K_vec_corrected = rate_K_vec
|
|
rate_K_vec_corrected[i] = rate_K_vec[i];
|
|
}
|
|
|
|
for (i = 0; i < Ncorrections; i++) {
|
|
|
|
// [mx mx_m] = max(error);
|
|
int mx_m = 0;
|
|
int mx = 0;
|
|
int m;
|
|
for (m = 0; m < start_m; m++) {
|
|
if (error[m] > mx) {
|
|
mx_m = m;
|
|
mx = error[m];
|
|
}
|
|
}
|
|
|
|
if (mx > error_thresh) {
|
|
|
|
// ignore these
|
|
//nasty_error_log = [nasty_error_log mx];
|
|
//nasty_error_m_log = [nasty_error_m_log mx_m];
|
|
|
|
//% find closest rate K sample to nasty error
|
|
|
|
nasty_error_freq = (float) mx_m * Wo * Fs / (2 * PI * 1000);
|
|
|
|
//[tmp closest_k] = min(abs(rate_K_sample_freqs_kHz - nasty_error_freq));
|
|
closest_k = -1;
|
|
float cka = K;
|
|
int k;
|
|
for (k = 0; k < K; k++) {
|
|
float a = fabs(rate_K_sample_freqs_kHz[k] - nasty_error_freq);
|
|
|
|
if (closest_k == -1 || a < cka) {
|
|
closest_k = k;
|
|
cka = a;
|
|
}
|
|
}
|
|
|
|
// this sets the value from the original AmdB value set for the model prior to recalculation
|
|
// TODO - check this is correct
|
|
rate_K_vec_corrected[closest_k] = orig_AmdB[mx_m];
|
|
|
|
//% zero out error in this region and look for another large error region
|
|
|
|
// here I'm assuming that the required result is a zero based index
|
|
// rather than an Octave 1 based index
|
|
// closest_k is already 0 based in this code
|
|
// TODO - check this
|
|
k = (0 > closest_k - 1 ? 0 : closest_k - 1);
|
|
//k = max(1, closest_k-1);
|
|
|
|
rate_K_prev_sample_kHz = rate_K_sample_freqs_kHz[k];
|
|
|
|
|
|
// again, assuming the required result is 0 rather than 1 based
|
|
// TODO - check
|
|
k = (K - 1 < closest_k + 1 ? K : closest_k + 1);
|
|
//k = min(K, closest_k+1);
|
|
|
|
rate_K_next_sample_kHz = rate_K_sample_freqs_kHz[k];
|
|
|
|
int st = -1;
|
|
int st_m = 0;
|
|
int en = -1;
|
|
int en_m = 0;
|
|
for (m = 0; m < C2WB_K - 1; m++) {
|
|
//[tmp st_m] = min(abs(Am_freqs_kHz - rate_K_prev_sample_kHz));
|
|
//[tmp en_m] = min(abs(Am_freqs_kHz - rate_K_next_sample_kHz));
|
|
int pa = fabs(Am_freqs_kHz[m] - rate_K_prev_sample_kHz);
|
|
int na = fabs(fabs(Am_freqs_kHz[m] - rate_K_next_sample_kHz));
|
|
if (st == -1 || pa < st) {
|
|
st = pa;
|
|
st_m = m;
|
|
}
|
|
if (en == -1 || na < en) {
|
|
en = na;
|
|
en_m = m;
|
|
}
|
|
}
|
|
if (closest_k == K)
|
|
en_m = L;
|
|
|
|
for (m = st_m; m < en_m; m++) {
|
|
error[m] = 0;
|
|
}
|
|
//error(st_m:en_m) = 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
void diff_de(int rows, int cols, float D[rows][cols], float E[rows][cols], float diff_de[rows][cols])
|
|
{
|
|
|
|
int col, row;
|
|
for (col = 0; col < cols; col++) {
|
|
for (row = 0; row < rows; row++) {
|
|
diff_de[row][col] = D[row][col] - E[row][col];
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
float mean(float data[], int n)
|
|
{
|
|
float sum = 0.0;
|
|
int i;
|
|
for (i = 0; i < n; ++i) {
|
|
sum += data[i];
|
|
}
|
|
|
|
return sum / n;
|
|
}
|
|
|
|
void array_col_to_row(int rows, int cols, float data[rows][cols], int col, float res[])
|
|
{
|
|
int row;
|
|
for (row = 0; row < rows; row++) {
|
|
res[row] = data[row][col];
|
|
}
|
|
}
|
|
|
|
float std(float data[], int rows)
|
|
{
|
|
float standardDeviation = 0.0;
|
|
int i;
|
|
for (i = 0; i < rows; ++i) {
|
|
standardDeviation += pow(data[i] - mean(data, rows), 2);
|
|
}
|
|
return sqrt(standardDeviation / rows);
|
|
}
|
|
|
|
void std_on_cols(int rows, int cols, float data[rows][cols], float res[])
|
|
{
|
|
float row_from_col[cols];
|
|
int col;
|
|
for (col = 0; col < cols; col++) {
|
|
array_col_to_row(rows, cols, data, col, row_from_col);
|
|
res[col] = std(row_from_col, rows);
|
|
}
|
|
}
|
|
|
|
float mean_std_diff_de(int rows, int cols, float D[rows][cols], float E[rows][cols])
|
|
{
|
|
float matrix_diff_de[rows][cols];
|
|
float std_array[cols];
|
|
diff_de(rows, cols, D, E, matrix_diff_de);
|
|
std_on_cols(rows, cols, matrix_diff_de, std_array);
|
|
return mean(std_array, cols);
|
|
}
|
|
|
|
|
|
//% Encode/decoder a 160ms block of model parameters
|
|
//% TODO: (i) quantisation of DCT coeffs (ii) break into separate encoder and decoder functions
|
|
//
|
|
//function [model_block_ dct2_sd qn rate_K_surface_block rate_K_surface_block_] = wideband_enc_dec(model_block, rmap, cmap)
|
|
|
|
void wideband_enc_dec(C2CONST *c2const, int n_block_frames, MODEL model_block[n_block_frames], WIDEBAND_MAP * wb_map,
|
|
MODEL model_block_[n_block_frames], float dct2_sd[n_block_frames], int * p_qn, float rate_K_surface_block[n_block_frames][C2WB_K], float rate_K_surface_block_[n_block_frames][C2WB_K])
|
|
{
|
|
|
|
|
|
//printf("starting wideband_enc_dec with model_block[0]->L = %d\n", model_block[0].L);
|
|
// c2wideband_const;
|
|
//
|
|
// sim_quant = 1; % used to simulate quantisation, set to 1,2,4, etc
|
|
// dist_dB = 2; % use enough coefficients to get this distortion ond DCT coeffs
|
|
int sim_quant = 1;
|
|
float dist_dB = 2;
|
|
|
|
// int Fs = c2const->Fs;
|
|
// int L;
|
|
// float Wo;
|
|
|
|
int K = C2WB_K;
|
|
int Nt = C2WB_NT;
|
|
|
|
int rows = Nt;
|
|
int cols = K;
|
|
int dec = C2WB_DEC;
|
|
|
|
// one time configuration of DCT & IDCT
|
|
|
|
codec2_dct_cfg dct_cfg_n = dct_config(cols);
|
|
codec2_dct_cfg dct_cfg_m = dct_config(rows);
|
|
codec2_dct_cfg idct_cfg_n = idct_config(cols);
|
|
codec2_dct_cfg idct_cfg_m = idct_config(rows);
|
|
|
|
//printf("starting iteration\n");
|
|
// iterate through the frames in the block
|
|
int f;
|
|
for (f = 0; f < n_block_frames; f++) {
|
|
//printf("processing frame %d of %d\n", f, n_block_frames);
|
|
|
|
float rate_K_sample_freqs_kHz[C2WB_K];
|
|
//MODEL * model = &model_block[f];
|
|
|
|
|
|
// % Resample variable rate L vectors to fixed length rate K. We have
|
|
// % left high end correction out for now, this is less of an issue
|
|
// % with a higher K
|
|
|
|
|
|
// [rate_K_surface_block rate_K_sample_freqs_kHz] = resample_const_rate_f_mel(model_block, K, Fs);
|
|
//printf("resample_const_rate_f_mel\n");
|
|
resample_const_rate_f_mel(c2const, &model_block[f], K, rate_K_surface_block[f], rate_K_sample_freqs_kHz);
|
|
|
|
// % decimate down to 20ms time resolution, and DCT
|
|
|
|
// D = dct2(rate_K_surface_block(1:dec:Nt*dec,:));
|
|
|
|
float D[rows][cols];
|
|
float E[rows][cols];
|
|
//printf("dct2\n");
|
|
dct2(dct_cfg_m, dct_cfg_n, rows, cols, &rate_K_surface_block[f], D);
|
|
|
|
// % So D is the 2D block of DCT coeffs at the encoder. We want to
|
|
// % create a quantised version at the "decoder" E. This loop copies
|
|
// % DCTs coeffs from D to E, until we get beneath a distortion
|
|
// % threshold.
|
|
//
|
|
// % This is essentially variable rate quantisation, but gives us
|
|
// % some idea of the final bit rate. In practice we will also need
|
|
// % to constrain the total number of bits (ie bit rate), and
|
|
// % quantise each coefficient.
|
|
//
|
|
// % Turns out than mean SD (across many blocks/frames) is about the
|
|
// % same in the DCT domain as the rate K domain. So we can just
|
|
// % measure MSE between D and E to estimate mean SD of the rate K
|
|
// % vectors after quantisation.
|
|
|
|
// E = mapped = zeros(Nt,K);
|
|
int r, c;
|
|
for (r = 0; r < rows; r++) {
|
|
memset(E[r], '\0', cols * sizeof (float));
|
|
}
|
|
|
|
// qn = 0;
|
|
*p_qn = 0;
|
|
|
|
// adct2_sd = mean(std(D-E));
|
|
|
|
float adct2_sd;
|
|
|
|
|
|
adct2_sd = mean_std_diff_de(rows, cols, D, E);
|
|
|
|
//printf("while adct2_sd > dist_dB (dist_dB=%f)\n", dist_dB);
|
|
// while adct2_sd > dist_dB
|
|
//TODO : validate the addition of *p_qn limit check is correct
|
|
while (adct2_sd > dist_dB && *p_qn < C2WB_NT) {
|
|
|
|
// qn++;
|
|
// --- this has moved to the end to cope with 0 base
|
|
assert(*p_qn < C2WB_NT);
|
|
int rmapqn = wb_map->rmap[*p_qn];
|
|
int cmapqn = wb_map->cmap[*p_qn];
|
|
assert(rmapqn < rows);
|
|
assert(cmapqn < cols);
|
|
// E(rmap(qn), cmap(qn)) = sim_quant*round(D(rmap(qn), cmap(qn))/sim_quant);
|
|
E[rmapqn][cmapqn] = sim_quant * round(D[rmapqn][cmapqn] / sim_quant);
|
|
// adct2_sd = mean(std(D-E));
|
|
adct2_sd = mean_std_diff_de(rows, cols, D, E);
|
|
|
|
//printf("qn %d %f\n", *p_qn, adct2_sd);
|
|
|
|
(*p_qn)++;
|
|
// %printf("qn %d %f\n", qn, adct2_sd);
|
|
// end
|
|
}
|
|
|
|
// % note neat trick to interpolate to 10ms frames despite dec to 20ms, this means
|
|
// % we don't need a separate decode side interpolator.
|
|
|
|
// dct2_sd = mean(std(D-E));
|
|
|
|
|
|
dct2_sd[f] = mean_std_diff_de(rows, cols, D, E);
|
|
|
|
|
|
// rate_K_surface_block_ = idct2([sqrt(dec)*E; zeros(Nt*(dec-1), K)]);
|
|
float inrks[rows * dec][K];
|
|
|
|
//printf("setting inrks\n");
|
|
for (r = 0; r < rows; r++) {
|
|
for (c = 0; c < cols; c++) {
|
|
inrks[r][c] = sqrt(dec) * E[r][c];
|
|
}
|
|
}
|
|
for (r = 0; r < Nt * (dec - 1); r++) {
|
|
for (c = 0; c < K; c++) {
|
|
inrks[r + rows][c] = 0;
|
|
}
|
|
}
|
|
|
|
|
|
//TODO ???
|
|
//= [sqrt(dec)*E; zeros(Nt*(dec-1), K)];
|
|
//printf("idct2\n");
|
|
idct2(idct_cfg_m, idct_cfg_n, rows, cols, inrks, &rate_K_surface_block_[f]);
|
|
|
|
// model_block_ = resample_rate_L(model_block, rate_K_surface_block_, rate_K_sample_freqs_kHz, Fs);
|
|
//printf("resample_rate_L\n");
|
|
resample_rate_L(c2const, &model_block[f], rate_K_surface_block_[f], rate_K_sample_freqs_kHz, K);
|
|
//endfunction
|
|
}
|
|
}
|
|
|
|
void setup_map(WIDEBAND_MAP * wb_map, int Nt, int K)
|
|
{
|
|
|
|
/*
|
|
% map that defines order we read out and quantise DCT coeffs
|
|
% TODO: for C port we need an Octave function to write Map to a C
|
|
% include file
|
|
|
|
map = load("c2wideband_map");
|
|
|
|
% create arrays to reverse map quantiser_num to r,c Luts
|
|
|
|
rmap = cmap = zeros(1,Nt*K);
|
|
for r=1:Nt
|
|
for c=1:K
|
|
quantiser_num = map(r,c);
|
|
rmap(quantiser_num) = r;
|
|
cmap(quantiser_num) = c;
|
|
end
|
|
end
|
|
|
|
*/
|
|
|
|
//printf("setup_map(wb_map, Nt, K)");
|
|
int quantiser_num, r, c;
|
|
|
|
memset(wb_map->rmap, '\0', Nt * K * sizeof *wb_map->rmap);
|
|
memset(wb_map->cmap, '\0', Nt * K * sizeof *wb_map->cmap);
|
|
|
|
for (r = 0; r < Nt; r++) {
|
|
for (c = 0; c < K; c++) {
|
|
quantiser_num = c2wideband_map[r][c];
|
|
wb_map->rmap[quantiser_num] = r;
|
|
wb_map->cmap[quantiser_num] = c;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
% ---------------------------------------------------------------------------------------
|
|
% rate K mel-resampling, high end correction, and DCT experiment workhorse
|
|
|
|
function [model_ rate_K_surface] = experiment_rate_K_dct2(model, plots=1)
|
|
*/
|
|
|
|
//TODO - review and produce a unit test for this
|
|
// this is really just a draft at this point
|
|
|
|
void experiment_rate_K_dct2(C2CONST *c2const, MODEL model_frames[], const int total_frames)
|
|
{
|
|
|
|
printf("experiment_rate_K_dct2 with frames: %d\n", total_frames);
|
|
// newamp;
|
|
// c2wideband_const;
|
|
// [frames nc] = size(model);
|
|
|
|
const int n_block_frames = C2WB_NT * C2WB_DEC;
|
|
|
|
const int K = C2WB_K;
|
|
const int Nt = C2WB_NT;
|
|
const int dec = C2WB_DEC;
|
|
const int Tf = C2WB_TF;
|
|
WIDEBAND_MAP wb_map;
|
|
|
|
|
|
// % break into blocks of (Nt time samples) x (K freq samples)
|
|
|
|
// Nblocks = floor(frames/(Nt*dec));
|
|
|
|
const int Nblocks = floor(total_frames / n_block_frames);
|
|
|
|
// number of frames that can be processed (if the final block is not a full set of frames)
|
|
int frames;
|
|
|
|
frames = Nblocks * n_block_frames;
|
|
|
|
printf("total_frames: %d processable frames: %d Nblocks: %d\n", total_frames, frames, Nblocks);
|
|
|
|
|
|
setup_map(&wb_map, Nt, K);
|
|
|
|
|
|
|
|
//% per-block processing ----------------------------------------------------
|
|
|
|
// % init a bunch of output variables
|
|
|
|
// rate_K_surface_ = zeros(Nblocks*Nt*dec, K);
|
|
// sumnz = zeros(1,Nblocks);
|
|
// dct2_sd = zeros(1,Nblocks);
|
|
// model_ = [];
|
|
|
|
|
|
float rate_K_surface_block[total_frames][K]; // rate K vecs for each frame, form a surface that makes pretty graphs
|
|
float rate_K_surface_block_[total_frames][K];
|
|
|
|
#ifdef C2WB_PLOT
|
|
// float rate_K_surface[total_frames][K];
|
|
// float rate_K_surface_[total_frames][K];
|
|
// MODEL model_[total_frames];
|
|
#endif
|
|
|
|
float sumnz[Nblocks];
|
|
float dct2_sd[Nblocks];
|
|
int qn;
|
|
|
|
MODEL model_block_[n_block_frames];
|
|
|
|
//for n=1:Nblocks
|
|
// Step through the model in blocks of 16 frames
|
|
int n_block = 0;
|
|
int f;
|
|
for (f = 0; f < frames; f += n_block_frames) {
|
|
MODEL * model_block = &model_frames[f];
|
|
|
|
|
|
//st = (n-1)*dec*Nt+1; en = st + dec*Nt - 1;
|
|
//printf("st: %d en: %d\n", st, en);
|
|
// effectively handled by the iterations through the block in wideband_enc_dec
|
|
|
|
//[model_block_ adct2_sd qn rate_K_surface_block rate_K_surface_block_] = wideband_enc_dec(model(st:en,:), rmap, cmap);
|
|
// void wideband_enc_dec(C2CONST *c2const, int n_block_frames, MODEL model_block[n_block_frames], WIDEBAND_MAP * wb_map,
|
|
// MODEL model_block_[n_block_frames], float dct2_sd[n_block_frames], int * p_qn, float rate_K_surface_block[n_block_frames][C2WB_K], float rate_K_surface_block_[n_block_frames][C2WB_K]) {
|
|
|
|
wideband_enc_dec(c2const, n_block_frames, model_block, &wb_map,
|
|
model_block_, &dct2_sd[n_block], &qn, &rate_K_surface_block[f], &rate_K_surface_block_[f]);
|
|
|
|
#ifdef C2WB_PLOT
|
|
//model_ = [model_; model_block_];
|
|
//% log these for plotting/development
|
|
|
|
//rate_K_surface(st:en,:) = rate_K_surface_block;
|
|
//rate_K_surface_(st:en,:) = rate_K_surface_block_;
|
|
|
|
// for (int p = 0; p < n_block_frames; p++) {
|
|
|
|
// model_[f+p] = model_block_[p];
|
|
|
|
// for (int k = 0; k < K; k++) {
|
|
// rate_K_surface[f+p][k] = rate_K_surface_block[n_block + p][k];
|
|
// rate_K_surface_[f+p][k] = rate_K_surface_block_[n_block + p][k];
|
|
// }
|
|
// }
|
|
//dct2_sd(n) = adct2_sd;
|
|
sumnz[n_block] = (float) qn;
|
|
// already handled in call
|
|
#endif
|
|
n_block++;
|
|
//end
|
|
}
|
|
|
|
|
|
#ifdef C2WB_PLOT
|
|
printf("average dct spectral distortion: %3.2f dB\n", mean(dct2_sd, Nblocks));
|
|
printf("mean number of coeffs/DCT: %3.2f/%d\n", mean(sumnz, Nblocks), Nt * K);
|
|
printf("coeffs/second: %3.2f\n", mean(sumnz, Nblocks) / (Nt * Tf * dec));
|
|
printf("bits/s: %3.2f\n", 2.9 * mean(sumnz, Nblocks) / (Nt * Tf * dec));
|
|
|
|
//TODO
|
|
//dist = std((rate_K_surface_(1:dec:Nblocks*Nt*dec,:) - rate_K_surface(1:dec:Nblocks*Nt*dec,:))');
|
|
//float dist =
|
|
//if plots
|
|
//figure(1); clf; plot(dist); title('Rate K SD');
|
|
//printf("Rate K spectral distortion mean: %3.2f dB var: %3.2f\n", mean(dist), var(dist));
|
|
//end
|
|
#endif
|
|
|
|
|
|
|
|
}
|