1 /*
2  * Copyright (C) 2020 Linux Studio Plugins Project <https://lsp-plug.in/>
3  *           (C) 2020 Vladimir Sadovnikov <sadko4u@gmail.com>
4  *
5  * This file is part of lsp-plugins
6  * Created on: 27 авг. 2018 г.
7  *
8  * lsp-plugins is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * any later version.
12  *
13  * lsp-plugins is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with lsp-plugins. If not, see <https://www.gnu.org/licenses/>.
20  */
21 
22 #include <test/mtest.h>
23 #include <test/helpers.h>
24 
25 #include <core/types.h>
26 #include <core/alloc.h>
27 #include <data/cvector.h>
28 
29 #include <core/envelope.h>
30 #include <math.h>
31 #include <core/util/LatencyDetector.h>
32 #include <stdlib.h>
33 #include <time.h>
34 
35 #include <dsp/dsp.h>
36 
37 #define LATENCYDETECTOR_BUFFER_SIZE 1024
38 #define LATENCYDETECTOR_SAMPLE_RATE 96000
39 #define LATENCYDETECTOR_MAX_DELAY   LATENCYDETECTOR_BUFFER_SIZE - 1
40 #define LATENCYDETECTOR_DELAY_STEP  1
41 
42 using namespace lsp;
43 
44 MTEST_BEGIN("core.util", latency_detector)
45 
test_latencydetector(float * out,float * bak,float * in,size_t * delay_exact,size_t * delay_detected,size_t buf_count,size_t bak_count)46     void test_latencydetector(float *out, float *bak, float *in, size_t *delay_exact, size_t *delay_detected, size_t buf_count, size_t bak_count)
47     {
48         printf("Testing LatencyDetector... ");
49 
50         // Initialise the LatencyDetector object:
51         LatencyDetector ld;
52         ld.init();
53         ld.set_sample_rate(LATENCYDETECTOR_SAMPLE_RATE);
54         ld.set_delay_ratio(0.5f);
55         ld.set_peak_threshold(0.5f);
56         ld.set_abs_threshold(0.01f);
57 
58         // Test Parameters
59     //        ld.set_duration(0.015f);
60     //        ld.set_fading(0.030f);
61     //        ld.set_pause(0.025f);
62 
63         // Random Parameters:
64         ld.set_duration((float(rand()) * 0.040f / RAND_MAX) + 0.010f);
65         ld.set_op_fading((float(rand()) * 0.045f / RAND_MAX) + 0.005f);
66         ld.set_op_pause((float(rand()) * 0.045f / RAND_MAX) + 0.005f);
67 
68         ld.set_ip_detection((3 * 0.050f) + (float(LATENCYDETECTOR_MAX_DELAY) / LATENCYDETECTOR_SAMPLE_RATE) + 0.005f);
69 
70         if (ld.needs_update())
71             ld.update_settings();
72 
73         ld.start_capture();
74 
75     //        size_t bak_head = 0;
76 
77         while (true)
78         {
79     //            dump_buffer("in", in, buf_count);
80     //            dump_buffer("out", out, buf_count);
81             ld.process(out, in, buf_count);
82 
83             if (ld.cycle_complete())
84                 break;
85 
86             // This will work only for delays shorter than the buffer length
87 
88             // When in CS_DETECT, in out there will be the chirp. Let's put a
89             // delayed copy into in.
90 
91             // Old tail of out is in the beginning:
92             dsp::copy(in, bak, *delay_exact);
93 
94             // Body of the delayed signal after:
95             dsp::copy(&in[*delay_exact], out, buf_count - *delay_exact);
96 
97             // Save out tail:
98             dsp::copy(bak, &out[buf_count - *delay_exact], *delay_exact);
99 
100             // Do Scaling (opposite phase with negative sign).
101             dsp::mul_k2(in, -1.0f, buf_count);
102         }
103 
104         // Now latency is detected:
105         *delay_detected = ld.get_latency_samples() - buf_count;
106 
107         if (*delay_exact == *delay_detected)
108         {
109             printf("Success\n");
110         }
111         else
112         {
113             printf("FAIL: %lu", (long unsigned)(*delay_exact));
114             printf(" VS %lu\n", (long unsigned)(*delay_detected));
115         }
116     }
117 
118     MTEST_MAIN
119     {
120         size_t buf_size         = LATENCYDETECTOR_BUFFER_SIZE;
121         size_t bak_size         = LATENCYDETECTOR_BUFFER_SIZE * ceil(float(LATENCYDETECTOR_MAX_DELAY) / LATENCYDETECTOR_BUFFER_SIZE);
122 
123         float *out              = new float[buf_size];
124         float *in               = new float[buf_size];
125         float *bak              = new float[bak_size];
126 
127         size_t delay_array_size     = ceil(float(LATENCYDETECTOR_MAX_DELAY) / LATENCYDETECTOR_DELAY_STEP);
128         size_t *delays_exact        = new size_t[delay_array_size];
129         size_t *delays_detected     = new size_t[delay_array_size];
130         ssize_t *delays_error       = new ssize_t[delay_array_size];
131 
132         size_t delay_idx = 0;
133 
134         size_t count_success    = 0;
135         size_t count_fail       = 0;
136         size_t count_total      = 0;
137 
138         for (size_t delay = 0; delay < LATENCYDETECTOR_MAX_DELAY; delay += LATENCYDETECTOR_DELAY_STEP)
139         {
140             printf("%.1f Percent:\t", 100.0f * float(delay) / (LATENCYDETECTOR_MAX_DELAY - 1));
141 
142             delays_exact[delay_idx] = delay;
143             dsp::fill_zero(out, buf_size);
144             dsp::fill_zero(in, buf_size);
145             dsp::fill_zero(bak, bak_size);
146 
147             test_latencydetector(out, bak, in, &delays_exact[delay_idx], &delays_detected[delay_idx], buf_size, bak_size);
148 
149             count_total += 1;
150             if (delays_exact[delay_idx] == delays_detected[delay_idx])
151                 count_success   ++;
152             else
153                 count_fail      ++;
154 
155             delays_error[delay_idx] = delays_exact[delay_idx] - delays_detected[delay_idx];
156 
157             delay_idx += 1;
158         }
159 
160 //        dump_buffer("exact_latency",    delays_exact,       delay_array_size);
161 //        dump_buffer("detected_latency", delays_detected,    delay_array_size);
162         dump_buffer("delays_error", delays_error,    delay_array_size);
163         printf("Success Rate:\t%.1f percent\n", 100 * float(count_success) / count_total);
164         printf("Fail Rate:\t%.1f percent\n", 100 * float(count_fail) / count_total);
165 
166         delete [] out;
167         delete [] in;
168         delete [] bak;
169         delete [] delays_exact;
170         delete [] delays_detected;
171     }
172 
173 MTEST_END
174 
175 
176 
177 
178 
179