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.

125 lines
4.0KB

  1. #!/usr/bin/python2.5
  2. #
  3. # Copyright 2015 Olivier Gillet.
  4. #
  5. # Author: Olivier Gillet (ol.gillet@gmail.com)
  6. #
  7. # Permission is hereby granted, free of charge, to any person obtaining a copy
  8. # of this software and associated documentation files (the "Software"), to deal
  9. # in the Software without restriction, including without limitation the rights
  10. # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. # copies of the Software, and to permit persons to whom the Software is
  12. # furnished to do so, subject to the following conditions:
  13. #
  14. # The above copyright notice and this permission notice shall be included in
  15. # all copies or substantial portions of the Software.
  16. #
  17. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23. # THE SOFTWARE.
  24. #
  25. # See http://creativecommons.org/licenses/MIT/ for more information.
  26. #
  27. # -----------------------------------------------------------------------------
  28. #
  29. # Lookup table definitions.
  30. import numpy
  31. lookup_tables = []
  32. int16_lookup_tables = []
  33. uint32_lookup_tables = []
  34. SAMPLE_RATE = 48000.0
  35. """----------------------------------------------------------------------------
  36. Sine table
  37. ----------------------------------------------------------------------------"""
  38. WAVETABLE_SIZE = 4096
  39. t = numpy.arange(0.0, WAVETABLE_SIZE + WAVETABLE_SIZE / 4 + 1) / WAVETABLE_SIZE
  40. x = numpy.sin(2 * numpy.pi * t)
  41. lookup_tables += [('sine', x)]
  42. """----------------------------------------------------------------------------
  43. Exponentials covering several decades in 256 steps, with safeguard
  44. ----------------------------------------------------------------------------"""
  45. x = numpy.arange(0, 257) / 256.0
  46. lookup_tables += [('4_decades', 10 ** (4 * x))]
  47. """----------------------------------------------------------------------------
  48. Delay compensation factor for SVF
  49. ----------------------------------------------------------------------------"""
  50. ratio = 2.0 ** (numpy.arange(0, 257) / 12.0)
  51. svf_shift = 2.0 * numpy.arctan(1.0 / ratio) / (2.0 * numpy.pi)
  52. lookup_tables += [('svf_shift', svf_shift)]
  53. """----------------------------------------------------------------------------
  54. Stiffness table.
  55. ----------------------------------------------------------------------------"""
  56. structure = numpy.arange(0, 257) / 256.0
  57. stiffness = structure + 0
  58. for i, g in enumerate(structure):
  59. if g < 0.25:
  60. g = 0.25 - g
  61. stiffness[i] = -g * 0.25
  62. elif g < 0.3:
  63. stiffness[i] = 0.0
  64. elif g < 0.9:
  65. g -= 0.3
  66. g /= 0.6
  67. stiffness[i] = 0.01 * 10 ** (g * 2.005) - 0.01
  68. else:
  69. g -= 0.9
  70. g /= 0.1
  71. g *= g
  72. stiffness[i] = 1.5 - numpy.cos(g * numpy.pi) / 2.0
  73. stiffness[-1] = 2.0
  74. stiffness[-2] = 2.0
  75. lookup_tables += [('stiffness', stiffness)]
  76. """----------------------------------------------------------------------------
  77. Quantizer for FM frequencies.
  78. ----------------------------------------------------------------------------"""
  79. fm_frequency_ratios = [ 0.5, 0.5 * 2 ** (16 / 1200.0),
  80. numpy.sqrt(2) / 2, numpy.pi / 4, 1.0, 1.0 * 2 ** (16 / 1200.0), numpy.sqrt(2),
  81. numpy.pi / 2, 7.0 / 4, 2, 2 * 2 ** (16 / 1200.0), 9.0 / 4, 11.0 / 4,
  82. 2 * numpy.sqrt(2), 3, numpy.pi, numpy.sqrt(3) * 2, 4, numpy.sqrt(2) * 3,
  83. numpy.pi * 3 / 2, 5, numpy.sqrt(2) * 4, 8]
  84. scale = []
  85. for ratio in fm_frequency_ratios:
  86. ratio = 12 * numpy.log2(ratio)
  87. scale.extend([ratio, ratio, ratio])
  88. target_size = int(2 ** numpy.ceil(numpy.log2(len(scale))))
  89. while len(scale) < target_size:
  90. gap = numpy.argmax(numpy.diff(scale))
  91. scale = scale[:gap + 1] + [(scale[gap] + scale[gap + 1]) / 2] + \
  92. scale[gap + 1:]
  93. scale.append(scale[-1])
  94. lookup_tables.append(
  95. ('fm_frequency_quantizer', scale)
  96. )