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.

267 lines
6.8KB

  1. // Copyright 2011 Olivier Gillet.
  2. //
  3. // Author: Olivier Gillet (ol.gillet@gmail.com)
  4. //
  5. // This program is free software: you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation, either version 3 of the License, or
  8. // (at your option) any later version.
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. // You should have received a copy of the GNU General Public License
  14. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. //
  16. // -----------------------------------------------------------------------------
  17. //
  18. // Pattern generator.
  19. //
  20. // OUTPUT MODE OUTPUT CLOCK BIT7 BIT6 BIT5 BIT4 BIT3 BIT2 BIT1 BIT0
  21. // DRUMS FALSE RND CLK HHAC SDAC BDAC HH SD BD
  22. // DRUMS TRUE RND CLK CLK BAR ACC HH SD BD
  23. // EUCLIDEAN FALSE RND CLK RST3 RST2 RST1 EUC3 EUC2 EUC1
  24. // EUCLIDEAN TRUE RND CLK CLK STEP RST EUC3 EUC2 EUC1
  25. #ifndef GRIDS_PATTERN_GENERATOR_H_
  26. #define GRIDS_PATTERN_GENERATOR_H_
  27. #include <string.h>
  28. #include "avrlib/base.h"
  29. #include "avrlib/random.h"
  30. #include "grids/hardware_config.h"
  31. namespace grids {
  32. const uint8_t kNumParts = 3;
  33. const uint8_t kPulsesPerStep = 3; // 24 ppqn ; 8 steps per quarter note.
  34. const uint8_t kStepsPerPattern = 32;
  35. const uint8_t kPulseDuration = 8; // 8 ticks of the main clock.
  36. struct DrumsSettings {
  37. uint8_t x;
  38. uint8_t y;
  39. uint8_t randomness;
  40. };
  41. struct PatternGeneratorSettings {
  42. union Options {
  43. DrumsSettings drums;
  44. uint8_t euclidean_length[kNumParts];
  45. } options;
  46. uint8_t density[kNumParts];
  47. };
  48. enum OutputMode {
  49. OUTPUT_MODE_EUCLIDEAN,
  50. OUTPUT_MODE_DRUMS
  51. };
  52. enum ClockResolution {
  53. CLOCK_RESOLUTION_4_PPQN,
  54. CLOCK_RESOLUTION_8_PPQN,
  55. CLOCK_RESOLUTION_24_PPQN,
  56. CLOCK_RESOLUTION_LAST
  57. };
  58. enum OutputBits {
  59. OUTPUT_BIT_COMMON = 0x08,
  60. OUTPUT_BIT_CLOCK = 0x10,
  61. OUTPUT_BIT_RESET = 0x20
  62. };
  63. struct Options {
  64. ClockResolution clock_resolution;
  65. OutputMode output_mode;
  66. bool output_clock;
  67. bool tap_tempo;
  68. bool gate_mode;
  69. bool swing;
  70. uint8_t pack() const {
  71. uint8_t byte = clock_resolution;
  72. if (!swing) {
  73. byte |= 0x08;
  74. }
  75. if (tap_tempo) {
  76. byte |= 0x10;
  77. }
  78. if (output_clock) {
  79. byte |= 0x20;
  80. }
  81. if (output_mode == OUTPUT_MODE_DRUMS) {
  82. byte |= 0x40;
  83. }
  84. if (!gate_mode) {
  85. byte |= 0x80;
  86. }
  87. return byte;
  88. }
  89. void unpack(uint8_t byte) {
  90. tap_tempo = byte & 0x10;
  91. output_clock = byte & 0x20;
  92. output_mode = byte & 0x40 ? OUTPUT_MODE_DRUMS : OUTPUT_MODE_EUCLIDEAN;
  93. gate_mode = !(byte & 0x80);
  94. swing = !(byte & 0x08);
  95. clock_resolution = static_cast<ClockResolution>(byte & 0x7);
  96. if (clock_resolution >= CLOCK_RESOLUTION_24_PPQN) {
  97. clock_resolution = CLOCK_RESOLUTION_24_PPQN;
  98. }
  99. }
  100. };
  101. class PatternGenerator {
  102. public:
  103. PatternGenerator() { }
  104. ~PatternGenerator() { }
  105. static inline void Init() {
  106. LoadSettings();
  107. Reset();
  108. }
  109. static inline void Reset() {
  110. step_ = 0;
  111. pulse_ = 0;
  112. memset(euclidean_step_, 0, sizeof(euclidean_step_));
  113. }
  114. static inline void Retrigger() {
  115. Evaluate();
  116. }
  117. static inline void TickClock(uint8_t num_pulses) {
  118. Evaluate();
  119. beat_ = (step_ & 0x7) == 0;
  120. first_beat_ = step_ == 0;
  121. pulse_ += num_pulses;
  122. // Wrap into ppqn steps.
  123. while (pulse_ >= kPulsesPerStep) {
  124. pulse_ -= kPulsesPerStep;
  125. if (!(step_ & 1)) {
  126. for (uint8_t i = 0; i < kNumParts; ++i) {
  127. ++euclidean_step_[i];
  128. }
  129. }
  130. ++step_;
  131. }
  132. // Wrap into step sequence steps.
  133. if (step_ >= kStepsPerPattern) {
  134. step_ -= kStepsPerPattern;
  135. }
  136. }
  137. static inline uint8_t state() {
  138. return state_;
  139. }
  140. static inline uint8_t step() { return step_; }
  141. static inline bool swing() { return options_.swing; }
  142. static int8_t swing_amount();
  143. static inline bool output_clock() { return options_.output_clock; }
  144. static inline bool tap_tempo() { return options_.tap_tempo; }
  145. static inline bool gate_mode() { return options_.gate_mode; }
  146. static inline OutputMode output_mode() { return options_.output_mode; }
  147. static inline ClockResolution clock_resolution() { return options_.clock_resolution; }
  148. static void set_swing(uint8_t value) { options_.swing = value; }
  149. static void set_output_clock(uint8_t value) { options_.output_clock = value; }
  150. static void set_tap_tempo(uint8_t value) { options_.tap_tempo = value; }
  151. static void set_output_mode(uint8_t value) {
  152. options_.output_mode = static_cast<OutputMode>(value);
  153. }
  154. static void set_clock_resolution(uint8_t value) {
  155. if (value >= CLOCK_RESOLUTION_24_PPQN) {
  156. value = CLOCK_RESOLUTION_24_PPQN;
  157. }
  158. options_.clock_resolution = static_cast<ClockResolution>(value);
  159. }
  160. static void set_gate_mode(bool gate_mode) {
  161. options_.gate_mode = gate_mode;
  162. }
  163. static inline void IncrementPulseCounter() {
  164. ++pulse_duration_counter_;
  165. // Zero all pulses after 1ms.
  166. if (pulse_duration_counter_ >= kPulseDuration && !options_.gate_mode) {
  167. state_ = 0;
  168. // Possible mod: the extra random pulse is not reset, and its behaviour
  169. // is more similar to that of a S&H.
  170. //state_ &= 0x80;
  171. }
  172. }
  173. static inline void ClockFallingEdge() {
  174. if (options_.gate_mode) {
  175. state_ = 0;
  176. }
  177. }
  178. static inline PatternGeneratorSettings* mutable_settings() {
  179. return &settings_;
  180. }
  181. static bool on_first_beat() { return first_beat_; }
  182. static bool on_beat() { return beat_; }
  183. static bool factory_testing() { return factory_testing_ < 5; }
  184. static void SaveSettings();
  185. static inline uint8_t led_pattern() {
  186. uint8_t result = 0;
  187. if (state_ & 1) {
  188. result |= LED_BD;
  189. }
  190. if (state_ & 2) {
  191. result |= LED_SD;
  192. }
  193. if (state_ & 4) {
  194. result |= LED_HH;
  195. }
  196. return result;
  197. }
  198. private:
  199. static void LoadSettings();
  200. static void Evaluate();
  201. static void EvaluateEuclidean();
  202. static void EvaluateDrums();
  203. static uint8_t ReadDrumMap(
  204. uint8_t step,
  205. uint8_t instrument,
  206. uint8_t x,
  207. uint8_t y);
  208. static Options options_;
  209. static uint8_t pulse_;
  210. static uint8_t step_;
  211. static uint8_t euclidean_step_[kNumParts];
  212. static bool first_beat_;
  213. static bool beat_;
  214. static uint8_t state_;
  215. static uint8_t part_perturbation_[kNumParts];
  216. static uint8_t pulse_duration_counter_;
  217. static uint8_t factory_testing_;
  218. static PatternGeneratorSettings settings_;
  219. DISALLOW_COPY_AND_ASSIGN(PatternGenerator);
  220. };
  221. extern PatternGenerator pattern_generator;
  222. } // namespace grids
  223. #endif // GRIDS_PATTERN_GENERATOR_H_