comparison foosdk/sdk/foobar2000/SDK/replaygain.cpp @ 1:20d02a178406 default tip

*: check in everything else yay
author Paper <paper@tflc.us>
date Mon, 05 Jan 2026 02:15:46 -0500
parents
children
comparison
equal deleted inserted replaced
0:e9bb126753e7 1:20d02a178406
1 #include "foobar2000-sdk-pch.h"
2 #include "replaygain.h"
3 #include "replaygain_scanner.h"
4
5 void t_replaygain_config::reset()
6 {
7 m_source_mode = source_mode_none;
8 m_processing_mode = processing_mode_none;
9 m_preamp_without_rg = 0;
10 m_preamp_with_rg = 0;
11 }
12
13 audio_sample t_replaygain_config::query_scale(const file_info & info) const
14 {
15 return query_scale(info.get_replaygain());
16 }
17
18 audio_sample t_replaygain_config::query_scale(const replaygain_info & info) const {
19 const audio_sample peak_margin = 1.0;//used to be 0.999 but it must not trigger on lossless
20
21 audio_sample peak = peak_margin;
22 audio_sample gain = 0;
23
24 bool have_rg_gain = false, have_rg_peak = false;
25
26 if (m_source_mode == source_mode_track || m_source_mode == source_mode_album)
27 {
28 if (m_source_mode == source_mode_track)
29 {
30 if (info.is_track_gain_present()) {gain = info.m_track_gain; have_rg_gain = true; }
31 else if (info.is_album_gain_present()) {gain = info.m_album_gain; have_rg_gain = true; }
32 if (info.is_track_peak_present()) {peak = info.m_track_peak; have_rg_peak = true; }
33 else if (info.is_album_peak_present()) {peak = info.m_album_peak; have_rg_peak = true; }
34 }
35 else
36 {
37 if (info.is_album_gain_present()) {gain = info.m_album_gain; have_rg_gain = true; }
38 else if (info.is_track_gain_present()) {gain = info.m_track_gain; have_rg_gain = true; }
39 if (info.is_album_peak_present()) {peak = info.m_album_peak; have_rg_peak = true; }
40 else if (info.is_track_peak_present()) {peak = info.m_track_peak; have_rg_peak = true; }
41 }
42 }
43
44 gain += have_rg_gain ? m_preamp_with_rg : m_preamp_without_rg;
45
46 audio_sample scale = 1.0;
47
48 if (m_processing_mode == processing_mode_gain || m_processing_mode == processing_mode_gain_and_peak)
49 {
50 scale *= (audio_sample) audio_math::gain_to_scale(gain);
51 }
52
53 if ((m_processing_mode == processing_mode_peak || m_processing_mode == processing_mode_gain_and_peak) && have_rg_peak)
54 {
55 if (scale * peak > peak_margin)
56 scale = (audio_sample)(peak_margin / peak);
57 }
58
59 return scale;
60 }
61
62 audio_sample t_replaygain_config::query_scale(const metadb_handle_ptr & p_object) const
63 {
64 return query_scale(p_object->get_async_info_ref()->info());
65 }
66
67 audio_sample replaygain_manager::core_settings_query_scale(const file_info & p_info)
68 {
69 t_replaygain_config temp;
70 get_core_settings(temp);
71 return temp.query_scale(p_info);
72 }
73
74 audio_sample replaygain_manager::core_settings_query_scale(const metadb_handle_ptr & info)
75 {
76 t_replaygain_config temp;
77 get_core_settings(temp);
78 return temp.query_scale(info);
79 }
80
81 //enum t_source_mode {source_mode_none,source_mode_track,source_mode_album};
82 //enum t_processing_mode {processing_mode_none,processing_mode_gain,processing_mode_gain_and_peak,processing_mode_peak};
83
84 static const char* querysign(int val) {
85 return val < 0 ? "-" : val>0 ? "+" : "\xc2\xb1";
86 }
87
88 static pfc::string_fixed_t<128> format_dbdelta(double p_val) {
89 pfc::string_fixed_t<128> ret;
90 int val = (int)pfc::rint32(p_val * 10);
91 ret << querysign(val) << (abs(val) / 10) << "." << (abs(val) % 10) << "dB";
92 return ret;
93 }
94 void t_replaygain_config::print_preamp(double val, pfc::string_base & out) {
95 out = format_dbdelta(val);
96 }
97 void t_replaygain_config::format_name(pfc::string_base & p_out) const
98 {
99 switch(m_processing_mode)
100 {
101 case processing_mode_none:
102 p_out = "None.";
103 break;
104 case processing_mode_gain:
105 switch(m_source_mode)
106 {
107 case source_mode_none:
108 if (m_preamp_without_rg == 0) p_out = "None.";
109 else p_out = PFC_string_formatter() << "Preamp : " << format_dbdelta(m_preamp_without_rg);
110 break;
111 case source_mode_track:
112 {
113 pfc::string_formatter fmt;
114 fmt << "Apply track gain";
115 if (m_preamp_without_rg != 0 || m_preamp_with_rg != 0) fmt << ", with preamp";
116 fmt << ".";
117 p_out = fmt;
118 }
119 break;
120 case source_mode_album:
121 {
122 pfc::string_formatter fmt;
123 fmt << "Apply album gain";
124 if (m_preamp_without_rg != 0 || m_preamp_with_rg != 0) fmt << ", with preamp";
125 fmt << ".";
126 p_out = fmt;
127 }
128 break;
129 };
130 break;
131 case processing_mode_gain_and_peak:
132 switch(m_source_mode)
133 {
134 case source_mode_none:
135 if (m_preamp_without_rg >= 0) p_out = "None.";
136 else p_out = PFC_string_formatter() << "Preamp : " << format_dbdelta(m_preamp_without_rg);
137 break;
138 case source_mode_track:
139 {
140 pfc::string_formatter fmt;
141 fmt << "Apply track gain";
142 if (m_preamp_without_rg != 0 || m_preamp_with_rg != 0) fmt << ", with preamp";
143 fmt << ", prevent clipping according to track peak.";
144 p_out = fmt;
145 }
146 break;
147 case source_mode_album:
148 {
149 pfc::string_formatter fmt;
150 fmt << "Apply album gain";
151 if (m_preamp_without_rg != 0 || m_preamp_with_rg != 0) fmt << ", with preamp";
152 fmt << ", prevent clipping according to album peak.";
153 p_out = fmt;
154 }
155 break;
156 };
157 break;
158 case processing_mode_peak:
159 switch(m_source_mode)
160 {
161 case source_mode_none:
162 p_out = "None.";
163 break;
164 case source_mode_track:
165 p_out = "Prevent clipping according to track peak.";
166 break;
167 case source_mode_album:
168 p_out = "Prevent clipping according to album peak.";
169 break;
170 };
171 break;
172 }
173 }
174
175 bool t_replaygain_config::is_active() const
176 {
177 switch(m_processing_mode)
178 {
179 case processing_mode_none:
180 return false;
181 case processing_mode_gain:
182 switch(m_source_mode)
183 {
184 case source_mode_none:
185 return m_preamp_without_rg != 0;
186 case source_mode_track:
187 return true;
188 case source_mode_album:
189 return true;
190 };
191 return false;
192 case processing_mode_gain_and_peak:
193 switch(m_source_mode)
194 {
195 case source_mode_none:
196 return m_preamp_without_rg < 0;
197 case source_mode_track:
198 return true;
199 case source_mode_album:
200 return true;
201 };
202 return false;
203 case processing_mode_peak:
204 switch(m_source_mode)
205 {
206 case source_mode_none:
207 return false;
208 case source_mode_track:
209 return true;
210 case source_mode_album:
211 return true;
212 };
213 return false;
214 default:
215 return false;
216 }
217 }
218
219
220 replaygain_scanner::ptr replaygain_scanner_entry::instantiate( uint32_t flags ) {
221 replaygain_scanner_entry_v2::ptr p2;
222 if ( p2 &= this ) return p2->instantiate( flags );
223 else return instantiate();
224 }
225
226 t_replaygain_config replaygain_manager::get_core_settings() {
227 t_replaygain_config cfg; get_core_settings(cfg); return cfg;
228 }