diff foosdk/sdk/foobar2000/SDK/dsp_manager.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/dsp_manager.cpp	Mon Jan 05 02:15:46 2026 -0500
@@ -0,0 +1,210 @@
+#include "foobar2000-sdk-pch.h"
+#include "dsp_manager.h"
+
+#ifdef FOOBAR2000_HAVE_DSP
+
+void dsp_manager::close() {
+	m_chain.remove_all();
+	m_config_changed = true;
+}
+
+void dsp_manager::set_config( const dsp_chain_config & p_data )
+{
+	//dsp_chain_config::g_instantiate(m_dsp_list,p_data);
+	m_config.copy(p_data);
+	m_config_changed = true;
+}
+
+bool dsp_manager::need_track_change_mark() const {
+	for ( auto i = this->m_chain.first(); i.is_valid(); ++ i ) {
+		if ( i->m_dsp->need_track_change_mark() ) return true;
+	}
+	return false;
+}
+
+void dsp_manager::dsp_run(t_dsp_chain::const_iterator p_iter,dsp_chunk_list * p_list,const dsp_track_t & cur_file,unsigned flags,double & latency,abort_callback & p_abort)
+{
+	p_list->remove_bad_chunks();
+
+	TRACK_CODE("dsp::run",p_iter->m_dsp->run_abortable(p_list,cur_file,flags,p_abort));
+	TRACK_CODE("dsp::get_latency",latency += p_iter->m_dsp->get_latency());
+}
+
+double dsp_manager::run(dsp_chunk_list * p_list,const dsp_track_t & p_cur_file,unsigned p_flags,abort_callback & p_abort) {
+	TRACK_CALL_TEXT("dsp_manager::run");
+
+	try {
+#if defined(_MSC_VER) && defined(_M_IX86)
+		fpu_control_default l_fpu_control;
+#endif
+		double latency=0;
+		bool done = false;
+
+		t_dsp_chain::const_iterator flush_mark;
+		if ((p_flags & dsp::END_OF_TRACK) && ! (p_flags & dsp::FLUSH)) {
+			for(t_dsp_chain::const_iterator iter = m_chain.first(); iter.is_valid(); ++iter) {
+				if (iter->m_dsp->need_track_change_mark()) flush_mark = iter;
+			}
+		}
+
+		if (m_config_changed)
+		{
+			t_dsp_chain newchain;
+			bool recycle_available = true;
+
+			for(t_size n=0;n<m_config.get_count();n++) {
+				service_ptr_t<dsp> temp;
+
+				const dsp_preset & preset = m_config.get_item(n);
+				const GUID owner = preset.get_owner();
+				if (dsp_entry::g_dsp_exists(owner) || dsp_entry_hidden::g_dsp_exists(owner)) {
+					t_dsp_chain::iterator iter = newchain.insert_last();
+					iter->m_preset = m_config.get_item(n);
+					iter->m_recycle_flag = false;
+				}
+			}
+
+
+			// Recycle existing DSPs in a special case when user has apparently only altered settings of one of DSPs.
+			if (newchain.get_count() == m_chain.get_count()) {
+				t_size data_mismatch_count = 0;
+				t_size owner_mismatch_count = 0;
+				t_dsp_chain::iterator iter_src, iter_dst;
+				iter_src = m_chain.first(); iter_dst = newchain.first();
+				while(iter_src.is_valid() && iter_dst.is_valid()) {
+					if (iter_src->m_preset.get_owner() != iter_dst->m_preset.get_owner()) {
+						owner_mismatch_count++;
+					} else if (iter_src->m_preset != iter_dst->m_preset) {
+						data_mismatch_count++;
+					}
+					++iter_src; ++iter_dst;
+				}
+				recycle_available = (owner_mismatch_count == 0 && data_mismatch_count <= 1);
+			} else {
+				recycle_available = false;
+			}
+
+			if (recycle_available) {
+				t_dsp_chain::iterator iter_src, iter_dst;
+				iter_src = m_chain.first(); iter_dst = newchain.first();
+				while(iter_src.is_valid() && iter_dst.is_valid()) {
+					if (iter_src->m_preset == iter_dst->m_preset) {
+						iter_src->m_recycle_flag = true;
+						iter_dst->m_dsp = iter_src->m_dsp;
+					}
+					++iter_src; ++iter_dst;
+				}
+			}
+
+            for( auto & iter : newchain ) {
+				if (iter.m_dsp.is_empty()) {
+					if (!dsp_entry::g_instantiate(iter.m_dsp,iter.m_preset, m_creationFlags) && !dsp_entry_hidden::g_instantiate(iter.m_dsp, iter.m_preset)) uBugCheck();
+				}
+			}
+
+			if (m_chain.get_count()>0) {
+				bool flushflag = flush_mark.is_valid();
+				for(t_dsp_chain::const_iterator iter = m_chain.first(); iter.is_valid(); ++iter) {
+					unsigned flags2 = p_flags;
+					if (iter == flush_mark) flushflag = false;
+					if (flushflag || !iter->m_recycle_flag) flags2|=dsp::FLUSH;
+					dsp_run(iter,p_list,p_cur_file,flags2,latency,p_abort);
+				}
+				done = true;
+			}
+
+			m_chain = newchain;
+			m_config_changed = false;
+		}
+		
+		if (!done)
+		{
+			bool flushflag = flush_mark.is_valid();
+			for(t_dsp_chain::const_iterator iter = m_chain.first(); iter.is_valid(); ++iter) {
+				unsigned flags2 = p_flags;
+				if (iter == flush_mark) flushflag = false;
+				if (flushflag) flags2|=dsp::FLUSH;
+				dsp_run(iter,p_list,p_cur_file,flags2,latency,p_abort);
+			}
+			done = true;
+		}
+		
+		p_list->remove_bad_chunks();
+
+		return latency;
+	} catch(...) {
+		p_list->remove_all();
+		throw;
+	}
+}
+
+void dsp_manager::flush()
+{
+	for(t_dsp_chain::const_iterator iter = m_chain.first(); iter.is_valid(); ++iter) {
+		TRACK_CODE("dsp::flush",iter->m_dsp->flush());
+	}
+}
+
+
+bool dsp_manager::is_active() const {return m_config.get_count()>0;}
+
+void dsp_config_manager::core_enable_dsp(const dsp_preset & preset, default_insert_t insertWhere ) {
+	dsp_chain_config_impl cfg;
+	get_core_settings(cfg);
+
+	bool found = false;
+	bool changed = false;
+	t_size n,m = cfg.get_count();
+	for(n=0;n<m;n++) {
+		if (cfg.get_item(n).get_owner() == preset.get_owner()) {
+			found = true;
+			if (cfg.get_item(n) != preset) {
+				cfg.replace_item(preset,n);
+				changed = true;
+			}
+			break;
+		}
+	}
+	if (!found) {
+		if ( insertWhere == default_insert_last ) {
+			cfg.add_item( preset );
+		} else {
+			cfg.insert_item(preset,0); 
+		}
+		
+		changed = true;
+	}
+
+	if (changed) set_core_settings(cfg);
+}
+void dsp_config_manager::core_disable_dsp(const GUID & id) {
+	dsp_chain_config_impl cfg;
+	get_core_settings(cfg);
+
+	t_size n,m = cfg.get_count();
+	pfc::bit_array_bittable mask(m);
+	bool changed = false;
+	for(n=0;n<m;n++) {
+		bool axe = (cfg.get_item(n).get_owner() == id) ? true : false;
+		if (axe) changed = true;
+		mask.set(n,axe);
+	}
+	if (changed) {
+		cfg.remove_mask(mask);
+		set_core_settings(cfg);
+	}
+}
+
+bool dsp_config_manager::core_query_dsp(const GUID & id, dsp_preset & out) {
+	dsp_chain_config_impl cfg;
+	get_core_settings(cfg);
+	for(t_size n=0;n<cfg.get_count();n++) {
+		const dsp_preset & entry = cfg.get_item(n);
+		if (entry.get_owner() == id) {
+			out = entry; return true;
+		}
+	}
+	return false;
+}
+
+#endif