mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-01-26 12:35:25 +00:00
cvsd_plc: octave script for PLC visualisation
This commit is contained in:
parent
cf8890c436
commit
3d45f2d56b
@ -42,7 +42,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -51,14 +50,16 @@
|
||||
#include "btstack_cvsd_plc.h"
|
||||
#include "btstack_debug.h"
|
||||
|
||||
#define SAMPLE_FORMAT int16_t
|
||||
|
||||
static float rcos[CVSD_OLAL] = {
|
||||
0.99148655f,0.96623611f,0.92510857f,0.86950446f,
|
||||
0.80131732f,0.72286918f,0.63683150f,0.54613418f,
|
||||
0.45386582f,0.36316850f,0.27713082f,0.19868268f,
|
||||
0.13049554f,0.07489143f,0.03376389f,0.00851345f};
|
||||
|
||||
float btstack_cvsd_plc_rcos(int index){
|
||||
if (index > CVSD_OLAL) return 0;
|
||||
return rcos[index];
|
||||
}
|
||||
// taken from http://www.codeproject.com/Articles/69941/Best-Square-Root-Method-Algorithm-Function-Precisi
|
||||
// Algorithm: Babylonian Method + some manipulations on IEEE 32 bit floating point representation
|
||||
static float sqrt3(const float x){
|
||||
@ -78,12 +79,12 @@ static float sqrt3(const float x){
|
||||
return u.x;
|
||||
}
|
||||
|
||||
static float absolute(float x){
|
||||
static float btstack_cvsd_plc_absolute(float x){
|
||||
if (x < 0) x = -x;
|
||||
return x;
|
||||
}
|
||||
|
||||
static float CrossCorrelation(SAMPLE_FORMAT *x, SAMPLE_FORMAT *y){
|
||||
static float btstack_cvsd_plc_cross_correlation(BTSTACK_CVSD_PLC_SAMPLE_FORMAT *x, BTSTACK_CVSD_PLC_SAMPLE_FORMAT *y){
|
||||
float num = 0;
|
||||
float den = 0;
|
||||
float x2 = 0;
|
||||
@ -98,13 +99,13 @@ static float CrossCorrelation(SAMPLE_FORMAT *x, SAMPLE_FORMAT *y){
|
||||
return num/den;
|
||||
}
|
||||
|
||||
static int PatternMatch(SAMPLE_FORMAT *y){
|
||||
int btstack_cvsd_plc_pattern_match(BTSTACK_CVSD_PLC_SAMPLE_FORMAT *y){
|
||||
float maxCn = -999999.0; // large negative number
|
||||
int bestmatch = 0;
|
||||
float Cn;
|
||||
int n;
|
||||
for (n=0;n<CVSD_N;n++){
|
||||
Cn = CrossCorrelation(&y[CVSD_LHIST-CVSD_M], &y[n]);
|
||||
Cn = btstack_cvsd_plc_cross_correlation(&y[CVSD_LHIST-CVSD_M], &y[n]);
|
||||
if (Cn>maxCn){
|
||||
bestmatch=n;
|
||||
maxCn = Cn;
|
||||
@ -113,15 +114,15 @@ static int PatternMatch(SAMPLE_FORMAT *y){
|
||||
return bestmatch;
|
||||
}
|
||||
|
||||
static float AmplitudeMatch(btstack_cvsd_plc_state_t *plc_state, SAMPLE_FORMAT *y, SAMPLE_FORMAT bestmatch) {
|
||||
float btstack_cvsd_plc_amplitude_match(btstack_cvsd_plc_state_t *plc_state, BTSTACK_CVSD_PLC_SAMPLE_FORMAT *y, BTSTACK_CVSD_PLC_SAMPLE_FORMAT bestmatch){
|
||||
int i;
|
||||
float sumx = 0;
|
||||
float sumy = 0.000001f;
|
||||
float sf;
|
||||
|
||||
for (i=0;i<plc_state->cvsd_fs;i++){
|
||||
sumx += absolute(y[CVSD_LHIST-plc_state->cvsd_fs+i]);
|
||||
sumy += absolute(y[bestmatch+i]);
|
||||
sumx += btstack_cvsd_plc_absolute(y[CVSD_LHIST-plc_state->cvsd_fs+i]);
|
||||
sumy += btstack_cvsd_plc_absolute(y[bestmatch+i]);
|
||||
}
|
||||
sf = sumx/sumy;
|
||||
// This is not in the paper, but limit the scaling factor to something reasonable to avoid creating artifacts
|
||||
@ -130,18 +131,18 @@ static float AmplitudeMatch(btstack_cvsd_plc_state_t *plc_state, SAMPLE_FORMAT *
|
||||
return sf;
|
||||
}
|
||||
|
||||
static SAMPLE_FORMAT crop_sample(float val){
|
||||
BTSTACK_CVSD_PLC_SAMPLE_FORMAT btstack_cvsd_plc_crop_sample(float val){
|
||||
float croped_val = val;
|
||||
if (croped_val > 32767.0) croped_val= 32767.0;
|
||||
if (croped_val < -32768.0) croped_val=-32768.0;
|
||||
return (SAMPLE_FORMAT) croped_val;
|
||||
return (BTSTACK_CVSD_PLC_SAMPLE_FORMAT) croped_val;
|
||||
}
|
||||
|
||||
void btstack_cvsd_plc_init(btstack_cvsd_plc_state_t *plc_state){
|
||||
memset(plc_state, 0, sizeof(btstack_cvsd_plc_state_t));
|
||||
}
|
||||
|
||||
void btstack_cvsd_plc_bad_frame(btstack_cvsd_plc_state_t *plc_state, SAMPLE_FORMAT *out){
|
||||
void btstack_cvsd_plc_bad_frame(btstack_cvsd_plc_state_t *plc_state, BTSTACK_CVSD_PLC_SAMPLE_FORMAT *out){
|
||||
float val;
|
||||
int i = 0;
|
||||
float sf = 1;
|
||||
@ -149,27 +150,27 @@ void btstack_cvsd_plc_bad_frame(btstack_cvsd_plc_state_t *plc_state, SAMPLE_FORM
|
||||
// plc_state->cvsd_fs = CVSD_FS_MAX;
|
||||
if (plc_state->nbf==1){
|
||||
// Perform pattern matching to find where to replicate
|
||||
plc_state->bestlag = PatternMatch(plc_state->hist);
|
||||
plc_state->bestlag = btstack_cvsd_plc_pattern_match(plc_state->hist);
|
||||
// the replication begins after the template match
|
||||
plc_state->bestlag += CVSD_M;
|
||||
|
||||
// Compute Scale Factor to Match Amplitude of Substitution Packet to that of Preceding Packet
|
||||
sf = AmplitudeMatch(plc_state, plc_state->hist, plc_state->bestlag);
|
||||
sf = btstack_cvsd_plc_amplitude_match(plc_state, plc_state->hist, plc_state->bestlag);
|
||||
for (i=0;i<CVSD_OLAL;i++){
|
||||
val = sf*plc_state->hist[plc_state->bestlag+i];
|
||||
plc_state->hist[CVSD_LHIST+i] = crop_sample(val);
|
||||
plc_state->hist[CVSD_LHIST+i] = btstack_cvsd_plc_crop_sample(val);
|
||||
}
|
||||
|
||||
for (;i<plc_state->cvsd_fs;i++){
|
||||
val = sf*plc_state->hist[plc_state->bestlag+i];
|
||||
plc_state->hist[CVSD_LHIST+i] = crop_sample(val);
|
||||
plc_state->hist[CVSD_LHIST+i] = btstack_cvsd_plc_crop_sample(val);
|
||||
}
|
||||
|
||||
for (;i<plc_state->cvsd_fs+CVSD_OLAL;i++){
|
||||
float left = sf*plc_state->hist[plc_state->bestlag+i];
|
||||
float right = plc_state->hist[plc_state->bestlag+i];
|
||||
val = left*rcos[i-plc_state->cvsd_fs] + right*rcos[CVSD_OLAL-1-i+plc_state->cvsd_fs];
|
||||
plc_state->hist[CVSD_LHIST+i] = crop_sample(val);
|
||||
plc_state->hist[CVSD_LHIST+i] = btstack_cvsd_plc_crop_sample(val);
|
||||
}
|
||||
|
||||
for (;i<plc_state->cvsd_fs+CVSD_RT+CVSD_OLAL;i++){
|
||||
@ -191,7 +192,7 @@ void btstack_cvsd_plc_bad_frame(btstack_cvsd_plc_state_t *plc_state, SAMPLE_FORM
|
||||
}
|
||||
}
|
||||
|
||||
void btstack_cvsd_plc_good_frame(btstack_cvsd_plc_state_t *plc_state, SAMPLE_FORMAT *in, SAMPLE_FORMAT *out){
|
||||
void btstack_cvsd_plc_good_frame(btstack_cvsd_plc_state_t *plc_state, BTSTACK_CVSD_PLC_SAMPLE_FORMAT *in, BTSTACK_CVSD_PLC_SAMPLE_FORMAT *out){
|
||||
float val;
|
||||
int i = 0;
|
||||
if (plc_state->nbf>0){
|
||||
@ -203,7 +204,7 @@ void btstack_cvsd_plc_good_frame(btstack_cvsd_plc_state_t *plc_state, SAMPLE_FOR
|
||||
float left = plc_state->hist[CVSD_LHIST+i];
|
||||
float right = in[i];
|
||||
val = left * rcos[i-CVSD_RT] + right *rcos[CVSD_OLAL+CVSD_RT-1-i];
|
||||
out[i] = (SAMPLE_FORMAT)val;
|
||||
out[i] = (BTSTACK_CVSD_PLC_SAMPLE_FORMAT)val;
|
||||
}
|
||||
}
|
||||
|
||||
@ -221,7 +222,7 @@ void btstack_cvsd_plc_good_frame(btstack_cvsd_plc_state_t *plc_state, SAMPLE_FOR
|
||||
plc_state->nbf=0;
|
||||
}
|
||||
|
||||
static int count_equal_samples(SAMPLE_FORMAT * packet, uint16_t size){
|
||||
static int count_equal_samples(BTSTACK_CVSD_PLC_SAMPLE_FORMAT * packet, uint16_t size){
|
||||
int count = 0;
|
||||
int temp_count = 1;
|
||||
int i;
|
||||
@ -241,11 +242,11 @@ static int count_equal_samples(SAMPLE_FORMAT * packet, uint16_t size){
|
||||
return count;
|
||||
}
|
||||
|
||||
static int bad_frame(btstack_cvsd_plc_state_t *plc_state, SAMPLE_FORMAT * frame, uint16_t size){
|
||||
static int bad_frame(btstack_cvsd_plc_state_t *plc_state, BTSTACK_CVSD_PLC_SAMPLE_FORMAT * frame, uint16_t size){
|
||||
return count_equal_samples(frame, size) > plc_state->cvsd_fs - 4;
|
||||
}
|
||||
|
||||
void btstack_cvsd_plc_process_data(btstack_cvsd_plc_state_t * plc_state, SAMPLE_FORMAT * in, uint16_t size, SAMPLE_FORMAT * out){
|
||||
void btstack_cvsd_plc_process_data(btstack_cvsd_plc_state_t * plc_state, BTSTACK_CVSD_PLC_SAMPLE_FORMAT * in, uint16_t size, BTSTACK_CVSD_PLC_SAMPLE_FORMAT * out){
|
||||
if (plc_state->cvsd_fs == 0){
|
||||
if (size > CVSD_FS_MAX){
|
||||
log_error("btstack_cvsd_plc_process_data: audio frame size is too large.");
|
||||
|
@ -49,6 +49,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define BTSTACK_CVSD_PLC_SAMPLE_FORMAT int16_t
|
||||
|
||||
#define CVSD_FS_MAX 60 /* CVSD Frame Size */
|
||||
#define CVSD_N 256 /* Window Length for pattern matching */
|
||||
@ -77,6 +78,12 @@ void btstack_cvsd_plc_good_frame(btstack_cvsd_plc_state_t *plc_state, int16_t *i
|
||||
void btstack_cvsd_plc_process_data(btstack_cvsd_plc_state_t * state, int16_t * in, uint16_t size, int16_t * out);
|
||||
void btstack_cvsd_dump_statistics(btstack_cvsd_plc_state_t * state);
|
||||
|
||||
// testing only
|
||||
int btstack_cvsd_plc_pattern_match(BTSTACK_CVSD_PLC_SAMPLE_FORMAT *y);
|
||||
float btstack_cvsd_plc_amplitude_match(btstack_cvsd_plc_state_t *plc_state, BTSTACK_CVSD_PLC_SAMPLE_FORMAT *y, BTSTACK_CVSD_PLC_SAMPLE_FORMAT bestmatch);
|
||||
BTSTACK_CVSD_PLC_SAMPLE_FORMAT btstack_cvsd_plc_crop_sample(float val);
|
||||
float btstack_cvsd_plc_rcos(int index);
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -11,15 +11,15 @@
|
||||
#include "btstack_cvsd_plc.h"
|
||||
#include "wav_util.h"
|
||||
|
||||
const int audio_samples_per_frame = 24;
|
||||
const int audio_samples_per_frame = 60;
|
||||
static int16_t audio_frame_in[audio_samples_per_frame];
|
||||
|
||||
static int16_t test_data[][audio_samples_per_frame] = {
|
||||
{ 0x05, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
|
||||
{ 0xff, 0xff, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x05 },
|
||||
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05 },
|
||||
{ 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
};
|
||||
// static int16_t test_data[][audio_samples_per_frame] = {
|
||||
// { 0x05, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
|
||||
// { 0xff, 0xff, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x05 },
|
||||
// { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05 },
|
||||
// { 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
// };
|
||||
|
||||
static btstack_cvsd_plc_state_t plc_state;
|
||||
|
||||
@ -59,16 +59,11 @@ static int count_equal_samples(int16_t * packet, uint16_t size){
|
||||
|
||||
// @assumption frame len 24 samples
|
||||
static int bad_frame(int16_t * frame, uint16_t size){
|
||||
return count_equal_samples(frame, size) > 20;
|
||||
return count_equal_samples(frame, size) > audio_samples_per_frame - 4;
|
||||
}
|
||||
|
||||
static void btstack_cvsd_plc_mark_bad_frame(btstack_cvsd_plc_state_t * state, int16_t * in, uint16_t size, int16_t * out){
|
||||
if (size != 24){
|
||||
printf("btstack_cvsd_plc_mark_bad_frame: audio frame size is incorrect. Expected %d, got %d\n", audio_samples_per_frame, size);
|
||||
return;
|
||||
}
|
||||
state->frame_count++;
|
||||
|
||||
if (bad_frame(in,size)){
|
||||
memcpy(out, in, size * 2);
|
||||
if (state->good_frames_nr > CVSD_LHIST/audio_samples_per_frame){
|
||||
@ -85,10 +80,10 @@ static void btstack_cvsd_plc_mark_bad_frame(btstack_cvsd_plc_state_t * state, in
|
||||
}
|
||||
|
||||
static int phase = 0;
|
||||
static void create_sine_wave_int16_data(int num_samples, int16_t * data){
|
||||
void create_sine_wave_int16_data(int num_samples, int16_t * data){
|
||||
int i;
|
||||
for (i=0; i < num_samples; i++){
|
||||
data[i] = sine_int16[phase++];
|
||||
data[i] = sine_int16[phase++] * 90/100;
|
||||
phase++;
|
||||
if (phase >= (sizeof(sine_int16) / sizeof(int16_t))){
|
||||
phase = 0;
|
||||
@ -96,25 +91,25 @@ static void create_sine_wave_int16_data(int num_samples, int16_t * data){
|
||||
}
|
||||
}
|
||||
|
||||
static int count_equal_bytes(int16_t * packet, uint16_t size){
|
||||
int count = 0;
|
||||
int temp_count = 1;
|
||||
int i;
|
||||
for (i = 0; i < size-1; i++){
|
||||
if (packet[i] == packet[i+1]){
|
||||
temp_count++;
|
||||
continue;
|
||||
}
|
||||
if (count < temp_count){
|
||||
count = temp_count;
|
||||
}
|
||||
temp_count = 1;
|
||||
}
|
||||
if (temp_count > count + 1){
|
||||
count = temp_count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
// static int count_equal_bytes(int16_t * packet, uint16_t size){
|
||||
// int count = 0;
|
||||
// int temp_count = 1;
|
||||
// int i;
|
||||
// for (i = 0; i < size-1; i++){
|
||||
// if (packet[i] == packet[i+1]){
|
||||
// temp_count++;
|
||||
// continue;
|
||||
// }
|
||||
// if (count < temp_count){
|
||||
// count = temp_count;
|
||||
// }
|
||||
// temp_count = 1;
|
||||
// }
|
||||
// if (temp_count > count + 1){
|
||||
// count = temp_count;
|
||||
// }
|
||||
// return count;
|
||||
// }
|
||||
|
||||
void create_sine_wav(const char * out_filename){
|
||||
btstack_cvsd_plc_init(&plc_state);
|
||||
@ -181,13 +176,156 @@ TEST_GROUP(CVSD_PLC){
|
||||
|
||||
};
|
||||
|
||||
TEST(CVSD_PLC, CountEqBytes){
|
||||
CHECK_EQUAL(23, count_equal_bytes(test_data[0],24));
|
||||
CHECK_EQUAL(11, count_equal_bytes(test_data[1],24));
|
||||
CHECK_EQUAL(12, count_equal_bytes(test_data[2],24));
|
||||
CHECK_EQUAL(23, count_equal_bytes(test_data[3],24));
|
||||
static void fprintf_array_int16(FILE * oct_file, char * name, int data_len, int16_t * data){
|
||||
fprintf(oct_file, "%s = [", name);
|
||||
int i;
|
||||
for (i = 0; i < data_len - 1; i++){
|
||||
fprintf(oct_file, "%d, ", data[i]);
|
||||
}
|
||||
fprintf(oct_file, "%d", data[i]);
|
||||
fprintf(oct_file, "%s", "];\n");
|
||||
}
|
||||
|
||||
static void fprintf_plot_history(FILE * oct_file, char * name, int data_len, int16_t * data){
|
||||
fprintf_array_int16(oct_file, name, CVSD_LHIST, plc_state.hist);
|
||||
|
||||
fprintf(oct_file, "y = [min(%s):1000:max(%s)];\n", name, name);
|
||||
fprintf(oct_file, "x = zeros(1, size(y,2));\n");
|
||||
fprintf(oct_file, "b = [0:500];\n");
|
||||
|
||||
int pos = CVSD_FS_MAX;
|
||||
fprintf(oct_file, "shift_x = x + %d;\n", pos);
|
||||
|
||||
pos = CVSD_LHIST - 1;
|
||||
fprintf(oct_file, "lhist_x = x + %d;\n", pos);
|
||||
pos += CVSD_OLAL;
|
||||
fprintf(oct_file, "lhist_olal1_x = x + %d;\n", pos);
|
||||
pos += CVSD_FS_MAX - CVSD_OLAL;
|
||||
fprintf(oct_file, "lhist_fs_x = x + %d;\n", pos);
|
||||
pos += CVSD_OLAL;
|
||||
fprintf(oct_file, "lhist_olal2_x = x + %d;\n", pos);
|
||||
pos += CVSD_RT;
|
||||
fprintf(oct_file, "lhist_rt_x = x + %d;\n", pos);
|
||||
|
||||
fprintf(oct_file, "pattern_window_x = x + %d;\n", CVSD_LHIST - CVSD_M);
|
||||
|
||||
fprintf(oct_file, "hold on;\n");
|
||||
fprintf(oct_file, "plot(%s); \n", name);
|
||||
|
||||
fprintf(oct_file, "plot(shift_x, y, 'k--'); \n");
|
||||
fprintf(oct_file, "plot(lhist_x, y, 'k'); \n");
|
||||
fprintf(oct_file, "plot(lhist_olal1_x, y, 'k'); \n");
|
||||
fprintf(oct_file, "plot(lhist_fs_x, y, 'k'); \n");
|
||||
fprintf(oct_file, "plot(lhist_olal2_x, y, 'k'); \n");
|
||||
fprintf(oct_file, "plot(lhist_rt_x, y, 'k');\n");
|
||||
|
||||
int x0 = plc_state.bestlag;
|
||||
int x1 = plc_state.bestlag + CVSD_M - 1;
|
||||
fprintf(oct_file, "plot(b(%d:%d), %s(%d:%d), 'rd'); \n", x0, x1, name, x0, x1);
|
||||
|
||||
x0 = plc_state.bestlag + CVSD_M ;
|
||||
x1 = plc_state.bestlag + CVSD_M + audio_samples_per_frame - 1;
|
||||
fprintf(oct_file, "plot(b(%d:%d), %s(%d:%d), 'kd'); \n", x0, x1, name, x0, x1);
|
||||
|
||||
x0 = CVSD_LHIST - CVSD_M;
|
||||
x1 = CVSD_LHIST - 1;
|
||||
fprintf(oct_file, "plot(b(%d:%d), %s(%d:%d), 'rd'); \n", x0, x1, name, x0, x1);
|
||||
fprintf(oct_file, "plot(pattern_window_x, y, 'g'); \n");
|
||||
}
|
||||
|
||||
TEST(CVSD_PLC, CountEqBytes){
|
||||
// init cvsd_fs in plc_state
|
||||
plc_state.cvsd_fs = audio_samples_per_frame;
|
||||
|
||||
float val, sf;
|
||||
int i, x0, x1;
|
||||
|
||||
char * name;
|
||||
BTSTACK_CVSD_PLC_SAMPLE_FORMAT out[CVSD_FS_MAX];
|
||||
BTSTACK_CVSD_PLC_SAMPLE_FORMAT hist[CVSD_LHIST+CVSD_FS_MAX+CVSD_RT+CVSD_OLAL];
|
||||
FILE * oct_file = fopen("/Users/mringwal/octave/plc.m", "wb");
|
||||
if (!oct_file) return;
|
||||
fprintf(oct_file, "%s", "1;\n\n");
|
||||
|
||||
int hist_len = sizeof(plc_state.hist)/2;
|
||||
create_sine_wave_int16_data(CVSD_LHIST, hist);
|
||||
memset(plc_state.hist, hist[CVSD_LHIST-1], sizeof(plc_state.hist));
|
||||
memcpy(plc_state.hist, hist, CVSD_LHIST*2);
|
||||
|
||||
// Perform pattern matching to find where to replicate
|
||||
plc_state.bestlag = btstack_cvsd_plc_pattern_match(plc_state.hist);
|
||||
name = (char *) "hist0";
|
||||
fprintf_plot_history(oct_file, name, hist_len, plc_state.hist);
|
||||
|
||||
plc_state.bestlag += CVSD_M;
|
||||
sf = btstack_cvsd_plc_amplitude_match(&plc_state, plc_state.hist, plc_state.bestlag);
|
||||
|
||||
for (i=0;i<CVSD_OLAL;i++){
|
||||
val = sf*plc_state.hist[plc_state.bestlag+i];
|
||||
plc_state.hist[CVSD_LHIST+i] = btstack_cvsd_plc_crop_sample(val);
|
||||
}
|
||||
name = (char *) "olal1";
|
||||
x0 = CVSD_LHIST;
|
||||
x1 = x0 + CVSD_OLAL - 1;
|
||||
fprintf_array_int16(oct_file, name, CVSD_OLAL, plc_state.hist+x0);
|
||||
fprintf(oct_file, "plot(b(%d:%d), %s, 'b.'); \n", x0, x1, name);
|
||||
|
||||
for (;i<CVSD_FS_MAX;i++){
|
||||
val = sf*plc_state.hist[plc_state.bestlag+i];
|
||||
plc_state.hist[CVSD_LHIST+i] = btstack_cvsd_plc_crop_sample(val);
|
||||
}
|
||||
name = (char *)"fs_minus_olal";
|
||||
x0 = x1 + 1;
|
||||
x1 = x0 + CVSD_FS_MAX - CVSD_OLAL - 1;
|
||||
fprintf_array_int16(oct_file, name, CVSD_FS_MAX - CVSD_OLAL, plc_state.hist+x0);
|
||||
fprintf(oct_file, "plot(b(%d:%d), %s, 'b.'); \n", x0, x1, name);
|
||||
|
||||
|
||||
for (;i<CVSD_FS_MAX+CVSD_OLAL;i++){
|
||||
float left = sf*plc_state.hist[plc_state.bestlag+i];
|
||||
float right = plc_state.hist[plc_state.bestlag+i];
|
||||
val = left*btstack_cvsd_plc_rcos(i-CVSD_FS_MAX) + right*btstack_cvsd_plc_rcos(CVSD_OLAL-1-i+CVSD_FS_MAX);
|
||||
plc_state.hist[CVSD_LHIST+i] = btstack_cvsd_plc_crop_sample(val);
|
||||
}
|
||||
name = (char *)"olal2";
|
||||
x0 = x1 + 1;
|
||||
x1 = x0 + CVSD_OLAL - 1;
|
||||
fprintf_array_int16(oct_file, name, CVSD_OLAL, plc_state.hist+x0);
|
||||
fprintf(oct_file, "plot(b(%d:%d), %s, 'b.'); \n", x0, x1, name);
|
||||
|
||||
for (;i<CVSD_FS_MAX+CVSD_RT+CVSD_OLAL;i++){
|
||||
plc_state.hist[CVSD_LHIST+i] = plc_state.hist[plc_state.bestlag+i];
|
||||
}
|
||||
name = (char *)"rt";
|
||||
x0 = x1 + 1;
|
||||
x1 = x0 + CVSD_RT - 1;
|
||||
fprintf_array_int16(oct_file, name, CVSD_RT, plc_state.hist+x0);
|
||||
fprintf(oct_file, "plot(b(%d:%d), %s, 'b.'); \n", x0, x1, name);
|
||||
|
||||
for (i=0;i<CVSD_FS_MAX;i++){
|
||||
out[i] = plc_state.hist[CVSD_LHIST+i];
|
||||
}
|
||||
name = (char *)"out";
|
||||
x0 = CVSD_LHIST;
|
||||
x1 = x0 + CVSD_FS_MAX - 1;
|
||||
fprintf_array_int16(oct_file, name, CVSD_FS_MAX, plc_state.hist+x0);
|
||||
fprintf(oct_file, "plot(b(%d:%d), %s, 'cd'); \n", x0, x1, name);
|
||||
|
||||
// shift the history buffer
|
||||
for (i=0;i<CVSD_LHIST+CVSD_RT+CVSD_OLAL;i++){
|
||||
plc_state.hist[i] = plc_state.hist[i+CVSD_FS_MAX];
|
||||
}
|
||||
fclose(oct_file);
|
||||
}
|
||||
|
||||
|
||||
// TEST(CVSD_PLC, CountEqBytes){
|
||||
// CHECK_EQUAL(23, count_equal_bytes(test_data[0],24));
|
||||
// CHECK_EQUAL(11, count_equal_bytes(test_data[1],24));
|
||||
// CHECK_EQUAL(12, count_equal_bytes(test_data[2],24));
|
||||
// CHECK_EQUAL(23, count_equal_bytes(test_data[3],24));
|
||||
// }
|
||||
|
||||
TEST(CVSD_PLC, TestLiveWavFile){
|
||||
int corruption_step = 10;
|
||||
introduce_bad_frames_to_wav_file("data/sco_input-16bit.wav", "results/sco_input.wav", 0);
|
||||
@ -209,7 +347,7 @@ TEST(CVSD_PLC, TestFanfareFile){
|
||||
}
|
||||
|
||||
TEST(CVSD_PLC, TestSineWave){
|
||||
int corruption_step = 10;
|
||||
int corruption_step = 25;
|
||||
create_sine_wav("results/sine_test.wav");
|
||||
introduce_bad_frames_to_wav_file("results/sine_test.wav", "results/sine_test_with_bad_frames.wav", corruption_step);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user