Music.h 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. /*
  2. * Copyright (c) 2021, kleines Filmröllchen <filmroellchen@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/FixedArray.h>
  8. #include <AK/HashMap.h>
  9. #include <AK/Noncopyable.h>
  10. #include <AK/Types.h>
  11. #include <AK/Variant.h>
  12. #include <AK/Vector.h>
  13. #include <LibAudio/Sample.h>
  14. #include <LibDSP/Envelope.h>
  15. namespace DSP {
  16. using Sample = Audio::Sample;
  17. constexpr Sample const SAMPLE_OFF = { 0.0, 0.0 };
  18. struct RollNote {
  19. constexpr u32 length() const { return (off_sample - on_sample) + 1; }
  20. u32 on_sample;
  21. u32 off_sample;
  22. u8 pitch;
  23. i8 velocity;
  24. constexpr Envelope to_envelope(u32 time, u32 attack_samples, u32 decay_samples, u32 release_samples) const
  25. {
  26. i64 time_since_end = static_cast<i64>(time) - static_cast<i64>(off_sample);
  27. // We're before the end of this note.
  28. if (time_since_end < 0) {
  29. i64 time_since_start = static_cast<i64>(time) - static_cast<i64>(on_sample);
  30. if (time_since_start < 0)
  31. return {};
  32. if (time_since_start < attack_samples) {
  33. if (attack_samples == 0)
  34. return Envelope::from_attack(0);
  35. return Envelope::from_attack(static_cast<double>(time_since_start) / static_cast<double>(attack_samples));
  36. }
  37. if (time_since_start < attack_samples + decay_samples) {
  38. if (decay_samples == 0)
  39. return Envelope::from_decay(0);
  40. return Envelope::from_decay(static_cast<double>(time_since_start - attack_samples) / static_cast<double>(decay_samples));
  41. }
  42. // This is a note-dependent value!
  43. u32 sustain_samples = length() - attack_samples - decay_samples;
  44. return Envelope::from_sustain(static_cast<double>(time_since_start - attack_samples - decay_samples) / static_cast<double>(sustain_samples));
  45. }
  46. // Overshot the release time
  47. if (time_since_end > release_samples)
  48. return {};
  49. return Envelope::from_release(static_cast<double>(time_since_end) / static_cast<double>(release_samples));
  50. }
  51. constexpr bool is_playing(u32 time) const { return on_sample <= time && time <= off_sample; }
  52. constexpr bool is_playing_during(u32 start_time, u32 end_time) const
  53. {
  54. // There are three scenarios for a playing note.
  55. return
  56. // 1. The note ends within our time frame.
  57. (this->off_sample >= start_time && this->off_sample < end_time)
  58. // 2. The note starts within our time frame.
  59. || (this->on_sample >= start_time && this->on_sample < end_time)
  60. // 3. The note starts before our time frame and ends after it.
  61. || (this->on_sample < start_time && this->off_sample >= end_time);
  62. }
  63. constexpr bool overlaps_with(RollNote const& other) const
  64. {
  65. // Notes don't overlap if one is completely before or behind the other.
  66. return !((this->on_sample < other.on_sample && this->off_sample < other.on_sample)
  67. || (this->on_sample >= other.off_sample && this->off_sample >= other.off_sample));
  68. }
  69. };
  70. enum class SignalType : u8 {
  71. Invalid,
  72. Sample,
  73. Note
  74. };
  75. // Perfect hashing for note (MIDI) values. This just uses the note value as the hash itself.
  76. class PerfectNoteHashTraits : Traits<u8> {
  77. public:
  78. static constexpr bool equals(u8 const& a, u8 const& b) { return a == b; }
  79. static constexpr unsigned hash(u8 value)
  80. {
  81. return static_cast<unsigned>(value);
  82. }
  83. };
  84. // Equal temperament, A = 440Hz
  85. // We calculate note frequencies relative to A4:
  86. // 440.0 * pow(pow(2.0, 1.0 / 12.0), N)
  87. // Where N is the note distance from A.
  88. constexpr Array<double, 84> note_frequencies = {
  89. // Octave 1
  90. 32.703195662574764,
  91. 34.647828872108946,
  92. 36.708095989675876,
  93. 38.890872965260044,
  94. 41.203444614108669,
  95. 43.653528929125407,
  96. 46.249302838954222,
  97. 48.99942949771858,
  98. 51.913087197493056,
  99. 54.999999999999915,
  100. 58.270470189761156,
  101. 61.735412657015416,
  102. // Octave 2
  103. 65.406391325149571,
  104. 69.295657744217934,
  105. 73.416191979351794,
  106. 77.781745930520117,
  107. 82.406889228217381,
  108. 87.307057858250872,
  109. 92.4986056779085,
  110. 97.998858995437217,
  111. 103.82617439498618,
  112. 109.99999999999989,
  113. 116.54094037952237,
  114. 123.4708253140309,
  115. // Octave 3
  116. 130.8127826502992,
  117. 138.59131548843592,
  118. 146.83238395870364,
  119. 155.56349186104035,
  120. 164.81377845643485,
  121. 174.61411571650183,
  122. 184.99721135581709,
  123. 195.99771799087452,
  124. 207.65234878997245,
  125. 219.99999999999989,
  126. 233.08188075904488,
  127. 246.94165062806198,
  128. // Octave 4
  129. 261.62556530059851,
  130. 277.18263097687202,
  131. 293.66476791740746,
  132. 311.12698372208081,
  133. 329.62755691286986,
  134. 349.22823143300383,
  135. 369.99442271163434,
  136. 391.99543598174927,
  137. 415.30469757994513,
  138. 440,
  139. 466.16376151808993,
  140. 493.88330125612413,
  141. // Octave 5
  142. 523.25113060119736,
  143. 554.36526195374427,
  144. 587.32953583481526,
  145. 622.25396744416196,
  146. 659.25511382574007,
  147. 698.456462866008,
  148. 739.98884542326903,
  149. 783.99087196349899,
  150. 830.60939515989071,
  151. 880.00000000000034,
  152. 932.32752303618031,
  153. 987.76660251224882,
  154. // Octave 6
  155. 1046.5022612023952,
  156. 1108.7305239074892,
  157. 1174.659071669631,
  158. 1244.5079348883246,
  159. 1318.5102276514808,
  160. 1396.9129257320169,
  161. 1479.977690846539,
  162. 1567.9817439269987,
  163. 1661.2187903197821,
  164. 1760.000000000002,
  165. 1864.6550460723618,
  166. 1975.5332050244986,
  167. // Octave 7
  168. 2093.0045224047913,
  169. 2217.4610478149793,
  170. 2349.3181433392633,
  171. 2489.0158697766506,
  172. 2637.020455302963,
  173. 2793.8258514640347,
  174. 2959.9553816930793,
  175. 3135.9634878539991,
  176. 3322.437580639566,
  177. 3520.0000000000055,
  178. 3729.3100921447249,
  179. 3951.0664100489994,
  180. };
  181. using RollNotes = Array<Optional<RollNote>, note_frequencies.size()>;
  182. constexpr size_t const notes_per_octave = 12;
  183. constexpr double const middle_c = note_frequencies[36];
  184. struct Signal : public Variant<FixedArray<Sample>, RollNotes> {
  185. using Variant::Variant;
  186. AK_MAKE_NONCOPYABLE(Signal);
  187. AK_MAKE_DEFAULT_MOVABLE(Signal);
  188. public:
  189. ALWAYS_INLINE SignalType type() const
  190. {
  191. if (has<FixedArray<Sample>>())
  192. return SignalType::Sample;
  193. if (has<RollNotes>())
  194. return SignalType::Note;
  195. return SignalType::Invalid;
  196. }
  197. };
  198. }