Mercurial > foo_out_sdl
comparison foosdk/sdk/foobar2000/foo_sample/dsp_sample.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 "stdafx.h" | |
| 2 #include "dsp_sample.h" | |
| 3 | |
| 4 #ifdef _WIN32 | |
| 5 #include <helpers/DarkMode.h> | |
| 6 #include "resource.h" | |
| 7 | |
| 8 static void RunDSPConfigPopup(const dsp_preset & p_data,HWND p_parent,dsp_preset_edit_callback & p_callback); | |
| 9 #endif | |
| 10 | |
| 11 #ifdef __APPLE__ | |
| 12 // fooSampleDSPView.mm | |
| 13 service_ptr ConfigureSampleDSP( fb2k::hwnd_t parent, dsp_preset_edit_callback_v2::ptr callback ); | |
| 14 #endif | |
| 15 | |
| 16 class dsp_sample : public dsp_impl_base | |
| 17 { | |
| 18 public: | |
| 19 dsp_sample(dsp_preset const & in) : m_gain(parse_preset(in)) { | |
| 20 } | |
| 21 | |
| 22 static GUID g_get_guid() { | |
| 23 return dsp_sample_common::guid; | |
| 24 } | |
| 25 | |
| 26 static void g_get_name(pfc::string_base & p_out) { p_out = "Sample DSP";} | |
| 27 | |
| 28 bool on_chunk(audio_chunk * chunk,abort_callback &) { | |
| 29 // Perform any operations on the chunk here. | |
| 30 // The most simple DSPs can just alter the chunk in-place here and skip the following functions. | |
| 31 | |
| 32 | |
| 33 // trivial DSP code: apply our gain to the audio data. | |
| 34 chunk->scale( (audio_sample)audio_math::gain_to_scale( m_gain ) ); | |
| 35 | |
| 36 // To retrieve the currently processed track, use get_cur_file(). | |
| 37 // Warning: the track is not always known - it's up to the calling component to provide this data and in some situations we'll be working with data that doesn't originate from an audio file. | |
| 38 // If you rely on get_cur_file(), you should change need_track_change_mark() to return true to get accurate information when advancing between tracks. | |
| 39 | |
| 40 return true; //Return true to keep the chunk or false to drop it from the chain. | |
| 41 } | |
| 42 | |
| 43 void on_endofplayback(abort_callback &) { | |
| 44 // The end of playlist has been reached, we've already received the last decoded audio chunk. | |
| 45 // We need to finish any pending processing and output any buffered data through insert_chunk(). | |
| 46 } | |
| 47 void on_endoftrack(abort_callback &) { | |
| 48 // Should do nothing except for special cases where your DSP performs special operations when changing tracks. | |
| 49 // If this function does anything, you must change need_track_change_mark() to return true. | |
| 50 // If you have pending audio data that you wish to output, you can use insert_chunk() to do so. | |
| 51 } | |
| 52 | |
| 53 void flush() { | |
| 54 // If you have any audio data buffered, you should drop it immediately and reset the DSP to a freshly initialized state. | |
| 55 // Called after a seek etc. | |
| 56 } | |
| 57 | |
| 58 double get_latency() { | |
| 59 // If the DSP buffers some amount of audio data, it should return the duration of buffered data (in seconds) here. | |
| 60 return 0; | |
| 61 } | |
| 62 | |
| 63 bool need_track_change_mark() { | |
| 64 // Return true if you need on_endoftrack() or need to accurately know which track we're currently processing | |
| 65 // WARNING: If you return true, the DSP manager will fire on_endofplayback() at DSPs that are before us in the chain on track change to ensure that we get an accurate mark, so use it only when needed. | |
| 66 return false; | |
| 67 } | |
| 68 static bool g_get_default_preset(dsp_preset & p_out) { | |
| 69 make_preset(0, p_out); | |
| 70 return true; | |
| 71 } | |
| 72 #ifdef _WIN32 | |
| 73 static void g_show_config_popup(const dsp_preset & p_data,HWND p_parent,dsp_preset_edit_callback & p_callback) { | |
| 74 ::RunDSPConfigPopup(p_data, p_parent, p_callback); | |
| 75 } | |
| 76 #endif // _WIN32 | |
| 77 #ifdef __APPLE__ | |
| 78 static service_ptr g_show_config_popup( fb2k::hwnd_t parent, dsp_preset_edit_callback_v2::ptr callback ) { | |
| 79 return ConfigureSampleDSP( parent, callback ); | |
| 80 } | |
| 81 #endif // __APPLE__ | |
| 82 static bool g_have_config_popup() {return true;} | |
| 83 private: | |
| 84 float m_gain; | |
| 85 }; | |
| 86 | |
| 87 // Use dsp_factory_nopreset_t<> instead of dsp_factory_t<> if your DSP does not provide preset/configuration functionality. | |
| 88 static dsp_factory_t<dsp_sample> g_dsp_sample_factory; | |
| 89 | |
| 90 #ifdef _WIN32 | |
| 91 | |
| 92 class CMyDSPPopup : public CDialogImpl<CMyDSPPopup> { | |
| 93 public: | |
| 94 CMyDSPPopup(const dsp_preset & initData, dsp_preset_edit_callback & callback) : m_initData(initData), m_callback(callback) {} | |
| 95 | |
| 96 enum { IDD = IDD_DSP }; | |
| 97 | |
| 98 enum { | |
| 99 RangeMin = -20, | |
| 100 RangeMax = 20, | |
| 101 | |
| 102 RangeTotal = RangeMax - RangeMin | |
| 103 }; | |
| 104 | |
| 105 BEGIN_MSG_MAP_EX(CMyDSPPopup) | |
| 106 MSG_WM_INITDIALOG(OnInitDialog) | |
| 107 COMMAND_HANDLER_EX(IDOK, BN_CLICKED, OnButton) | |
| 108 COMMAND_HANDLER_EX(IDCANCEL, BN_CLICKED, OnButton) | |
| 109 MSG_WM_HSCROLL(OnHScroll) | |
| 110 END_MSG_MAP() | |
| 111 | |
| 112 private: | |
| 113 | |
| 114 BOOL OnInitDialog(CWindow, LPARAM) { | |
| 115 m_dark.AddDialogWithControls(m_hWnd); | |
| 116 m_slider = GetDlgItem(IDC_SLIDER); | |
| 117 m_slider.SetRange(0, RangeTotal); | |
| 118 | |
| 119 { | |
| 120 float val = parse_preset(m_initData); | |
| 121 m_slider.SetPos( pfc::clip_t<t_int32>( pfc::rint32(val), RangeMin, RangeMax ) - RangeMin ); | |
| 122 RefreshLabel(val); | |
| 123 } | |
| 124 return TRUE; | |
| 125 } | |
| 126 | |
| 127 void OnButton(UINT, int id, CWindow) { | |
| 128 EndDialog(id); | |
| 129 } | |
| 130 | |
| 131 void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar pScrollBar) { | |
| 132 float val; | |
| 133 val = (float) ( m_slider.GetPos() + RangeMin ); | |
| 134 | |
| 135 { | |
| 136 dsp_preset_impl preset; | |
| 137 make_preset(val, preset); | |
| 138 m_callback.on_preset_changed(preset); | |
| 139 } | |
| 140 RefreshLabel(val); | |
| 141 } | |
| 142 | |
| 143 void RefreshLabel(float val) { | |
| 144 pfc::string_formatter msg; msg << pfc::format_float(val) << " dB"; | |
| 145 ::uSetDlgItemText(*this, IDC_SLIDER_LABEL, msg); | |
| 146 } | |
| 147 | |
| 148 const dsp_preset & m_initData; // modal dialog so we can reference this caller-owned object. | |
| 149 dsp_preset_edit_callback & m_callback; | |
| 150 | |
| 151 CTrackBarCtrl m_slider; | |
| 152 fb2k::CDarkModeHooks m_dark; | |
| 153 }; | |
| 154 | |
| 155 static void RunDSPConfigPopup(const dsp_preset & p_data,HWND p_parent,dsp_preset_edit_callback & p_callback) { | |
| 156 CMyDSPPopup popup(p_data, p_callback); | |
| 157 if (popup.DoModal(p_parent) != IDOK) { | |
| 158 // If the dialog exited with something else than IDOK,k | |
| 159 // tell host that the editing has been cancelled by sending it old preset data that we got initialized with | |
| 160 p_callback.on_preset_changed(p_data); | |
| 161 } | |
| 162 } | |
| 163 #endif |
