Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

freeverb.rb 6.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. # freeverb.rb -- CLM -> Snd/Ruby translation of freeverb.ins
  2. # Translator/Author: Michael Scholz <mi-scholz@users.sourceforge.net>
  3. # Created: 03/04/08 03:53:20
  4. # Changed: 14/11/13 15:47:00
  5. # Original notes of Fernando Lopez-Lezcano
  6. # ;; Freeverb - Free, studio-quality reverb SOURCE CODE in the public domain
  7. # ;;
  8. # ;; Written by Jezar at Dreampoint, June 2000
  9. # ;; http://www.dreampoint.co.uk
  10. # ;;
  11. # ;; Translated into clm-2 by Fernando Lopez-Lezcano <nando@ccrma.stanford.edu>
  12. # ;; Version 1.0 for clm-2 released in January 2001
  13. # ;; http://ccrma.stanford.edu/~nando/clm/freeverb/
  14. # ;;
  15. # ;; Changes to the original code by Jezar (by Fernando Lopez-Lezcano):
  16. # ;; - the clm version can now work with a mono input or an n-channel input
  17. # ;; stream (in the latter case the number of channels of the input and output
  18. # ;; streams must match.
  19. # ;; - the "wet" parameter has been eliminated as it does not apply to the model
  20. # ;; that clm uses to generate reverberation
  21. # ;; - the "width" parameter name has been changed to :global. It now controls
  22. # ;; the coefficients of an NxN matrix that specifies how the output of the
  23. # ;; reverbs is mixed into the output stream.
  24. # ;; - predelays for the input channels have been added.
  25. # ;; - damping can be controlled individually for each channel.
  26. # For more information see clm-x/freeverb.html.
  27. require "ws"
  28. # Snd-Ruby's freeverb and fcomb (see sndins.so for a faster one).
  29. unless provided? :sndins
  30. class Fcomb
  31. def initialize(scaler, size, a0, a1)
  32. @feedback = scaler.to_f
  33. @delay = make_delay(size.to_i)
  34. @filter = make_one_zero(a0, a1)
  35. end
  36. attr_accessor :feedback
  37. def fcomb(input = 0.0)
  38. delay(@delay, input + one_zero(@filter, tap(@delay)) * @feedback)
  39. end
  40. def inspect
  41. format("#<%s: %p, %p, feedback: %0.3f>",
  42. self.class, @delay, @filter, @feedback)
  43. end
  44. end
  45. def make_fcomb(scaler = 0.0, size = 1, a0 = 0.0, a1 = 0.0)
  46. Fcomb.new(scaler, size, a0, a1)
  47. end
  48. def fcomb(gen, input = 0.0)
  49. gen.fcomb(input)
  50. end
  51. def fcomb?(obj)
  52. obj.kind_of?(Fcomb)
  53. end
  54. end
  55. add_help(:freeverb,
  56. "freeverb(*args)
  57. :room_decay, 0.5,
  58. :damping, 0.5,
  59. :global, 0.3,
  60. :predelay, 0.03,
  61. :output_gain, 1.0,
  62. :output_mixer, nil,
  63. :scale_room_decay, 0.28,
  64. :offset_room_decay, 0.7,
  65. :combtuning, [1116, 1188, 1277, 1356, 1422, 1491, 1557, 1617],
  66. :allpasstuning, [556, 441, 341, 225],
  67. :scale_damping, 0.4,
  68. :stereo_spread, 23,
  69. with_sound(:reverb, :freeverb) do fm_violin(0, 1, 440, 0.3) end
  70. This is the Ruby version of freeverb. For a faster one see sndins.so.")
  71. def freeverb(*args)
  72. room_decay, damping, global, predelay, output_gain, output_mixer = nil
  73. scale_room_decay, offset_room_decay, combtuning, allpasstuning = nil
  74. scale_damping, stereo_spread = nil
  75. optkey(args, binding,
  76. [:room_decay, 0.5],
  77. [:damping, 0.5],
  78. [:global, 0.3],
  79. [:predelay, 0.03],
  80. [:output_gain, 1.0],
  81. [:output_mixer, nil],
  82. [:scale_room_decay, 0.28],
  83. [:offset_room_decay, 0.7],
  84. [:combtuning, [1116, 1188, 1277, 1356, 1422, 1491, 1557, 1617]],
  85. [:allpasstuning, [556, 441, 341, 225]],
  86. [:scale_damping, 0.4],
  87. [:stereo_spread, 23])
  88. if @reverb_channels > 1 and @reverb_channels != @channels
  89. error("input must be mono or input channels must equal output channels")
  90. end
  91. out_gain = output_gain
  92. local_gain = (1.0 - global) * (1.0 - 1.0 / @channels) + 1.0 / @channels
  93. global_gain = (@channels - local_gain * @channels) /
  94. [(@channels * @channels - @channels), 1].max
  95. srate_scale = @srate / 44100.0
  96. out_mix = output_mixer
  97. unless vct?(output_mixer)
  98. out_mix = Vct.new(@channels) do
  99. (out_gain * global_gain) / @channels
  100. end
  101. end
  102. predelays = make_array(@reverb_channels) do
  103. make_delay(:size, (@srate * predelay).to_i)
  104. end
  105. room_decay_val = room_decay * scale_room_decay + offset_room_decay
  106. combs = make_array(@channels) do |c|
  107. combtuning.map do |tuning|
  108. dmp = scale_damping * damping
  109. sz = (srate_scale * tuning).to_i
  110. if c.odd?
  111. sz += (srate_scale * stereo_spread).to_i
  112. end
  113. make_fcomb(room_decay_val, sz, 1.0 - dmp, dmp)
  114. end
  115. end
  116. allpasses = make_array(@channels) do |c|
  117. allpasstuning.map do |tuning|
  118. sz = (srate_scale * tuning).to_i
  119. if c.odd?
  120. sz += (srate_scale * stereo_spread).to_i
  121. end
  122. make_all_pass(:size, sz, :feedforward, -1.0, :feedback, 0.5)
  123. end
  124. end
  125. len = @ws_reverb.length + seconds2samples(@decay_time)
  126. name = get_func_name()
  127. # to satisfy with_sound-option :info and :notehook
  128. with_sound_info(name, 0, samples2seconds(len))
  129. if @verbose
  130. Snd.message("%s on %d in and %d out channels",
  131. name, @reverb_channels, @channels)
  132. end
  133. f_in = Vct.new(@reverb_channels, 0.0)
  134. f_out = Vct.new(@channels, 0.0)
  135. out_buf = Vct.new(@channels, 0.0)
  136. if @reverb_channels == 1
  137. len.times do |i|
  138. fin = delay(predelays[0], file2sample(@ws_reverb, i, 0))
  139. combs.each_with_index do |fcbs, c|
  140. f_out[c] = 0.0
  141. fcbs.each do |fcb|
  142. f_out[c] += fcomb(fcb, fin)
  143. end
  144. end
  145. allpasses.each_with_index do |apss, c|
  146. apss.each do |aps|
  147. f_out[c] = all_pass(aps, f_out[c])
  148. end
  149. end
  150. frample2file(@ws_output, i,
  151. frample2frample(out_mix, f_out, @channels,
  152. out_buf, @channels))
  153. end
  154. else
  155. len.times do |i|
  156. fin = file2frample(@ws_reverb, i, f_in).map_with_index do |f, c|
  157. delay(predelays[c], f)
  158. end
  159. combs.each_with_index do |fcbs, c|
  160. f_out[c] = 0.0
  161. fcbs.each do |fcb|
  162. f_out[c] += fcomb(fcb, fin[c])
  163. end
  164. end
  165. allpasses.each_with_index do |apss, c|
  166. apss.each do |aps|
  167. f_out[c] = all_pass(aps, f_out[c])
  168. end
  169. end
  170. frample2file(@ws_output, i,
  171. frample2frample(out_mix, f_out, @channels,
  172. out_buf, @channels))
  173. end
  174. end
  175. end
  176. =begin
  177. with_sound(:reverb, :freeverb,
  178. :reverb_data, [:room_decay, 0.9],
  179. :channels, 2,
  180. :reverb_channels, 1,
  181. :output, "fvrb-test.snd",
  182. :play, 1,
  183. :statistics, true) do
  184. fm_violin(0, 1, 440, 0.5)
  185. end
  186. with_sound(:statistics, true,
  187. :reverb, :freeverb,
  188. :reverb_data, [:output_gain, 3.0]) do
  189. outa(0, 0.5, @ws_reverb)
  190. end
  191. with_sound(:channels, 2,
  192. :reverb_channels, 2,
  193. :statistics, true,
  194. :reverb, :freeverb,
  195. :reverb_data, [:output_gain, 3.0]) do
  196. outa(0, 0.5, @ws_reverb)
  197. outb(0, 0.1, @ws_reverb)
  198. end
  199. =end
  200. # freeverb.rb ends here