Music.h 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /*
  2. * Copyright (c) 2021, kleines Filmröllchen <malu.bertsch@gmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/HashMap.h>
  8. #include <AK/Types.h>
  9. #include <AK/Variant.h>
  10. #include <AK/Vector.h>
  11. #include <LibAudio/Buffer.h>
  12. namespace LibDSP {
  13. // FIXME: Audio::Frame is 64-bit float, which is quite large for long clips.
  14. using Sample = Audio::Sample;
  15. Sample const SAMPLE_OFF = { 0.0, 0.0 };
  16. struct RollNote {
  17. constexpr u32 length() const { return (off_sample - on_sample) + 1; }
  18. u32 on_sample;
  19. u32 off_sample;
  20. u8 pitch;
  21. i8 velocity;
  22. };
  23. enum class SignalType : u8 {
  24. Invalid,
  25. Sample,
  26. Note
  27. };
  28. using RollNotes = OrderedHashMap<u8, RollNote>;
  29. struct Signal : public Variant<Sample, RollNotes> {
  30. using Variant::Variant;
  31. ALWAYS_INLINE SignalType type() const
  32. {
  33. return has<Sample>() ? SignalType::Sample : has<RollNotes>() ? SignalType::Note
  34. : SignalType::Invalid;
  35. }
  36. };
  37. // Equal temperament, A = 440Hz
  38. // We calculate note frequencies relative to A4:
  39. // 440.0 * pow(pow(2.0, 1.0 / 12.0), N)
  40. // Where N is the note distance from A.
  41. constexpr double note_frequencies[] = {
  42. // Octave 1
  43. 32.703195662574764,
  44. 34.647828872108946,
  45. 36.708095989675876,
  46. 38.890872965260044,
  47. 41.203444614108669,
  48. 43.653528929125407,
  49. 46.249302838954222,
  50. 48.99942949771858,
  51. 51.913087197493056,
  52. 54.999999999999915,
  53. 58.270470189761156,
  54. 61.735412657015416,
  55. // Octave 2
  56. 65.406391325149571,
  57. 69.295657744217934,
  58. 73.416191979351794,
  59. 77.781745930520117,
  60. 82.406889228217381,
  61. 87.307057858250872,
  62. 92.4986056779085,
  63. 97.998858995437217,
  64. 103.82617439498618,
  65. 109.99999999999989,
  66. 116.54094037952237,
  67. 123.4708253140309,
  68. // Octave 3
  69. 130.8127826502992,
  70. 138.59131548843592,
  71. 146.83238395870364,
  72. 155.56349186104035,
  73. 164.81377845643485,
  74. 174.61411571650183,
  75. 184.99721135581709,
  76. 195.99771799087452,
  77. 207.65234878997245,
  78. 219.99999999999989,
  79. 233.08188075904488,
  80. 246.94165062806198,
  81. // Octave 4
  82. 261.62556530059851,
  83. 277.18263097687202,
  84. 293.66476791740746,
  85. 311.12698372208081,
  86. 329.62755691286986,
  87. 349.22823143300383,
  88. 369.99442271163434,
  89. 391.99543598174927,
  90. 415.30469757994513,
  91. 440,
  92. 466.16376151808993,
  93. 493.88330125612413,
  94. // Octave 5
  95. 523.25113060119736,
  96. 554.36526195374427,
  97. 587.32953583481526,
  98. 622.25396744416196,
  99. 659.25511382574007,
  100. 698.456462866008,
  101. 739.98884542326903,
  102. 783.99087196349899,
  103. 830.60939515989071,
  104. 880.00000000000034,
  105. 932.32752303618031,
  106. 987.76660251224882,
  107. // Octave 6
  108. 1046.5022612023952,
  109. 1108.7305239074892,
  110. 1174.659071669631,
  111. 1244.5079348883246,
  112. 1318.5102276514808,
  113. 1396.9129257320169,
  114. 1479.977690846539,
  115. 1567.9817439269987,
  116. 1661.2187903197821,
  117. 1760.000000000002,
  118. 1864.6550460723618,
  119. 1975.5332050244986,
  120. // Octave 7
  121. 2093.0045224047913,
  122. 2217.4610478149793,
  123. 2349.3181433392633,
  124. 2489.0158697766506,
  125. 2637.020455302963,
  126. 2793.8258514640347,
  127. 2959.9553816930793,
  128. 3135.9634878539991,
  129. 3322.437580639566,
  130. 3520.0000000000055,
  131. 3729.3100921447249,
  132. 3951.0664100489994,
  133. };
  134. constexpr size_t note_count = array_size(note_frequencies);
  135. constexpr double middle_c = note_frequencies[36];
  136. }