SampleGenerator.h 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /*
  2. * SampleGenerator.h
  3. * -----------------
  4. * Purpose: Generate samples from math formulas using muParser
  5. * Notes : (currently none)
  6. * Authors: OpenMPT Devs
  7. * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
  8. */
  9. #pragma once
  10. #include "openmpt/all/BuildSettings.hpp"
  11. #ifdef MPT_DISABLED_CODE
  12. #include "Mptrack.h"
  13. #include "Mainfrm.h"
  14. #include "Sndfile.h"
  15. #include "../muParser/include/muParser.h"
  16. // sample length
  17. #define SMPGEN_MINLENGTH 1
  18. #define SMPGEN_MAXLENGTH MAX_SAMPLE_LENGTH
  19. // sample frequency
  20. #define SMPGEN_MINFREQ 1
  21. #define SMPGEN_MAXFREQ 96000 // MAX_SAMPLE_RATE
  22. // 16-bit sample quality - when changing this, also change CSampleGenerator::sampling_type and 16-bit flags in SampleGenerator.cpp!
  23. #define SMPGEN_MIXBYTES 2
  24. enum smpgen_clip_methods
  25. {
  26. smpgen_clip,
  27. smpgen_overflow,
  28. smpgen_normalize,
  29. };
  30. class CSampleGenerator
  31. {
  32. protected:
  33. // sample parameters
  34. static int sample_frequency;
  35. static int sample_length;
  36. static mu::string_type expression;
  37. static smpgen_clip_methods sample_clipping;
  38. // rendering helper variables (they're here for the callback functions)
  39. static mu::value_type *sample_buffer;
  40. static size_t samples_written;
  41. typedef int16 sampling_type; // has to match SMPGEN_MIXBYTES!
  42. static constexpr sampling_type sample_maxvalue = (1 << ((SMPGEN_MIXBYTES << 3) - 1)) - 1;
  43. // muParser object for parsing the expression
  44. mu::Parser muParser;
  45. // Rendering callback functions
  46. // functions
  47. static mu::value_type ClipCallback(mu::value_type val, mu::value_type min, mu::value_type max) { return Clamp(val, min, max); };
  48. static mu::value_type PWMCallback(mu::value_type pos, mu::value_type duty, mu::value_type width) { if(width == 0) return 0; else return (fmod(pos, width) < ((duty / 100) * width)) ? 1 : -1; };
  49. static mu::value_type RndCallback(mu::value_type v) { return v * std::rand() / (mu::value_type)(RAND_MAX + 1.0); };
  50. static mu::value_type SampleDataCallback(mu::value_type v);
  51. static mu::value_type TriangleCallback(mu::value_type pos, mu::value_type width) { if((int)width == 0) return 0; else return std::abs(((int)pos % (int)(width)) - width / 2) / (width / 4) - 1; };
  52. // binary operators
  53. static mu::value_type ModuloCallback(mu::value_type x, mu::value_type y) { if(y == 0) return 0; else return fmod(x , y); };
  54. void ShowError(mu::Parser::exception_type *e);
  55. public:
  56. bool ShowDialog();
  57. bool TestExpression();
  58. bool CanRenderSample() const;
  59. bool RenderSample(CSoundFile *pSndFile, SAMPLEINDEX nSample);
  60. CSampleGenerator();
  61. };
  62. //////////////////////////////////////////////////////////////////////////
  63. // Sample Generator Formula Preset implementation
  64. struct samplegen_expression
  65. {
  66. std::string description; // e.g. "Pulse"
  67. mu::string_type expression; // e.g. "pwm(x,y,z)" - empty if this is a sub menu
  68. };
  69. #define MAX_SAMPLEGEN_PRESETS 100
  70. class CSmpGenPresets
  71. {
  72. protected:
  73. vector<samplegen_expression> presets;
  74. public:
  75. bool AddPreset(samplegen_expression new_preset) { if(GetNumPresets() >= MAX_SAMPLEGEN_PRESETS) return false; presets.push_back(new_preset); return true;};
  76. bool RemovePreset(size_t which) { if(which < GetNumPresets()) { presets.erase(presets.begin() + which); return true; } else return false; };
  77. samplegen_expression *GetPreset(size_t which) { if(which < GetNumPresets()) return &presets[which]; else return nullptr; };
  78. size_t GetNumPresets() { return presets.size(); };
  79. void Clear() { presets.clear(); };
  80. CSmpGenPresets() { Clear(); }
  81. ~CSmpGenPresets() { Clear(); }
  82. };
  83. //////////////////////////////////////////////////////////////////////////
  84. // Sample Generator Dialog implementation
  85. class CSmpGenDialog: public CDialog
  86. {
  87. protected:
  88. // sample parameters
  89. int sample_frequency;
  90. int sample_length;
  91. double sample_seconds;
  92. mu::string_type expression;
  93. smpgen_clip_methods sample_clipping;
  94. // pressed "OK"?
  95. bool apply;
  96. // preset slots
  97. CSmpGenPresets presets;
  98. HFONT hButtonFont; // "Marlett" font for "dropdown" button
  99. void RecalcParameters(bool secondsChanged, bool forceRefresh = false);
  100. // function presets
  101. void CreateDefaultPresets();
  102. public:
  103. const int GetFrequency() { return sample_frequency; };
  104. const int GetLength() { return sample_length; };
  105. const smpgen_clip_methods GetClipping() { return sample_clipping; }
  106. const mu::string_type GetExpression() { return expression; };
  107. bool CanApply() { return apply; };
  108. CSmpGenDialog(int freq, int len, smpgen_clip_methods clipping, mu::string_type expr):CDialog(IDD_SAMPLE_GENERATOR, CMainFrame::GetMainFrame())
  109. {
  110. sample_frequency = freq;
  111. sample_length = len;
  112. sample_clipping = clipping;
  113. expression = expr;
  114. apply = false;
  115. }
  116. protected:
  117. virtual BOOL OnInitDialog();
  118. virtual void OnOK();
  119. virtual void OnCancel();
  120. afx_msg void OnSampleLengthChanged();
  121. afx_msg void OnSampleSecondsChanged();
  122. afx_msg void OnSampleFreqChanged();
  123. afx_msg void OnExpressionChanged();
  124. afx_msg void OnShowExpressions();
  125. afx_msg void OnShowPresets();
  126. afx_msg void OnInsertExpression(UINT nId);
  127. afx_msg void OnSelectPreset(UINT nId);
  128. //}}AFX_MSG
  129. DECLARE_MESSAGE_MAP()
  130. };
  131. //////////////////////////////////////////////////////////////////////////
  132. // Sample Generator Preset Dialog implementation
  133. class CSmpGenPresetDlg: public CDialog
  134. {
  135. protected:
  136. CSmpGenPresets *presets;
  137. size_t currentItem; // first item is actually 1!
  138. void RefreshList();
  139. public:
  140. CSmpGenPresetDlg(CSmpGenPresets *pPresets):CDialog(IDD_SAMPLE_GENERATOR_PRESETS, CMainFrame::GetMainFrame())
  141. {
  142. presets = pPresets;
  143. currentItem = 0;
  144. }
  145. protected:
  146. virtual BOOL OnInitDialog();
  147. virtual void OnOK();
  148. afx_msg void OnListSelChange();
  149. afx_msg void OnTextChanged();
  150. afx_msg void OnExpressionChanged();
  151. afx_msg void OnAddPreset();
  152. afx_msg void OnRemovePreset();
  153. DECLARE_MESSAGE_MAP()
  154. };
  155. #endif // MPT_DISABLED_CODE