mdaines-soxophone 0.2 → 0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/examples/effects.rb +43 -3
- data/examples/mod.rb +42 -0
- data/lib/soxophone.rb +2 -0
- data/lib/soxophone/effects.rb +30 -3
- data/lib/soxophone/envelope.rb +34 -0
- data/lib/soxophone/modulation.rb +81 -0
- data/lib/soxophone/sound.rb +7 -30
- metadata +4 -1
data/examples/effects.rb
CHANGED
@@ -5,7 +5,7 @@ Soxophone.play do |x|
|
|
5
5
|
s = x.sound(:square)
|
6
6
|
s.release = 0.5
|
7
7
|
|
8
|
-
x.tune s, "a b c"
|
8
|
+
x.tune s, "a b c 4"
|
9
9
|
end
|
10
10
|
|
11
11
|
Soxophone.play do |x|
|
@@ -13,7 +13,7 @@ Soxophone.play do |x|
|
|
13
13
|
s.release = 0.5
|
14
14
|
s.tremolo = 10
|
15
15
|
|
16
|
-
x.tune s, "a b c"
|
16
|
+
x.tune s, "a b c 4"
|
17
17
|
end
|
18
18
|
|
19
19
|
Soxophone.play do |x|
|
@@ -21,5 +21,45 @@ Soxophone.play do |x|
|
|
21
21
|
s.release = 0.5
|
22
22
|
s.phaser = true
|
23
23
|
|
24
|
-
x.tune s, "a b c"
|
24
|
+
x.tune s, "a b c 4"
|
25
|
+
end
|
26
|
+
|
27
|
+
Soxophone.play do |x|
|
28
|
+
s = x.sound(:square)
|
29
|
+
s.release = 0.5
|
30
|
+
s.lowpass = 250
|
31
|
+
|
32
|
+
x.tune s, "a b c 4"
|
33
|
+
end
|
34
|
+
|
35
|
+
Soxophone.play do |x|
|
36
|
+
s = x.sound(:square)
|
37
|
+
s.release = 0.5
|
38
|
+
s.lowpass = 500
|
39
|
+
|
40
|
+
x.tune s, "a b c 4"
|
41
|
+
end
|
42
|
+
|
43
|
+
Soxophone.play do |x|
|
44
|
+
s = x.sound(:square)
|
45
|
+
s.release = 0.5
|
46
|
+
s.highpass = 500
|
47
|
+
|
48
|
+
x.tune s, "a b c 4"
|
49
|
+
end
|
50
|
+
|
51
|
+
Soxophone.play do |x|
|
52
|
+
s = x.sound(:square)
|
53
|
+
s.release = 0.5
|
54
|
+
s.highpass = 5000
|
55
|
+
|
56
|
+
x.tune s, "a b c 4"
|
57
|
+
end
|
58
|
+
|
59
|
+
Soxophone.play do |x|
|
60
|
+
s = x.sound(:square)
|
61
|
+
s.release = 0.5
|
62
|
+
s.reverb = true
|
63
|
+
|
64
|
+
x.tune s, "a b c 4"
|
25
65
|
end
|
data/examples/mod.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
$LOAD_PATH << File.dirname(__FILE__) + "/../lib"
|
2
|
+
require "soxophone"
|
3
|
+
|
4
|
+
Soxophone.play do |x|
|
5
|
+
s = x.sound(:sine)
|
6
|
+
s.mods << s.amod(:square)
|
7
|
+
|
8
|
+
x.tune s, "a b c d e f g + a 4 - (a c e) 4"
|
9
|
+
end
|
10
|
+
|
11
|
+
Soxophone.play do |x|
|
12
|
+
s = x.sound(:sine)
|
13
|
+
s.mods << s.fmod(:sine, 700..600)
|
14
|
+
|
15
|
+
x.tune s, "a b c d e f g + a 4 - (a c e) 4"
|
16
|
+
end
|
17
|
+
|
18
|
+
Soxophone.play do |x|
|
19
|
+
s = x.sound(:sine)
|
20
|
+
s.mods << s.fmod(:square, 100)
|
21
|
+
s.gain = -4
|
22
|
+
|
23
|
+
x.tune s, "a b c d e f g + a 4 - (a c e) 4"
|
24
|
+
end
|
25
|
+
|
26
|
+
Soxophone.play do |x|
|
27
|
+
s = x.sound(:sine)
|
28
|
+
s.mods << s.fmod(:sine)
|
29
|
+
|
30
|
+
ss = x.sound(:sine)
|
31
|
+
ss.mods << ss.fmod(:sine)
|
32
|
+
ss.mods << ss.fmod(:sine)
|
33
|
+
|
34
|
+
sss = x.sound(:sine)
|
35
|
+
sss.mods << sss.fmod(:sine)
|
36
|
+
sss.mods << sss.fmod(:sine)
|
37
|
+
sss.mods << sss.fmod(:sine)
|
38
|
+
|
39
|
+
x.tune s, "a b c"
|
40
|
+
x.tune ss, "4 4 4 a b c"
|
41
|
+
x.tune sss, "4 4 4 4 4 4 a b c 4"
|
42
|
+
end
|
data/lib/soxophone.rb
CHANGED
data/lib/soxophone/effects.rb
CHANGED
@@ -5,33 +5,60 @@ module Soxophone
|
|
5
5
|
attr_reader :tremolo
|
6
6
|
attr_reader :phaser
|
7
7
|
attr_reader :gain
|
8
|
+
attr_reader :highpass
|
9
|
+
attr_reader :lowpass
|
10
|
+
attr_reader :reverb
|
8
11
|
|
9
12
|
def tremolo=(tremolo)
|
10
13
|
unless tremolo.is_a?(Numeric)
|
11
|
-
raise "
|
14
|
+
raise "rremolo must be a number"
|
12
15
|
end
|
13
16
|
@tremolo = tremolo
|
14
17
|
end
|
15
18
|
|
16
19
|
def phaser=(phaser)
|
17
20
|
unless [true, false].include?(phaser)
|
18
|
-
raise "
|
21
|
+
raise "phaser must be true or false"
|
19
22
|
end
|
20
23
|
@phaser = phaser
|
21
24
|
end
|
22
25
|
|
23
26
|
def gain=(gain)
|
24
27
|
unless gain.is_a?(Numeric)
|
25
|
-
raise "
|
28
|
+
raise "gain must be a number"
|
26
29
|
end
|
27
30
|
@gain = gain
|
28
31
|
end
|
29
32
|
|
33
|
+
def highpass=(highpass)
|
34
|
+
unless highpass.is_a?(Numeric)
|
35
|
+
raise "highpass must be a number"
|
36
|
+
end
|
37
|
+
@highpass = highpass
|
38
|
+
end
|
39
|
+
|
40
|
+
def lowpass=(lowpass)
|
41
|
+
unless lowpass.is_a?(Numeric)
|
42
|
+
raise "lowpass must be a number"
|
43
|
+
end
|
44
|
+
@lowpass = lowpass
|
45
|
+
end
|
46
|
+
|
47
|
+
def reverb=(reverb)
|
48
|
+
unless [true, false].include?(reverb)
|
49
|
+
raise "Reverb must be true or false"
|
50
|
+
end
|
51
|
+
@reverb = reverb
|
52
|
+
end
|
53
|
+
|
30
54
|
def effectopts
|
31
55
|
fx = []
|
32
56
|
fx << "tremolo #{tremolo}" if tremolo
|
33
57
|
fx << "phaser 0.6 0.66 3 0.6 2 -t" if phaser
|
34
58
|
fx << "gain #{gain}" if gain
|
59
|
+
fx << "highpass #{highpass}" if highpass
|
60
|
+
fx << "lowpass #{lowpass}" if lowpass
|
61
|
+
fx << "reverb" if reverb
|
35
62
|
|
36
63
|
fx.compact.join(" ")
|
37
64
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Soxophone
|
2
|
+
|
3
|
+
module Envelope
|
4
|
+
|
5
|
+
attr_reader :attack
|
6
|
+
attr_reader :release
|
7
|
+
|
8
|
+
def attack=(attack)
|
9
|
+
unless attack.is_a?(Numeric)
|
10
|
+
raise "attack must be a number"
|
11
|
+
end
|
12
|
+
@attack = attack
|
13
|
+
end
|
14
|
+
|
15
|
+
def release=(release)
|
16
|
+
unless release.is_a?(Numeric)
|
17
|
+
raise "release must be a number"
|
18
|
+
end
|
19
|
+
@release = release
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def envelope(duration)
|
25
|
+
env = []
|
26
|
+
env << "fade #{attack * duration}" if attack > 0
|
27
|
+
env << "fade 0 #{duration} #{release * duration}" if release > 0
|
28
|
+
|
29
|
+
env.compact.join(" ")
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module Soxophone
|
2
|
+
|
3
|
+
module Modulation
|
4
|
+
|
5
|
+
class Combine
|
6
|
+
|
7
|
+
COMBINES = %w( fmod amod )
|
8
|
+
|
9
|
+
KINDS = %w(
|
10
|
+
sine square triangle sawtooth trapezium
|
11
|
+
exp noise whitenoise pinknoise brownnoise
|
12
|
+
)
|
13
|
+
|
14
|
+
def initialize(combine, kind, frequency = nil)
|
15
|
+
self.combine = combine
|
16
|
+
self.kind = kind
|
17
|
+
self.frequency = frequency
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_reader :combine
|
21
|
+
attr_reader :kind
|
22
|
+
attr_reader :frequency
|
23
|
+
|
24
|
+
def combine=(combine)
|
25
|
+
if COMBINES.include?(combine.to_s)
|
26
|
+
@combine = combine
|
27
|
+
else
|
28
|
+
raise "combine must be one of: #{COMBINES.join(", ")}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def kind=(kind)
|
33
|
+
if KINDS.include?(kind.to_s)
|
34
|
+
@kind = kind
|
35
|
+
else
|
36
|
+
raise "kind must be one of: #{KINDS.join(", ")}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def frequency=(freq)
|
41
|
+
if freq.nil? || freq.is_a?(Numeric) || (freq.is_a?(Range) && freq.first.is_a?(Numeric) && freq.first.is_a?(Numeric))
|
42
|
+
@frequency = freq
|
43
|
+
else
|
44
|
+
raise "frequency must be nil, a number, or a range of numbers"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def synth(duration, freq)
|
49
|
+
if frequency.nil?
|
50
|
+
"synth #{duration} #{kind} #{combine} %#{freq}"
|
51
|
+
elsif frequency.is_a?(Numeric)
|
52
|
+
"synth #{duration} #{kind} #{combine} #{frequency}"
|
53
|
+
elsif frequency.is_a?(Range)
|
54
|
+
"synth #{duration} #{kind} #{combine} #{frequency.first}-#{frequency.last}"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
def fmod(kind, freq = nil)
|
61
|
+
Combine.new(:fmod, kind, freq)
|
62
|
+
end
|
63
|
+
|
64
|
+
def amod(kind, freq = nil)
|
65
|
+
Combine.new(:amod, kind, freq)
|
66
|
+
end
|
67
|
+
|
68
|
+
def mods
|
69
|
+
@mods = [] unless defined?(@mods)
|
70
|
+
@mods
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def modulation(duration, freq)
|
76
|
+
mods.map { |m| m.synth(duration, freq) }.join(" ")
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
data/lib/soxophone/sound.rb
CHANGED
@@ -3,6 +3,8 @@ module Soxophone
|
|
3
3
|
class Sound
|
4
4
|
|
5
5
|
include Effects
|
6
|
+
include Modulation
|
7
|
+
include Envelope
|
6
8
|
|
7
9
|
KINDS = %w(
|
8
10
|
sine square triangle sawtooth trapezium
|
@@ -16,50 +18,25 @@ module Soxophone
|
|
16
18
|
end
|
17
19
|
|
18
20
|
attr_reader :kind
|
19
|
-
attr_reader :attack
|
20
|
-
attr_reader :release
|
21
21
|
|
22
22
|
def kind=(kind)
|
23
23
|
unless KINDS.include?(kind.to_s)
|
24
|
-
raise "
|
24
|
+
raise "kind must be one of: #{KINDS.join(", ")}"
|
25
25
|
end
|
26
26
|
@kind = kind
|
27
27
|
end
|
28
28
|
|
29
|
-
def attack=(attack)
|
30
|
-
unless attack.is_a?(Numeric)
|
31
|
-
raise "Attack must be a number"
|
32
|
-
end
|
33
|
-
@attack = attack
|
34
|
-
end
|
35
|
-
|
36
|
-
def release=(release)
|
37
|
-
unless release.is_a?(Numeric)
|
38
|
-
raise "Release must be a number"
|
39
|
-
end
|
40
|
-
@release = release
|
41
|
-
end
|
42
|
-
|
43
29
|
def notecmd(freq, duration)
|
44
30
|
env = envelope(duration)
|
45
|
-
|
31
|
+
mod = modulation(duration, freq)
|
32
|
+
"sox -n -p synth #{duration} #{kind} %#{freq} #{mod} #{env}"
|
46
33
|
end
|
47
34
|
|
48
35
|
def chordcmd(freqs, duration)
|
49
|
-
|
50
|
-
"sox -
|
36
|
+
cmds = freqs.map { |f| notecmd(f, duration) }
|
37
|
+
"sox -m #{cmds.map { |c| "\"|#{c}\"" }.join(" ")} -p"
|
51
38
|
end
|
52
39
|
|
53
|
-
private
|
54
|
-
|
55
|
-
def envelope(duration)
|
56
|
-
env = []
|
57
|
-
env << "fade #{attack * duration}" if attack > 0
|
58
|
-
env << "fade 0 #{duration} #{release * duration}" if release > 0
|
59
|
-
|
60
|
-
env.compact.join(" ")
|
61
|
-
end
|
62
|
-
|
63
40
|
end
|
64
41
|
|
65
42
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mdaines-soxophone
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: "0.
|
4
|
+
version: "0.3"
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Daines
|
@@ -29,6 +29,7 @@ files:
|
|
29
29
|
- examples/chords.rb
|
30
30
|
- examples/effects.rb
|
31
31
|
- examples/envelope.rb
|
32
|
+
- examples/mod.rb
|
32
33
|
- examples/notation.rb
|
33
34
|
- examples/samples.rb
|
34
35
|
- examples/crash.mp3
|
@@ -36,6 +37,8 @@ files:
|
|
36
37
|
- lib/soxophone.rb
|
37
38
|
- lib/soxophone/base.rb
|
38
39
|
- lib/soxophone/effects.rb
|
40
|
+
- lib/soxophone/envelope.rb
|
41
|
+
- lib/soxophone/modulation.rb
|
39
42
|
- lib/soxophone/notation.rb
|
40
43
|
- lib/soxophone/notation.rl
|
41
44
|
- lib/soxophone/sample.rb
|