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.

79 lines
1.5KB

  1. #pragma once
  2. #include <random>
  3. #include "base.hpp"
  4. namespace frozenwasteland {
  5. namespace dsp {
  6. class Seeds {
  7. private:
  8. std::mt19937 _generator;
  9. Seeds();
  10. unsigned int _next();
  11. public:
  12. Seeds(const Seeds&) = delete;
  13. void operator=(const Seeds&) = delete;
  14. static Seeds& getInstance();
  15. static unsigned int next();
  16. };
  17. struct NoiseGenerator : Generator {
  18. std::minstd_rand _generator; // one of the faster options.
  19. NoiseGenerator() : _generator(Seeds::next()) {}
  20. };
  21. struct WhiteNoiseGenerator : NoiseGenerator {
  22. std::uniform_real_distribution<float> _uniform;
  23. WhiteNoiseGenerator() : _uniform(-1.0, 1.0) {}
  24. virtual float _next() override {
  25. return _uniform(_generator);
  26. }
  27. };
  28. template<typename G>
  29. struct BasePinkNoiseGenerator : NoiseGenerator {
  30. static const int _n = 7;
  31. G _g;
  32. G _gs[_n];
  33. uint32_t _count = _g.next();
  34. virtual float _next() override {
  35. // See: http://www.firstpr.com.au/dsp/pink-noise/
  36. float sum = _g.next();
  37. for (int i = 0, bit = 1; i < _n; ++i, bit <<= 1) {
  38. if (_count & bit) {
  39. sum += _gs[i].next();
  40. }
  41. else {
  42. sum += _gs[i].current();
  43. }
  44. }
  45. ++_count;
  46. return sum / (float)(_n + 1);
  47. }
  48. };
  49. struct PinkNoiseGenerator : BasePinkNoiseGenerator<WhiteNoiseGenerator> {};
  50. struct RedNoiseGenerator : BasePinkNoiseGenerator<PinkNoiseGenerator> {};
  51. struct GaussianNoiseGenerator : NoiseGenerator {
  52. std::normal_distribution<float> _normal;
  53. GaussianNoiseGenerator() : _normal(0, 1.0) {}
  54. virtual float _next() override {
  55. return _normal(_generator);
  56. }
  57. };
  58. } // namespace dsp
  59. } // namespace frozenwasteland