diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/foosdk/sdk/foobar2000/SDK/replaygain.cpp	Mon Jan 05 02:15:46 2026 -0500
@@ -0,0 +1,228 @@
+#include "foobar2000-sdk-pch.h"
+#include "replaygain.h"
+#include "replaygain_scanner.h"
+
+void t_replaygain_config::reset()
+{
+	m_source_mode = source_mode_none;
+	m_processing_mode = processing_mode_none;
+	m_preamp_without_rg = 0;
+	m_preamp_with_rg = 0;
+}
+
+audio_sample t_replaygain_config::query_scale(const file_info & info) const
+{
+	return query_scale(info.get_replaygain());
+}
+
+audio_sample t_replaygain_config::query_scale(const replaygain_info & info) const {
+	const audio_sample peak_margin = 1.0;//used to be 0.999 but it must not trigger on lossless
+
+	audio_sample peak = peak_margin;
+	audio_sample gain = 0;
+
+	bool have_rg_gain = false, have_rg_peak = false;
+
+	if (m_source_mode == source_mode_track || m_source_mode == source_mode_album)
+	{
+		if (m_source_mode == source_mode_track)
+		{
+			if (info.is_track_gain_present()) {gain = info.m_track_gain; have_rg_gain = true; }
+			else if (info.is_album_gain_present()) {gain = info.m_album_gain; have_rg_gain = true; }
+			if (info.is_track_peak_present()) {peak = info.m_track_peak; have_rg_peak = true; }
+			else if (info.is_album_peak_present()) {peak = info.m_album_peak; have_rg_peak = true; }
+		}
+		else
+		{
+			if (info.is_album_gain_present()) {gain = info.m_album_gain; have_rg_gain = true; }
+			else if (info.is_track_gain_present()) {gain = info.m_track_gain; have_rg_gain = true; }
+			if (info.is_album_peak_present()) {peak = info.m_album_peak; have_rg_peak = true; }
+			else if (info.is_track_peak_present()) {peak = info.m_track_peak; have_rg_peak = true; }
+		}
+	}
+
+	gain += have_rg_gain ? m_preamp_with_rg : m_preamp_without_rg;
+
+	audio_sample scale = 1.0;
+
+	if (m_processing_mode == processing_mode_gain || m_processing_mode == processing_mode_gain_and_peak)
+	{
+		scale *= (audio_sample) audio_math::gain_to_scale(gain);
+	}
+
+	if ((m_processing_mode == processing_mode_peak || m_processing_mode == processing_mode_gain_and_peak) && have_rg_peak)
+	{
+		if (scale * peak > peak_margin)
+			scale = (audio_sample)(peak_margin / peak);
+	}
+
+	return scale;
+}
+
+audio_sample t_replaygain_config::query_scale(const metadb_handle_ptr & p_object) const
+{
+	return query_scale(p_object->get_async_info_ref()->info());
+}
+
+audio_sample replaygain_manager::core_settings_query_scale(const file_info & p_info)
+{
+	t_replaygain_config temp;
+	get_core_settings(temp);
+	return temp.query_scale(p_info);
+}
+
+audio_sample replaygain_manager::core_settings_query_scale(const metadb_handle_ptr & info)
+{
+	t_replaygain_config temp;
+	get_core_settings(temp);
+	return temp.query_scale(info);
+}
+
+//enum t_source_mode {source_mode_none,source_mode_track,source_mode_album};
+//enum t_processing_mode {processing_mode_none,processing_mode_gain,processing_mode_gain_and_peak,processing_mode_peak};
+
+static const char* querysign(int val) {
+	return val < 0 ? "-" : val>0 ? "+" : "\xc2\xb1";
+}
+
+static pfc::string_fixed_t<128> format_dbdelta(double p_val) {
+	pfc::string_fixed_t<128> ret;
+	int val = (int)pfc::rint32(p_val * 10);
+	ret << querysign(val) << (abs(val) / 10) << "." << (abs(val) % 10) << "dB";
+	return ret;
+}
+void t_replaygain_config::print_preamp(double val, pfc::string_base & out) {
+	out = format_dbdelta(val);
+}
+void t_replaygain_config::format_name(pfc::string_base & p_out) const
+{
+	switch(m_processing_mode)
+	{
+	case processing_mode_none:
+		p_out = "None.";
+		break;
+	case processing_mode_gain:
+		switch(m_source_mode)
+		{
+		case source_mode_none:
+			if (m_preamp_without_rg == 0) p_out = "None."; 
+			else p_out = PFC_string_formatter() << "Preamp : " << format_dbdelta(m_preamp_without_rg);
+			break;
+		case source_mode_track:
+			{
+				pfc::string_formatter fmt;
+				fmt << "Apply track gain";
+				if (m_preamp_without_rg != 0 || m_preamp_with_rg != 0) fmt << ", with preamp";
+				fmt << ".";
+				p_out = fmt;
+			}
+			break;
+		case source_mode_album:
+			{
+				pfc::string_formatter fmt;
+				fmt << "Apply album gain";
+				if (m_preamp_without_rg != 0 || m_preamp_with_rg != 0) fmt << ", with preamp";
+				fmt << ".";
+				p_out = fmt;
+			}
+			break;
+		};
+		break;
+	case processing_mode_gain_and_peak:
+		switch(m_source_mode)
+		{
+		case source_mode_none:
+			if (m_preamp_without_rg >= 0) p_out = "None.";
+			else p_out = PFC_string_formatter() << "Preamp : " << format_dbdelta(m_preamp_without_rg);
+			break;
+		case source_mode_track:
+			{
+				pfc::string_formatter fmt;
+				fmt << "Apply track gain";
+				if (m_preamp_without_rg != 0 || m_preamp_with_rg != 0) fmt << ", with preamp";
+				fmt << ", prevent clipping according to track peak.";
+				p_out = fmt;
+			}
+			break;
+		case source_mode_album:
+			{
+				pfc::string_formatter fmt;
+				fmt << "Apply album gain";
+				if (m_preamp_without_rg != 0 || m_preamp_with_rg != 0) fmt << ", with preamp";
+				fmt << ", prevent clipping according to album peak.";
+				p_out = fmt;
+			}
+			break;
+		};
+		break;
+	case processing_mode_peak:
+		switch(m_source_mode)
+		{
+		case source_mode_none:
+			p_out = "None.";
+			break;
+		case source_mode_track:
+			p_out = "Prevent clipping according to track peak.";
+			break;
+		case source_mode_album:
+			p_out = "Prevent clipping according to album peak.";
+			break;
+		};
+		break;
+	}
+}
+
+bool t_replaygain_config::is_active() const
+{
+	switch(m_processing_mode)
+	{
+	case processing_mode_none:
+		return false;
+	case processing_mode_gain:
+		switch(m_source_mode)
+		{
+		case source_mode_none:
+			return m_preamp_without_rg != 0;
+		case source_mode_track:
+			return true;
+		case source_mode_album:
+			return true;
+		};
+		return false;
+	case processing_mode_gain_and_peak:
+		switch(m_source_mode)
+		{
+		case source_mode_none:
+			return m_preamp_without_rg < 0;
+		case source_mode_track:
+			return true;
+		case source_mode_album:
+			return true;
+		};
+		return false;
+	case processing_mode_peak:
+		switch(m_source_mode)
+		{
+		case source_mode_none:
+			return false;
+		case source_mode_track:
+			return true;
+		case source_mode_album:
+			return true;
+		};
+		return false;
+	default:
+		return false;
+	}
+}
+
+
+replaygain_scanner::ptr replaygain_scanner_entry::instantiate( uint32_t flags ) {
+	replaygain_scanner_entry_v2::ptr p2;
+	if ( p2 &= this ) return p2->instantiate( flags );
+	else return instantiate();
+}
+
+t_replaygain_config replaygain_manager::get_core_settings() {
+	t_replaygain_config cfg; get_core_settings(cfg); return cfg;
+}