youpy-scissor 0.0.16 → 0.0.17
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.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
|