1 /*
2 * lingot, a musical instrument tuner.
3 *
4 * Copyright (C) 2004-2018 Iban Cereijo.
5 * Copyright (C) 2004-2008 Jairo Chapela.
6
7 *
8 * This file is part of lingot.
9 *
10 * lingot is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * lingot is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with lingot; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24
25 #include <assert.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <math.h>
30 #include <locale.h>
31
32 #include "lingot-defs.h"
33 #include "lingot-config.h"
34 #include "lingot-config-scale.h"
35 #include "lingot-msg.h"
36 #include "lingot-i18n.h"
37
38 #define MAX(a, b) (((a) > (b)) ? (a) : (b))
39
40
lingot_config_new(LingotConfig * config)41 void lingot_config_new(LingotConfig* config) {
42
43 config->max_nr_iter = 10; // iterations
44 config->window_type = HAMMING;
45 config->optimize_internal_parameters = 0;
46 lingot_config_scale_new(&config->scale);
47 }
48
lingot_config_destroy(LingotConfig * config)49 void lingot_config_destroy(LingotConfig* config) {
50 lingot_config_scale_destroy(&config->scale);
51 }
52
lingot_config_copy(LingotConfig * dst,const LingotConfig * src)53 void lingot_config_copy(LingotConfig* dst, const LingotConfig* src) {
54 *dst = *src;
55 lingot_config_scale_new(&dst->scale); // null scale that will be destroyed in the copy below
56 lingot_config_scale_copy(&dst->scale, &src->scale);
57 }
58
59 //----------------------------------------------------------------------------
60
lingot_config_restore_default_values(LingotConfig * config)61 void lingot_config_restore_default_values(LingotConfig* config) {
62
63 #if defined(DEFAULT_AUDIO_SYSTEM_OSS)
64 config->audio_system = AUDIO_SYSTEM_OSS;
65 #elif defined(DEFAULT_AUDIO_SYSTEM_JACK)
66 config->audio_system = AUDIO_SYSTEM_JACK;
67 #elif defined(DEFAULT_AUDIO_SYSTEM_PULSEAUDIO)
68 config->audio_system = AUDIO_SYSTEM_PULSEAUDIO;
69 #else
70 config->audio_system = AUDIO_SYSTEM_ALSA;
71 #endif
72 sprintf(config->audio_dev[AUDIO_SYSTEM_OSS], "%s", "/dev/dsp");
73 sprintf(config->audio_dev[AUDIO_SYSTEM_ALSA], "%s", "default");
74 sprintf(config->audio_dev[AUDIO_SYSTEM_JACK], "%s", "default");
75 sprintf(config->audio_dev[AUDIO_SYSTEM_PULSEAUDIO], "%s", "default");
76
77 config->sample_rate = 44100; // Hz
78 config->oversampling = 21;
79 config->root_frequency_error = 0.0; // Hz
80 config->min_frequency = 82.407; // Hz (E2)
81 config->max_frequency = 329.6276; // Hz (E4)
82 config->optimize_internal_parameters = 0;
83
84 config->fft_size = 512; // samples
85 config->temporal_window = 0.3; // seconds
86 config->calculation_rate = 15.0; // Hz
87 config->visualization_rate = 24.0; // Hz
88 config->min_overall_SNR = 20.0; // dB
89
90 config->peak_number = 8; // peaks
91 config->peak_half_width = 1; // samples
92
93 //--------------------------------------------------------------------------
94
95 lingot_config_scale_restore_default_values(&config->scale);
96 lingot_config_update_internal_params(config);
97 }
98
99 //----------------------------------------------------------------------------
100
lingot_config_update_internal_params(LingotConfig * config)101 void lingot_config_update_internal_params(LingotConfig* config) {
102
103 // derived parameters.
104
105 config->internal_min_frequency = 0.8 * config->min_frequency;
106 config->internal_max_frequency = 3.1 * config->max_frequency;
107
108 if (config->internal_min_frequency < 0) {
109 config->internal_min_frequency = 0;
110 }
111 if (config->internal_max_frequency < 500) {
112 config->internal_max_frequency = 500;
113 }
114 if (config->internal_max_frequency > 20000) {
115 config->internal_max_frequency = 20000;
116 }
117
118 config->oversampling = floor(
119 0.5 * config->sample_rate / config->internal_max_frequency);
120 if (config->oversampling < 1) {
121 config->oversampling = 1;
122 }
123
124 // TODO: tune this parameters
125 unsigned int fft_size = 512;
126 if (config->internal_max_frequency > 5000) {
127 fft_size = 1024;
128 }
129 FLT temporal_window = 1.0 * config->fft_size * config->oversampling
130 / config->sample_rate;
131 if (temporal_window < 0.3) {
132 temporal_window = 0.3;
133 }
134 if (config->optimize_internal_parameters) {
135 config->fft_size = fft_size;
136 config->temporal_window = temporal_window;
137 } else {
138 // if the governed parameters happen to be the same as the one we would
139 // suggest, then we will indeed suggest them.
140 config->optimize_internal_parameters = (config->fft_size == fft_size) &&
141 (config->temporal_window == temporal_window);
142 }
143
144 config->temporal_buffer_size = (unsigned int) ceil(
145 config->temporal_window * config->sample_rate
146 / config->oversampling);
147
148 config->min_SNR = 0.5 * config->min_overall_SNR;
149 config->peak_half_width = (config->fft_size > 256) ? 2 : 1;
150
151 if (config->scale.notes == 1) {
152 config->scale.max_offset_rounded = 1200.0;
153 } else {
154 int i;
155 FLT max_offset = 0.0;
156 for (i = 1; i < config->scale.notes; i++) {
157 max_offset = MAX(max_offset, config->scale.offset_cents[i]
158 - config->scale.offset_cents[i - 1]);
159 }
160 config->scale.max_offset_rounded = max_offset;
161 }
162
163 config->gauge_rest_value = -0.45 * config->scale.max_offset_rounded;
164 }
165
166