youpy-scissor 0.0.16 → 0.0.17
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +3 -2
- data/Rakefile +1 -1
- data/lib/scissor/chunk.rb +40 -31
- data/lib/scissor/sequence.rb +11 -7
- metadata +2 -2
data/README.rdoc
CHANGED
@@ -22,6 +22,7 @@ supported file format:
|
|
22
22
|
|
23
23
|
=== Gem Installation
|
24
24
|
|
25
|
+
gem sources -a http://gems.github.com/
|
25
26
|
gem install youpy-scissor
|
26
27
|
|
27
28
|
== Features/Problems
|
@@ -40,7 +41,7 @@ supported file format:
|
|
40
41
|
foo[10, 1] + bar.slice[2, 3] > 'slicefoobar.mp3'
|
41
42
|
|
42
43
|
# slice + concat + loop
|
43
|
-
foo[10, 1] + bar[2, 3] * 4 > 'slicefoobarloop.mp3'
|
44
|
+
(foo[10, 1] + bar[2, 3]) * 4 > 'slicefoobarloop.mp3'
|
44
45
|
|
45
46
|
# split
|
46
47
|
(Scissor('sequence.mp3') / 16).first.to_file('split.mp3')
|
@@ -50,7 +51,7 @@ supported file format:
|
|
50
51
|
|
51
52
|
# sequence + loop
|
52
53
|
seq = Scissor.sequence('x y xyz', 0.2)
|
53
|
-
seq.apply(:x => foo, :y => bar, :z => foo.reverse) * 4 > 'sequence.wav'
|
54
|
+
seq.apply(:x => foo, :y => Proc.new { bar }, :z => foo.reverse) * 4 > 'sequence.wav'
|
54
55
|
|
55
56
|
== Copyright
|
56
57
|
|
data/Rakefile
CHANGED
@@ -17,7 +17,7 @@ DESCRIPTION = "utility to chop sound files"
|
|
17
17
|
RUBYFORGE_PROJECT = "scissor"
|
18
18
|
HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
|
19
19
|
BIN_FILES = %w( )
|
20
|
-
VERS = "0.0.
|
20
|
+
VERS = "0.0.17"
|
21
21
|
|
22
22
|
REV = File.read(".svn/entries")[/committed-rev="(d+)"/, 1] rescue nil
|
23
23
|
CLEAN.include ['**/.*.sw?', '*.gem', '.config']
|
data/lib/scissor/chunk.rb
CHANGED
@@ -2,9 +2,17 @@ require 'digest/md5'
|
|
2
2
|
require 'pathname'
|
3
3
|
require 'open4'
|
4
4
|
require 'logger'
|
5
|
+
require 'bigdecimal'
|
5
6
|
|
6
7
|
module Scissor
|
7
8
|
class Chunk
|
9
|
+
@logger = Logger.new(STDOUT)
|
10
|
+
@logger.level = Logger::INFO
|
11
|
+
|
12
|
+
class << self
|
13
|
+
attr_accessor :logger
|
14
|
+
end
|
15
|
+
|
8
16
|
class Error < StandardError; end
|
9
17
|
class FileExists < Error; end
|
10
18
|
class EmptyFragment < Error; end
|
@@ -12,12 +20,9 @@ module Scissor
|
|
12
20
|
class CommandFailed < Error; end
|
13
21
|
|
14
22
|
attr_reader :fragments
|
15
|
-
attr_accessor :logger
|
16
23
|
|
17
24
|
def initialize(filename = nil)
|
18
25
|
@fragments = []
|
19
|
-
@logger = Logger.new(STDOUT)
|
20
|
-
@logger.level = Logger::INFO
|
21
26
|
|
22
27
|
if filename
|
23
28
|
@fragments << Fragment.new(
|
@@ -31,12 +36,19 @@ module Scissor
|
|
31
36
|
@fragments << fragment
|
32
37
|
end
|
33
38
|
|
34
|
-
def
|
35
|
-
|
36
|
-
|
39
|
+
def add_fragments(fragments)
|
40
|
+
fragments.each do |fragment|
|
41
|
+
add_fragment(fragment)
|
37
42
|
end
|
38
43
|
end
|
39
44
|
|
45
|
+
def duration
|
46
|
+
BigDecimal(
|
47
|
+
@fragments.inject(0) do |memo, fragment|
|
48
|
+
memo += fragment.duration
|
49
|
+
end.to_s).round(3).to_f
|
50
|
+
end
|
51
|
+
|
40
52
|
def slice(start, length)
|
41
53
|
if start + length > duration
|
42
54
|
raise OutOfDuration
|
@@ -65,9 +77,7 @@ module Scissor
|
|
65
77
|
alias [] slice
|
66
78
|
|
67
79
|
def concat(other)
|
68
|
-
other.fragments
|
69
|
-
add_fragment(fragment)
|
70
|
-
end
|
80
|
+
add_fragments(other.fragments)
|
71
81
|
|
72
82
|
self
|
73
83
|
end
|
@@ -76,11 +86,7 @@ module Scissor
|
|
76
86
|
|
77
87
|
def +(other)
|
78
88
|
new_instance = Scissor()
|
79
|
-
|
80
|
-
(@fragments + other.fragments).each do |fragment|
|
81
|
-
new_instance.add_fragment(fragment)
|
82
|
-
end
|
83
|
-
|
89
|
+
new_instance.add_fragments(@fragments + other.fragments)
|
84
90
|
new_instance
|
85
91
|
end
|
86
92
|
|
@@ -88,9 +94,7 @@ module Scissor
|
|
88
94
|
orig_fragments = @fragments.clone
|
89
95
|
|
90
96
|
(count - 1).times do
|
91
|
-
orig_fragments
|
92
|
-
add_fragment(fragment)
|
93
|
-
end
|
97
|
+
add_fragments(orig_fragments)
|
94
98
|
end
|
95
99
|
|
96
100
|
self
|
@@ -133,11 +137,11 @@ module Scissor
|
|
133
137
|
new_instance
|
134
138
|
end
|
135
139
|
|
136
|
-
def replace(start,
|
140
|
+
def replace(start, length, replaced)
|
137
141
|
new_instance = self.class.new
|
138
|
-
offset = start +
|
142
|
+
offset = start + length
|
139
143
|
|
140
|
-
if offset >
|
144
|
+
if offset > duration
|
141
145
|
raise OutOfDuration
|
142
146
|
end
|
143
147
|
|
@@ -146,7 +150,7 @@ module Scissor
|
|
146
150
|
end
|
147
151
|
|
148
152
|
new_instance += replaced
|
149
|
-
new_instance += slice(offset,
|
153
|
+
new_instance += slice(offset, duration - offset)
|
150
154
|
|
151
155
|
new_instance
|
152
156
|
end
|
@@ -197,36 +201,37 @@ module Scissor
|
|
197
201
|
|
198
202
|
begin
|
199
203
|
@fragments.each_with_index do |fragment, index|
|
204
|
+
fragment_filename = fragment.filename
|
205
|
+
fragment_duration = fragment.duration
|
206
|
+
|
200
207
|
if !index.zero? && (index % 80).zero?
|
201
208
|
run_command(cmd.join(' '))
|
202
209
|
cmd = %w/ecasound/
|
203
210
|
end
|
204
211
|
|
205
212
|
fragment_tmpfile =
|
206
|
-
|
207
|
-
tmpdir + (Digest::MD5.hexdigest(
|
213
|
+
fragment_filename.extname.downcase == '.wav' ? fragment_filename :
|
214
|
+
tmpdir + (Digest::MD5.hexdigest(fragment_filename) + '.wav')
|
208
215
|
|
209
216
|
unless fragment_tmpfile.exist?
|
210
|
-
run_command("ffmpeg -i \"#{
|
217
|
+
run_command("ffmpeg -i \"#{fragment_filename}\" \"#{fragment_tmpfile}\"")
|
211
218
|
end
|
212
219
|
|
213
220
|
cmd <<
|
214
221
|
"-a:#{index} " +
|
215
222
|
"-i:" +
|
216
223
|
(fragment.reversed? ? 'reverse,' : '') +
|
217
|
-
"select,#{fragment.start},#{
|
224
|
+
"select,#{fragment.start},#{fragment_duration},\"#{fragment_tmpfile}\" " +
|
218
225
|
"-o:#{tmpfile} " +
|
219
226
|
"-y:#{position}"
|
220
227
|
|
221
|
-
position +=
|
228
|
+
position += fragment_duration
|
222
229
|
end
|
223
230
|
|
224
231
|
run_command(cmd.join(' '))
|
225
232
|
|
226
233
|
if filename.extname == '.wav'
|
227
|
-
|
228
|
-
file.write(tmpfile.read)
|
229
|
-
end
|
234
|
+
File.rename(tmpfile, filename)
|
230
235
|
else
|
231
236
|
run_command("ffmpeg -i \"#{tmpfile}\" \"#{filename}\"")
|
232
237
|
end
|
@@ -248,11 +253,11 @@ module Scissor
|
|
248
253
|
end
|
249
254
|
|
250
255
|
def run_command(cmd)
|
251
|
-
|
256
|
+
logger.debug("run_command: #{cmd}")
|
252
257
|
|
253
258
|
result = ''
|
254
259
|
status = Open4.popen4(cmd) do |pid, stdin, stdout, stderr|
|
255
|
-
|
260
|
+
logger.debug(stderr.read)
|
256
261
|
result = stdout.read
|
257
262
|
end
|
258
263
|
|
@@ -262,5 +267,9 @@ module Scissor
|
|
262
267
|
|
263
268
|
return result
|
264
269
|
end
|
270
|
+
|
271
|
+
def logger
|
272
|
+
self.class.logger
|
273
|
+
end
|
265
274
|
end
|
266
275
|
end
|
data/lib/scissor/sequence.rb
CHANGED
@@ -5,18 +5,22 @@ module Scissor
|
|
5
5
|
@duration_per_step = duration_per_step
|
6
6
|
end
|
7
7
|
|
8
|
-
def apply(
|
8
|
+
def apply(instruments)
|
9
9
|
result = Scissor()
|
10
10
|
|
11
11
|
@pattern.split(//).each do |c|
|
12
|
-
if
|
13
|
-
|
12
|
+
if instruments.include?(c.to_sym)
|
13
|
+
instrument = instruments[c.to_sym]
|
14
14
|
|
15
|
-
if
|
16
|
-
|
17
|
-
|
15
|
+
if instrument.is_a?(Proc)
|
16
|
+
instrument = instrument.call(c)
|
17
|
+
end
|
18
|
+
|
19
|
+
if @duration_per_step > instrument.duration
|
20
|
+
result += instrument
|
21
|
+
result += Scissor.silence(@duration_per_step - instrument.duration)
|
18
22
|
else
|
19
|
-
result +=
|
23
|
+
result += instrument.slice(0, @duration_per_step)
|
20
24
|
end
|
21
25
|
else
|
22
26
|
result += Scissor.silence(@duration_per_step)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: youpy-scissor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.17
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- youpy
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-04-
|
12
|
+
date: 2009-04-15 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|