ruck 0.1.2 → 0.2.0
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/README +18 -50
- data/Rakefile +13 -13
- data/VERSION +1 -1
- data/lib/ruck/shreduling.rb +17 -40
- data/lib/ruck.rb +0 -5
- data/ruck.gemspec +4 -57
- metadata +17 -59
- data/bin/ruck_glapp +0 -162
- data/bin/ruck_midi +0 -151
- data/bin/ruck_sleep +0 -47
- data/bin/ruck_ugen +0 -53
- data/examples/glapp/ex01.rb +0 -28
- data/examples/glapp/ex02.rb +0 -57
- data/examples/glapp/ex03.rb +0 -9
- data/examples/midi/ex01.rb +0 -24
- data/examples/midi/ex02.rb +0 -72
- data/examples/ugen/ex01.rb +0 -24
- data/examples/ugen/ex02.rb +0 -2
- data/examples/ugen/ex03.rb +0 -8
- data/examples/ugen/ex04.rb +0 -14
- data/examples/ugen/ex05.rb +0 -9
- data/examples/ugen/ex06.rb +0 -10
- data/examples/ugen/ex07.rb +0 -35
- data/examples/ugen/ex08.rb +0 -28
- data/examples/ugen/ex09.rb +0 -26
- data/examples/ugen/ex10.rb +0 -15
- data/examples/ugen/ex11.rb +0 -10
- data/examples/ugen/ex12.rb +0 -9
- data/lib/ruck/bench.rb +0 -44
- data/lib/ruck/misc/linkage.rb +0 -22
- data/lib/ruck/misc/metaid.rb +0 -18
- data/lib/ruck/misc/pcm_time_helpers.rb +0 -29
- data/lib/ruck/misc/riff.rb +0 -71
- data/lib/ruck/misc/wavparse.rb +0 -35
- data/lib/ruck/ugen/general.rb +0 -408
- data/lib/ruck/ugen/oscillators.rb +0 -106
- data/lib/ruck/ugen/wav.rb +0 -185
data/lib/ruck/ugen/wav.rb
DELETED
@@ -1,185 +0,0 @@
|
|
1
|
-
|
2
|
-
require File.join(File.dirname(__FILE__), "..", "misc", "riff")
|
3
|
-
|
4
|
-
module Ruck
|
5
|
-
module Generators
|
6
|
-
|
7
|
-
# saves all incoming samples in memory to export to disk later
|
8
|
-
# outputs 0.0 samples
|
9
|
-
class WavOut
|
10
|
-
include UGen
|
11
|
-
include Source
|
12
|
-
include MultiChannelTarget
|
13
|
-
|
14
|
-
attr_reader :filename
|
15
|
-
|
16
|
-
def initialize(attrs = {})
|
17
|
-
require_attrs attrs, [:filename]
|
18
|
-
@filename = attrs.delete(:filename)
|
19
|
-
@num_channels = attrs.delete(:num_channels) || 1
|
20
|
-
@bits_per_sample = attrs.delete(:bits_per_sample) || 16
|
21
|
-
parse_attrs attrs
|
22
|
-
|
23
|
-
@in_channels = (1..@num_channels).map { InChannel.new }
|
24
|
-
|
25
|
-
@sample_rate = SAMPLE_RATE
|
26
|
-
@samples = (1..@num_channels).map { [] }
|
27
|
-
@ins = []
|
28
|
-
@last = 0.0
|
29
|
-
|
30
|
-
# TODO: this is necessary, but if UGen graph were explicitly
|
31
|
-
# destructed, that would be nice.
|
32
|
-
at_exit { save }
|
33
|
-
end
|
34
|
-
|
35
|
-
def next(now)
|
36
|
-
return @last if @now == now
|
37
|
-
@now = now
|
38
|
-
@samples << @in_channels.map { |chan| chan.next now }
|
39
|
-
@last
|
40
|
-
end
|
41
|
-
|
42
|
-
def save
|
43
|
-
LOG.info "Saving WAV to #{@filename}..."
|
44
|
-
File.open(@filename, "wb") { |f| f.write encode }
|
45
|
-
end
|
46
|
-
|
47
|
-
def attr_names
|
48
|
-
[:filename]
|
49
|
-
end
|
50
|
-
|
51
|
-
private
|
52
|
-
|
53
|
-
def encode
|
54
|
-
chunk("RIFF") do |riff|
|
55
|
-
riff << ascii("WAVE")
|
56
|
-
riff << chunk("fmt ") do |fmt|
|
57
|
-
fmt << short(1) # format = 1: PCM (no compression)
|
58
|
-
fmt << short(@num_channels)
|
59
|
-
fmt << int(@sample_rate)
|
60
|
-
fmt << int((@sample_rate * @num_channels * (@bits_per_sample / 8))) # byte-rate
|
61
|
-
fmt << short((@num_channels * @bits_per_sample/8)) # block align
|
62
|
-
fmt << short(@bits_per_sample) # bits/sample
|
63
|
-
end
|
64
|
-
riff << chunk("data") do |data|
|
65
|
-
range = 2 ** (@bits_per_sample - 1)
|
66
|
-
@samples.each do |sample_list|
|
67
|
-
sample_list.each { |sample| data << [sample * range].pack("s1") }
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
def int(i)
|
74
|
-
[i].pack("i1")
|
75
|
-
end
|
76
|
-
|
77
|
-
def short(s)
|
78
|
-
[s].pack("s1")
|
79
|
-
end
|
80
|
-
|
81
|
-
def ascii(str)
|
82
|
-
str.split("").pack("A1" * str.length)
|
83
|
-
end
|
84
|
-
|
85
|
-
def chunk(type, &block)
|
86
|
-
buf = ""
|
87
|
-
block.call(buf)
|
88
|
-
ascii(type) + int(buf.length) + buf
|
89
|
-
end
|
90
|
-
|
91
|
-
end
|
92
|
-
|
93
|
-
# plays sound stored in a RIFF WAV file
|
94
|
-
class WavIn
|
95
|
-
include UGen
|
96
|
-
include MultiChannelSource
|
97
|
-
|
98
|
-
linkable_attr :rate
|
99
|
-
linkable_attr :gain
|
100
|
-
attr_reader :filename
|
101
|
-
|
102
|
-
def initialize(attrs = {})
|
103
|
-
require_attrs attrs, [:filename]
|
104
|
-
@rate = 1.0
|
105
|
-
@gain = 1.0
|
106
|
-
@filename = attrs.delete(:filename)
|
107
|
-
parse_attrs attrs
|
108
|
-
|
109
|
-
@loaded = false
|
110
|
-
@playing = true
|
111
|
-
|
112
|
-
init_wav
|
113
|
-
end
|
114
|
-
|
115
|
-
def init_wav
|
116
|
-
riff = Riff::RiffReader.new(@filename).chunks.first
|
117
|
-
unless riff.type == "RIFF"
|
118
|
-
LOG.error "#{@filename}: Not RIFF!"
|
119
|
-
return
|
120
|
-
end
|
121
|
-
unless riff[0..3] == "WAVE"
|
122
|
-
LOG.error "#{@filename}: Not WAVE!"
|
123
|
-
return
|
124
|
-
end
|
125
|
-
|
126
|
-
riff.data_skip = 4 # skip "WAVE"
|
127
|
-
fmt = riff.chunks.first
|
128
|
-
@wav = riff.chunks.find { |c| c.type == "data" }
|
129
|
-
unless fmt[0..1].unpack("s1").first == 1
|
130
|
-
LOG.error "#{@filename}: Not PCM!"
|
131
|
-
return
|
132
|
-
end
|
133
|
-
|
134
|
-
@num_channels, @sample_rate, @byte_rate,
|
135
|
-
@block_align, @bits_per_sample =
|
136
|
-
fmt[2..15].unpack("s1i1i1s1s1")
|
137
|
-
@range = (2 ** (@bits_per_sample - 1)).to_f
|
138
|
-
|
139
|
-
@out_channels = (0..@num_channels-1).map { |chan| OutChannel.new self, chan }
|
140
|
-
@sample = [0.0] * @num_channels
|
141
|
-
@last = [0.0] * @num_channels
|
142
|
-
@now = [nil] * @num_channels
|
143
|
-
@rate_adjust = @sample_rate / SAMPLE_RATE
|
144
|
-
|
145
|
-
@loaded = true
|
146
|
-
end
|
147
|
-
|
148
|
-
def duration
|
149
|
-
@loaded ? @wav.size / @block_align / @rate_adjust : 0
|
150
|
-
end
|
151
|
-
|
152
|
-
def attr_names
|
153
|
-
[:filename, :rate]
|
154
|
-
end
|
155
|
-
|
156
|
-
def next(now, chan = 0)
|
157
|
-
return @last[chan] if @now[chan] == now
|
158
|
-
@now[chan] = now
|
159
|
-
|
160
|
-
return @last[chan] unless @loaded && @playing
|
161
|
-
|
162
|
-
offset = @sample[chan].to_i * @block_align
|
163
|
-
chan_offset = (chan * @bits_per_sample) / 8
|
164
|
-
|
165
|
-
if offset + @block_align > @wav.size
|
166
|
-
@playing = false
|
167
|
-
return @last[chan]
|
168
|
-
end
|
169
|
-
|
170
|
-
@last[chan] = @wav[offset + chan_offset, @bits_per_sample].unpack("s1").first / @range * gain
|
171
|
-
@sample[chan] += rate * @rate_adjust
|
172
|
-
@last[chan]
|
173
|
-
end
|
174
|
-
|
175
|
-
def play; @playing = true; end
|
176
|
-
def stop; @playing = false; end
|
177
|
-
|
178
|
-
def reset
|
179
|
-
@offset = 0
|
180
|
-
end
|
181
|
-
|
182
|
-
end
|
183
|
-
|
184
|
-
end
|
185
|
-
end
|