Guest User

Untitled

a guest
Jul 15th, 2018
93
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.03 KB | None | 0 0
  1. #define _WIN32_WINNT 0x0501
  2. #include "../SDK/foobar2000.h"
  3. #include "../helpers/dropdown_helper.h"
  4. #include "../ATLHelpers/ATLHelpers.h"
  5. #include "resource.h"
  6. #include "circular_buffer.h"
  7. #include "speex_resampler.h"
  8. #define BUFFER_SIZE 1024
  9. static void RunDSPConfigPopup( const dsp_preset & p_data, HWND p_parent, dsp_preset_edit_callback & p_callback );
  10. class dsp_resample_speex : public dsp_impl_base
  11. {
  12. int m_rate, m_ch, m_ch_mask;
  13. int new_rate;
  14. int q_setting;
  15. circular_buffer<audio_sample>sample_buffer;
  16. pfc::array_t<audio_sample>in_samples;
  17. t_size in_sample_count;
  18. pfc::array_t<audio_sample>out_samples;
  19. unsigned buffered;
  20. SpeexResamplerState *resampler;
  21. public:
  22. dsp_resample_speex(dsp_preset const & in) :m_rate( 0 ), m_ch( 0 ), m_ch_mask( 0 ),buffered(0),q_setting(5),new_rate(48000) {
  23. resampler = NULL;
  24. parse_preset( q_setting, new_rate ,in);
  25. }
  26.  
  27. ~dsp_resample_speex(){
  28. if (resampler) speex_resampler_destroy(resampler);
  29. resampler = NULL;
  30. }
  31.  
  32. // Every DSP type is identified by a GUID.
  33. static GUID g_get_guid() {
  34. // {C2D19FE8-5AFB-4C91-B39D-C54643F35B81}
  35. static const GUID guid =
  36. { 0xc2d19fe8, 0x5afb, 0x4c91, { 0xb3, 0x9d, 0xc5, 0x46, 0x43, 0xf3, 0x5b, 0x81 } };
  37. return guid;
  38. }
  39.  
  40. static void g_get_name(pfc::string_base & p_out) {
  41. p_out = "Resampler (Speex)";
  42. }
  43.  
  44. virtual void on_endoftrack(abort_callback & p_abort) {
  45. }
  46.  
  47. virtual void on_endofplayback(abort_callback & p_abort) {
  48. if (buffered)
  49. {
  50. audio_sample * input = in_samples.get_ptr();
  51. audio_sample * output = out_samples.get_ptr();
  52. int done = sample_buffer.read(input,buffered*m_ch);//number of individual samples
  53. t_size in_sample_count = buffered; //number of sample pairs
  54. t_size out_sample_count = buffered; //initialize
  55. while (in_sample_count > 0)
  56. {
  57. unsigned todo = min(BUFFER_SIZE, in_sample_count);
  58. int res = speex_resampler_process_interleaved_float(resampler,input,&todo,output,&out_sample_count);
  59. audio_chunk *out_chunk = insert_chunk(out_sample_count);
  60. out_chunk->set_data_32(output,out_sample_count, m_ch, new_rate);
  61. input += todo*m_ch;
  62. in_sample_count -= todo;
  63. }
  64. buffered = 0;
  65. }
  66. }
  67.  
  68. virtual bool on_chunk(audio_chunk * chunk, abort_callback & p_abort) {
  69. t_size sample_count = chunk->get_sample_count();
  70. audio_sample * source_samples = chunk->get_data();
  71.  
  72. if (chunk-> get_srate() != m_rate|| chunk->get_channels() != m_ch || chunk->get_channel_config() != m_ch_mask )
  73. {
  74. m_rate = chunk->get_srate();
  75. m_ch = chunk->get_channels();
  76. m_ch_mask = chunk->get_channel_config();
  77. sample_buffer.set_size(BUFFER_SIZE*m_ch);
  78. in_samples.set_size(0);
  79. out_samples.set_size(0);
  80. int err=0;
  81. if (resampler) speex_resampler_destroy(resampler);
  82. resampler = NULL;
  83. resampler = speex_resampler_init(m_ch, m_rate, new_rate, q_setting, &err);
  84. if (err) return 0;
  85. }
  86. in_samples.grow_size(BUFFER_SIZE*m_ch);
  87. out_samples.grow_size(BUFFER_SIZE*m_ch);
  88. while (sample_count > 0)
  89. {
  90. int todo = min(BUFFER_SIZE - buffered, sample_count);
  91. bool canWrite = sample_buffer.write(source_samples,todo*m_ch);
  92. source_samples += todo * m_ch;
  93. buffered += todo;
  94. sample_count -= todo;
  95. if (buffered == BUFFER_SIZE)
  96. {
  97. audio_sample * input = in_samples.get_ptr();
  98. audio_sample * output = out_samples.get_ptr();
  99. int done = sample_buffer.read(input,buffered*m_ch);//number of individual samples
  100. t_size in_sample_count = buffered; //number of sample pairs
  101. t_size out_sample_count = buffered; //initialize
  102. while (in_sample_count > 0)
  103. {
  104. unsigned todo = min(BUFFER_SIZE, in_sample_count);
  105. int res = speex_resampler_process_interleaved_float(resampler,input,&todo,output,&out_sample_count);
  106. audio_chunk *out_chunk = insert_chunk(out_sample_count);
  107. out_chunk->set_data_32(output,out_sample_count, m_ch, new_rate);
  108. input += todo*m_ch;
  109. in_sample_count -= todo;
  110. }
  111. buffered = 0;
  112. }
  113. }
  114. return false;
  115. }
  116.  
  117. virtual void flush() {
  118. m_rate = m_ch = m_ch_mask = buffered = in_sample_count = 0;
  119. }
  120.  
  121. virtual double get_latency() {
  122. return (resampler) ? ((double)buffered / (double)new_rate): 0;
  123. }
  124.  
  125. virtual bool need_track_change_mark() {
  126. return false;
  127. }
  128.  
  129. static bool g_get_default_preset( dsp_preset & p_out )
  130. {
  131. make_preset( 5,48000, p_out );
  132. return true;
  133. }
  134. static void g_show_config_popup( const dsp_preset & p_data, HWND p_parent, dsp_preset_edit_callback & p_callback )
  135. {
  136. ::RunDSPConfigPopup( p_data, p_parent, p_callback );
  137. }
  138. static bool g_have_config_popup() { return true; }
  139. static void make_preset( int q_setting, int new_rate, dsp_preset & out )
  140. {
  141. dsp_preset_builder builder;
  142. builder << q_setting;
  143. builder << new_rate;
  144. builder.finish( g_get_guid(), out );
  145. }
  146. static void parse_preset(int & q_setting, int & new_rate, const dsp_preset & in)
  147. {
  148. try
  149. {
  150. dsp_preset_parser parser(in);
  151. parser >> q_setting;
  152. parser >> new_rate;
  153. }
  154. catch(exception_io_data) {q_setting = 5;new_rate=48000;}
  155. }
  156. };
  157.  
  158.  
  159.  
  160. class dsp_resample_speex_entry : public resampler_entry
  161. {
  162. public:
  163. dsp_resample_speex_entry() {
  164.  
  165. };
  166. };
  167.  
  168.  
  169. const long samplerates[] = {8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000, 176400, 192000};
  170. const TCHAR* samplerates_s[] = {L"8000", L"11025", L"16000", L"22050",L"24000",L"32000",
  171. L"44100",L"48000", L"64000",L"88200",L"96000", L"176400",L"192000"};
  172. const TCHAR * q_settings []={L"0",L"1", L"2" ,L"3 (VoIP)", L"4 (Default)", L"5 (Desktop)", L"6", L"7", L"8", L"9", L"10"};
  173. class CMyDSPPopupResample : public CDialogImpl<CMyDSPPopupResample>
  174. {
  175. public:
  176. CMyDSPPopupResample( const dsp_preset & initData, dsp_preset_edit_callback & callback ) : m_initData( initData ), m_callback( callback ) { }
  177. enum { IDD = IDD_RESAMPLER };
  178. BEGIN_MSG_MAP( CMyDSPPopup )
  179. MSG_WM_INITDIALOG( OnInitDialog )
  180. COMMAND_HANDLER_EX( IDOK, BN_CLICKED, OnButton )
  181. COMMAND_HANDLER_EX( IDCANCEL, BN_CLICKED, OnButton )
  182. COMMAND_HANDLER_EX(IDC_SAMPLERATE, CBN_SELCHANGE, OnSampleRateChange)
  183. COMMAND_HANDLER_EX(IDC_RESAMPLEQ, CBN_SELCHANGE, OnQChange)
  184. END_MSG_MAP()
  185. private:
  186. BOOL OnInitDialog(CWindow, LPARAM)
  187. {
  188. int new_rate;
  189. int q_setting;
  190. TCHAR temp[16] = {0};
  191. samplerate_select = GetDlgItem(IDC_SAMPLERATE);
  192. quality_select = GetDlgItem(IDC_RESAMPLEQ);
  193. int n;
  194. dsp_resample_speex::parse_preset(q_setting,new_rate, m_initData);
  195. for (n=0;n<tabsize(samplerates_s);n++)
  196. {
  197. samplerate_select.AddString(samplerates_s[n]);
  198. }
  199. _itow(new_rate,temp,10);
  200. int pos = samplerate_select.FindString(0,temp);
  201. samplerate_select.SetCurSel(pos);
  202. for (n=0;n<tabsize(q_settings);n++)
  203. {
  204. quality_select.AddString(q_settings[n]);
  205. }
  206. quality_select.SetCurSel(q_setting);
  207. return TRUE;
  208. }
  209.  
  210. void OnQChange( UINT, int id, CWindow )
  211. {
  212. int new_srate = samplerate_select.GetCurSel();
  213. int q_level = quality_select.GetCurSel();
  214. dsp_preset_impl preset;
  215. dsp_resample_speex::make_preset( q_level,samplerates[new_srate], preset );
  216. m_callback.on_preset_changed( preset );
  217. }
  218.  
  219. void OnSampleRateChange( UINT, int id, CWindow )
  220. {
  221. int new_srate = samplerate_select.GetCurSel();
  222. int q_level = quality_select.GetCurSel();
  223. dsp_preset_impl preset;
  224. dsp_resample_speex::make_preset( q_level,samplerates[new_srate], preset );
  225. m_callback.on_preset_changed( preset );
  226. }
  227.  
  228. void OnButton( UINT, int id, CWindow )
  229. {
  230. EndDialog( id );
  231. }
  232. const dsp_preset & m_initData; // modal dialog so we can reference this caller-owned object.
  233. dsp_preset_edit_callback & m_callback;
  234. CComboBox samplerate_select, quality_select;
  235. };
  236. static void RunDSPConfigPopup( const dsp_preset & p_data, HWND p_parent, dsp_preset_edit_callback & p_callback )
  237. {
  238. CMyDSPPopupResample popup( p_data, p_callback );
  239. if ( popup.DoModal(p_parent) != IDOK ) p_callback.on_preset_changed( p_data );
  240. }
  241.  
  242.  
  243. //static service_factory_t<dsp_resample_speex_entry> foo_dsp_speex;
  244. static dsp_factory_t<dsp_resample_speex> foo_dsp_speexresample;
Add Comment
Please, Sign In to add comment