1# noise.rb -- CLM -> Snd/Ruby translation of noise.ins
2
3# Translator/Author: Michael Scholz <mi-scholz@users.sourceforge.net>
4# Created: Wed Mar 19 05:16:56 CET 2003
5# Changed: Thu Oct 15 00:17:48 CEST 2009
6
7# Comments beginning with ;; are taken from noise.ins!
8
9# attack_point(dur, attack, decay, total_x = 100.0)
10# fm_noise(...)
11
12# ;;; The "noise" instrument (useful for Oceanic Music):
13
14require "ws"
15require "env"
16include Env
17
18def attack_point(dur, attack, decay, total_x = 100.0)
19  x = if 0.0 == attack
20        if 0.0 == decay
21          dur / 4.0
22        else
23          (dur - decay) / 4.0
24        end
25      else
26        attack.to_f
27      end
28  total_x * (x / dur)
29end
30
31def fm_noise(start, dur, freq0,
32             amp, ampfun, ampat, ampdc,
33             freq1, glissfun, freqat, freqdc,
34             rfreq0, rfreq1, rfreqfun, rfreqat, rfreqdc,
35             dev0, dev1, devfun, devat, devdc,
36             *args)
37  degree, distance, reverb = nil
38  optkey(args, binding,
39         [:degree, kernel_rand(90.0)],
40         [:distance, 1.0],
41         [:reverb, 0.005])
42
43  # ;; ampat = amp envelope attack time, and so on -- this instrument
44  # ;; assumes your envelopes go from 0 to 100 on the x-axis, and that
45  # ;; the "attack" portion ends at 25, the "decay" portion starts at
46  # ;; 75.  "rfreq" is the frequency of the random number generator --
47  # ;; if below about 25 hz you get automatic composition, above that
48  # ;; you start to get noise.  well, you get a different kind of
49  # ;; noise.  "dev" is the bandwidth of the noise -- very narrow
50  # ;; gives a whistle, very broad more of a whoosh.  this is
51  # ;; basically "simple fm", but the modulating signal is white
52  # ;; noise.
53
54  car = make_oscil(:frequency, freq0)
55  mod = make_rand(:frequency, rfreq0, :amplitude, 1.0)
56  dev_0 = hz2radians(dev0)
57
58  # ;; next fix-up troubles in attack and decay times (there are lots
59  # ;; of ways to handle this -- the basic problem is that these
60  # ;; durned instruments end up having way too many parameters.  rick
61  # ;; taube's common music replacement for pla should help, but just
62  # ;; for old time's sake, we'll do it the way the ancients did it.
63  # ;; (we could also package up this stuff in our own function,
64  # ;; somewhat like the allvln function in vln.clm, leaving the
65  # ;; instrument code to apply envelopes and other data to some
66  # ;; patch).
67
68  amp_attack = attack_point(dur, ampat, ampdc)
69  amp_decay = 100.0 - attack_point(dur, ampdc, ampat)
70  freq_attack = attack_point(dur, freqat, freqdc)
71  freq_decay = 100.0 - attack_point(dur, freqdc, freqat)
72  dev_attack = attack_point(dur, devat, devdc)
73  dev_decay = 100.0 - attack_point(dur, devdc, devat)
74  rfreq_attack = attack_point(dur, rfreqat, rfreqdc)
75  rfreq_decay = 100.0 - attack_point(dur, rfreqdc, rfreqat)
76
77  # ;; now make the actual envelopes -- these all assume we are
78  # ;; thinking in terms of the "value when the envelope is 1"
79  # ;; (i.e. dev1 and friends), and the "value when the envelope is 0"
80  # ;; (i.e. dev0 and friends) -- over the years this seemed to make
81  # ;; beginners happier than various other ways of describing the
82  # ;; y-axis behaviour of the envelope.  all this boiler-plate for
83  # ;; envelopes might seem overly elaborate when our basic instrument
84  # ;; is really simple, but in most cases, and this one in
85  # ;; particular, nearly all the musical interest comes from the
86  # ;; envelopes, not the somewhat dull spectrum generated by the
87  # ;; basic patch.
88
89  dev_f = make_env(stretch_envelope(devfun, 25, dev_attack, 75, dev_decay),
90                   hz2radians(dev1 - dev0), dur)
91  amp_f = make_env(stretch_envelope(ampfun, 25, amp_attack, 75, amp_decay), amp, dur)
92  freq_f = make_env(stretch_envelope(glissfun, 25, freq_attack, 75, freq_decay),
93                    hz2radians(freq1 - freq0), dur)
94  rfreq_f = make_env(stretch_envelope(rfreqfun, 25, rfreq_attack, 75, rfreq_decay),
95                     hz2radians(rfreq1 - rfreq0), dur)
96
97  run_instrument(start, dur, :degree, degree, :distance, distance, :reverb_amount, reverb) do
98    env(amp_f) * oscil(car, env(freq_f) + (dev_0 + env(dev_f)) * rand(mod, env(rfreq_f)))
99  end
100end
101
102=begin
103with_sound(:statistics, true, :play, 1) do
104  fm_noise(0, 1.8, 500,
105           0.25, [0, 0, 25, 1, 75, 1, 100, 0], 0.1, 0.1,
106           1000, [0, 0, 100, 1], 0.1, 0.1,
107           10, 1000, [0, 0, 100, 1], 0, 0,
108           100, 500, [0, 0, 100, 1], 0, 0)
109  fm_noise(2, 1.8, 200,
110           0.25, [0, 0, 25, 1, 75, 1, 100, 0], 0.1, 0.1,
111           1000, [0, 0, 100, 1], 0.1, 0.1,
112           10, 1000, [0, 0, 100, 1], 0, 0,
113           100, 500, [0, 0, 100, 1], 0, 0)
114end
115=end
116
117# noise.rb ends here
118