Mercurial > foo_out_sdl
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
