You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

377 lines
9.6KB

  1. // Copyright 2012 Olivier Gillet.
  2. //
  3. // Author: Olivier Gillet (ol.gillet@gmail.com)
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. //
  23. // See http://creativecommons.org/licenses/MIT/ for more information.
  24. //
  25. // -----------------------------------------------------------------------------
  26. //
  27. // Settings
  28. #ifndef BRAIDS_SETTINGS_H_
  29. #define BRAIDS_SETTINGS_H_
  30. #include "stmlib/stmlib.h"
  31. namespace braids {
  32. enum MacroOscillatorShape {
  33. MACRO_OSC_SHAPE_CSAW,
  34. MACRO_OSC_SHAPE_MORPH,
  35. MACRO_OSC_SHAPE_SAW_SQUARE,
  36. MACRO_OSC_SHAPE_SINE_TRIANGLE,
  37. MACRO_OSC_SHAPE_BUZZ,
  38. MACRO_OSC_SHAPE_SQUARE_SUB,
  39. MACRO_OSC_SHAPE_SAW_SUB,
  40. MACRO_OSC_SHAPE_SQUARE_SYNC,
  41. MACRO_OSC_SHAPE_SAW_SYNC,
  42. MACRO_OSC_SHAPE_TRIPLE_SAW,
  43. MACRO_OSC_SHAPE_TRIPLE_SQUARE,
  44. MACRO_OSC_SHAPE_TRIPLE_TRIANGLE,
  45. MACRO_OSC_SHAPE_TRIPLE_SINE,
  46. MACRO_OSC_SHAPE_TRIPLE_RING_MOD,
  47. MACRO_OSC_SHAPE_SAW_SWARM,
  48. MACRO_OSC_SHAPE_SAW_COMB,
  49. MACRO_OSC_SHAPE_TOY,
  50. MACRO_OSC_SHAPE_DIGITAL_FILTER_LP,
  51. MACRO_OSC_SHAPE_DIGITAL_FILTER_PK,
  52. MACRO_OSC_SHAPE_DIGITAL_FILTER_BP,
  53. MACRO_OSC_SHAPE_DIGITAL_FILTER_HP,
  54. MACRO_OSC_SHAPE_VOSIM,
  55. MACRO_OSC_SHAPE_VOWEL,
  56. MACRO_OSC_SHAPE_VOWEL_FOF,
  57. MACRO_OSC_SHAPE_HARMONICS,
  58. MACRO_OSC_SHAPE_FM,
  59. MACRO_OSC_SHAPE_FEEDBACK_FM,
  60. MACRO_OSC_SHAPE_CHAOTIC_FEEDBACK_FM,
  61. MACRO_OSC_SHAPE_PLUCKED,
  62. MACRO_OSC_SHAPE_BOWED,
  63. MACRO_OSC_SHAPE_BLOWN,
  64. MACRO_OSC_SHAPE_FLUTED,
  65. MACRO_OSC_SHAPE_STRUCK_BELL,
  66. MACRO_OSC_SHAPE_STRUCK_DRUM,
  67. MACRO_OSC_SHAPE_KICK,
  68. MACRO_OSC_SHAPE_CYMBAL,
  69. MACRO_OSC_SHAPE_SNARE,
  70. MACRO_OSC_SHAPE_WAVETABLES,
  71. MACRO_OSC_SHAPE_WAVE_MAP,
  72. MACRO_OSC_SHAPE_WAVE_LINE,
  73. MACRO_OSC_SHAPE_WAVE_PARAPHONIC,
  74. MACRO_OSC_SHAPE_FILTERED_NOISE,
  75. MACRO_OSC_SHAPE_TWIN_PEAKS_NOISE,
  76. MACRO_OSC_SHAPE_CLOCKED_NOISE,
  77. MACRO_OSC_SHAPE_GRANULAR_CLOUD,
  78. MACRO_OSC_SHAPE_PARTICLE_NOISE,
  79. MACRO_OSC_SHAPE_DIGITAL_MODULATION,
  80. MACRO_OSC_SHAPE_QUESTION_MARK,
  81. // MACRO_OSC_SHAPE_YOUR_ALGO
  82. MACRO_OSC_SHAPE_LAST,
  83. MACRO_OSC_SHAPE_LAST_ACCESSIBLE_FROM_META = MACRO_OSC_SHAPE_DIGITAL_MODULATION
  84. };
  85. enum Resolution {
  86. RESOLUTION_2_BIT,
  87. RESOLUTION_3_BIT,
  88. RESOLUTION_4_BIT,
  89. RESOLUTION_6_BIT,
  90. RESOLUTION_8_BIT,
  91. RESOLUTION_12_BIT,
  92. RESOLUTION_16_BIT,
  93. RESOLUTION_LAST
  94. };
  95. enum SampleRate {
  96. SAMPLE_RATE_4K,
  97. SAMPLE_RATE_8K,
  98. SAMPLE_RATE_16K,
  99. SAMPLE_RATE_24k,
  100. SAMPLE_RATE_32k,
  101. SAMPLE_RATE_48K,
  102. SAMPLE_RATE_96K,
  103. SAMPLE_RATE_LAST
  104. };
  105. enum PitchRange {
  106. PITCH_RANGE_EXTERNAL,
  107. PITCH_RANGE_FREE,
  108. PITCH_RANGE_EXTENDED,
  109. PITCH_RANGE_440,
  110. PITCH_RANGE_LFO // This setting is hidden by default!
  111. };
  112. enum Setting {
  113. SETTING_OSCILLATOR_SHAPE,
  114. SETTING_RESOLUTION,
  115. SETTING_SAMPLE_RATE,
  116. SETTING_AD_TIMBRE,
  117. SETTING_TRIG_SOURCE,
  118. SETTING_TRIG_DELAY,
  119. SETTING_META_MODULATION,
  120. SETTING_PITCH_RANGE,
  121. SETTING_PITCH_OCTAVE,
  122. SETTING_QUANTIZER_SCALE,
  123. SETTING_VCO_FLATTEN,
  124. SETTING_VCO_DRIFT,
  125. SETTING_SIGNATURE,
  126. SETTING_BRIGHTNESS,
  127. SETTING_AD_ATTACK,
  128. SETTING_AD_DECAY,
  129. SETTING_AD_FM,
  130. SETTING_AD_COLOR,
  131. SETTING_AD_VCA,
  132. SETTING_QUANTIZER_ROOT,
  133. SETTING_LAST_EDITABLE_SETTING = SETTING_QUANTIZER_ROOT,
  134. // Not settings per-se, but used for menu display!
  135. SETTING_CALIBRATION,
  136. SETTING_CV_TESTER,
  137. SETTING_MARQUEE,
  138. SETTING_VERSION,
  139. SETTING_LAST
  140. };
  141. struct SettingsData {
  142. uint8_t shape;
  143. uint8_t resolution;
  144. uint8_t sample_rate;
  145. uint8_t ad_timbre;
  146. uint8_t auto_trig;
  147. uint8_t trig_delay;
  148. uint8_t meta_modulation;
  149. uint8_t pitch_range;
  150. uint8_t pitch_octave;
  151. uint8_t quantizer_scale;
  152. uint8_t vco_flatten;
  153. uint8_t vco_drift;
  154. uint8_t signature;
  155. uint8_t brightness;
  156. uint8_t ad_attack;
  157. uint8_t ad_decay;
  158. uint8_t ad_fm;
  159. uint8_t ad_color;
  160. uint8_t ad_vca;
  161. uint8_t quantizer_root;
  162. int32_t pitch_cv_offset;
  163. int32_t pitch_cv_scale;
  164. int32_t fm_cv_offset;
  165. int16_t parameter_cv_offset[2];
  166. uint16_t parameter_cv_scale[2];
  167. char marquee_text[55];
  168. char magic_byte;
  169. };
  170. struct SettingMetadata {
  171. uint8_t min_value;
  172. uint8_t max_value;
  173. const char name[5];
  174. const char* const* strings;
  175. int16_t Clip(int16_t value) const {
  176. if (value > max_value) {
  177. value = max_value;
  178. } else if (value < min_value) {
  179. value = min_value;
  180. }
  181. return value;
  182. }
  183. };
  184. class Settings {
  185. public:
  186. Settings() { }
  187. ~Settings() { }
  188. void Init();
  189. void Save();
  190. void Reset();
  191. void SetValue(Setting setting, uint8_t value) {
  192. uint8_t* data = static_cast<uint8_t*>(static_cast<void*>(&data_));
  193. data[setting] = value;
  194. }
  195. uint8_t GetValue(Setting setting) const {
  196. const uint8_t* data = static_cast<const uint8_t*>(
  197. static_cast<const void*>(&data_));
  198. return data[setting];
  199. }
  200. inline MacroOscillatorShape shape() const {
  201. return static_cast<MacroOscillatorShape>(data_.shape);
  202. }
  203. inline Resolution resolution() const {
  204. return static_cast<Resolution>(data_.resolution);
  205. }
  206. inline SampleRate sample_rate() const {
  207. return static_cast<SampleRate>(data_.sample_rate);
  208. }
  209. inline bool vco_flatten() const {
  210. return data_.vco_flatten;
  211. }
  212. inline uint8_t vco_drift() const {
  213. return data_.vco_drift;
  214. }
  215. inline uint8_t signature() const {
  216. return data_.signature;
  217. }
  218. inline bool meta_modulation() const {
  219. return data_.meta_modulation;
  220. }
  221. inline uint8_t trig_delay() const {
  222. return data_.trig_delay;
  223. }
  224. inline int32_t quantizer_root() const {
  225. return data_.quantizer_root;
  226. }
  227. inline const char* marquee_text() const {
  228. return data_.marquee_text;
  229. }
  230. inline char* mutable_marquee_text() {
  231. return data_.marquee_text;
  232. }
  233. inline const SettingsData& data() const { return data_; }
  234. inline SettingsData* mutable_data() { return &data_; }
  235. void Calibrate(
  236. int32_t adc_code_c2,
  237. int32_t adc_code_c4,
  238. int32_t adc_code_fm,
  239. int32_t adc_code_p0_min,
  240. int32_t adc_code_p0_max,
  241. int32_t adc_code_p1_min,
  242. int32_t adc_code_p1_max) {
  243. if (adc_code_c4 != adc_code_c2) {
  244. int32_t scale = (24 * 128 * 4096L) / (adc_code_c4 - adc_code_c2);
  245. data_.pitch_cv_scale = scale;
  246. data_.pitch_cv_offset = (60 << 7) -
  247. (scale * ((adc_code_c2 + adc_code_c4) >> 1) >> 12);
  248. data_.fm_cv_offset = adc_code_fm;
  249. }
  250. // int32_t min_code[2] = { adc_code_p0_min, adc_code_p1_min };
  251. // int32_t max_code[2] = { adc_code_p0_max, adc_code_p1_max };
  252. //
  253. // for (int i = 0; i < 2; ++i) {
  254. // int32_t d = max_code[i] - min_code[i];
  255. // if (d > 3700) {
  256. // int32_t scale = (32768 * 4106) / d;
  257. // int32_t offset = -(min_code[i] * scale >> 12) - 40;
  258. // data_.parameter_cv_offset[i] = offset;
  259. // data_.parameter_cv_scale[i] = scale;
  260. // }
  261. // }
  262. Save();
  263. }
  264. inline int32_t adc_to_pitch(int32_t pitch_adc_code) const {
  265. if (data_.pitch_range == PITCH_RANGE_EXTERNAL ||
  266. data_.pitch_range == PITCH_RANGE_LFO) {
  267. pitch_adc_code = pitch_adc_code * data_.pitch_cv_scale >> 12;
  268. pitch_adc_code += data_.pitch_cv_offset;
  269. } else if (data_.pitch_range == PITCH_RANGE_FREE) {
  270. pitch_adc_code = (pitch_adc_code - 1638);
  271. pitch_adc_code = pitch_adc_code * data_.pitch_cv_scale >> 12;
  272. pitch_adc_code += 60 << 7;
  273. } else if (data_.pitch_range == PITCH_RANGE_440) {
  274. pitch_adc_code = 69 << 7;
  275. } else {
  276. pitch_adc_code = (pitch_adc_code - 1638) * 9 >> 1;
  277. pitch_adc_code += 60 << 7;
  278. }
  279. return pitch_adc_code;
  280. }
  281. inline int32_t pitch_transposition() const {
  282. int32_t t = data_.pitch_range == PITCH_RANGE_LFO ? -36 << 7 : 0;
  283. t += (static_cast<int32_t>(data_.pitch_octave) - 2) * 12 * 128;
  284. return t;
  285. }
  286. inline int32_t adc_to_fm(int32_t fm_adc_code) const {
  287. fm_adc_code -= data_.fm_cv_offset;
  288. fm_adc_code = fm_adc_code * 7680 >> 12;
  289. if (data_.pitch_range == PITCH_RANGE_440) {
  290. fm_adc_code = 0;
  291. }
  292. return fm_adc_code;
  293. }
  294. inline int32_t adc_to_parameter(int index, int32_t adc_code) const {
  295. int32_t scale = static_cast<int32_t>(data_.parameter_cv_scale[index]);
  296. int32_t offset = static_cast<int32_t>(data_.parameter_cv_offset[index]);
  297. return (scale * adc_code >> 12) + offset;
  298. }
  299. inline bool paques() const {
  300. return paques_;
  301. }
  302. static const SettingMetadata& metadata(Setting setting) {
  303. return metadata_[setting];
  304. }
  305. static const Setting setting_at_index(int16_t index) {
  306. return settings_order_[index];
  307. }
  308. private:
  309. void CheckPaques();
  310. SettingsData data_;
  311. uint16_t version_token_;
  312. bool paques_;
  313. static const SettingMetadata metadata_[SETTING_LAST];
  314. static const Setting settings_order_[SETTING_LAST];
  315. DISALLOW_COPY_AND_ASSIGN(Settings);
  316. };
  317. extern Settings settings;
  318. } // namespace braids
  319. #endif // BRAIDS_SETTINGS_H_