rsox-command 0.0.1
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/.gitignore +5 -0
- data/Gemfile +4 -0
- data/Guardfile +9 -0
- data/Rakefile +1 -0
- data/bin/silent-file +21 -0
- data/bin/silent-files +14 -0
- data/lib/rsox-command.rb +13 -0
- data/lib/sox/command.rb +200 -0
- data/lib/sox/stats.rb +51 -0
- data/rsox-command.gemspec +28 -0
- data/spec/fixtures/test.ogg +0 -0
- data/spec/fixtures/test.stats +16 -0
- data/spec/lib/sox/command_spec.rb +288 -0
- data/spec/lib/sox/stats_spec.rb +55 -0
- data/spec/spec_helper.rb +8 -0
- metadata +168 -0
data/Gemfile
ADDED
data/Guardfile
ADDED
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/silent-file
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rsox-command'
|
4
|
+
|
5
|
+
file = ARGV.first
|
6
|
+
stats = Sox::Stats.new(file)
|
7
|
+
|
8
|
+
begin
|
9
|
+
$stderr.puts "#{file} rms_level:#{stats.rms_level}dB rms_peak:#{stats.rms_peak}dB" if $DEBUG
|
10
|
+
|
11
|
+
if stats.silent?
|
12
|
+
puts "silent"
|
13
|
+
exit 0
|
14
|
+
else
|
15
|
+
puts "not silent"
|
16
|
+
exit 1
|
17
|
+
end
|
18
|
+
rescue => e
|
19
|
+
$stderr.puts "Error: #{file}, #{e}"
|
20
|
+
exit 2
|
21
|
+
end
|
data/bin/silent-files
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rsox-command'
|
4
|
+
|
5
|
+
ARGV.each do |file|
|
6
|
+
Sox::Stats.new(file).tap do |stats|
|
7
|
+
begin
|
8
|
+
$stderr.puts "#{file} rms_level:#{stats.rms_level}dB rms_peak:#{stats.rms_peak}dB" if $DEBUG
|
9
|
+
puts file if stats.silent?
|
10
|
+
rescue => e
|
11
|
+
$stderr.puts "Error: #{file}, #{e}"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/rsox-command.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
|
2
|
+
module Sox
|
3
|
+
|
4
|
+
end
|
5
|
+
|
6
|
+
require 'active_support/core_ext/module/attribute_accessors'
|
7
|
+
require 'active_support/core_ext/object/blank'
|
8
|
+
require 'active_support/core_ext/enumerable'
|
9
|
+
require 'active_support/core_ext/module/delegation'
|
10
|
+
|
11
|
+
require 'sox/command'
|
12
|
+
require 'sox/stats'
|
13
|
+
|
data/lib/sox/command.rb
ADDED
@@ -0,0 +1,200 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
require 'cocaine'
|
3
|
+
|
4
|
+
module Sox
|
5
|
+
|
6
|
+
@@logger = nil
|
7
|
+
mattr_accessor :logger
|
8
|
+
|
9
|
+
def self.command
|
10
|
+
command = Command.new
|
11
|
+
yield command
|
12
|
+
command.run
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.command!
|
16
|
+
command = Command.new
|
17
|
+
yield command
|
18
|
+
command.run!
|
19
|
+
end
|
20
|
+
|
21
|
+
# Sox.command do |sox|
|
22
|
+
# sox.input "input1.wav"
|
23
|
+
# sox.input "input2", :type => "ogg"
|
24
|
+
#
|
25
|
+
# sox.output "output", :type => "ogg", :compression => 8
|
26
|
+
# end
|
27
|
+
class Command
|
28
|
+
|
29
|
+
attr_accessor :inputs, :effects
|
30
|
+
attr_writer :output
|
31
|
+
attr_accessor :run_output
|
32
|
+
|
33
|
+
def initialize(&block)
|
34
|
+
@inputs = []
|
35
|
+
@effects = []
|
36
|
+
yield self if block_given?
|
37
|
+
end
|
38
|
+
|
39
|
+
def input(filename, options = {})
|
40
|
+
inputs << File.new(filename, options)
|
41
|
+
end
|
42
|
+
|
43
|
+
def output(*arguments)
|
44
|
+
if arguments.empty?
|
45
|
+
@output
|
46
|
+
else
|
47
|
+
self.output=File.new(*arguments)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def effect(name, *arguments)
|
52
|
+
effects << Effect.new(name, *arguments)
|
53
|
+
end
|
54
|
+
|
55
|
+
def command_line
|
56
|
+
Cocaine::CommandLine.new("sox", "#{command_arguments} 2>&1")
|
57
|
+
end
|
58
|
+
|
59
|
+
def command_arguments
|
60
|
+
[].tap do |arguments|
|
61
|
+
unless inputs.empty?
|
62
|
+
if playlist.useful?
|
63
|
+
arguments << playlist.create
|
64
|
+
else
|
65
|
+
arguments << inputs.collect(&:command_arguments)
|
66
|
+
end
|
67
|
+
else
|
68
|
+
arguments << "-n"
|
69
|
+
end
|
70
|
+
|
71
|
+
unless output.blank?
|
72
|
+
arguments << output.command_arguments
|
73
|
+
else
|
74
|
+
arguments << "-n"
|
75
|
+
end
|
76
|
+
|
77
|
+
arguments << effects.collect(&:command_arguments).join(' : ')
|
78
|
+
end.flatten.delete_if(&:blank?).join(' ')
|
79
|
+
end
|
80
|
+
|
81
|
+
def playlist
|
82
|
+
@playlist ||= Playlist.new(inputs)
|
83
|
+
end
|
84
|
+
|
85
|
+
def run
|
86
|
+
begin
|
87
|
+
run!
|
88
|
+
true
|
89
|
+
rescue Cocaine::CommandLineError => e
|
90
|
+
false
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def run!
|
95
|
+
Sox.logger.debug "Run '#{command_line.command}'" if Sox.logger
|
96
|
+
|
97
|
+
begin
|
98
|
+
self.run_output = command_line.run
|
99
|
+
ensure
|
100
|
+
playlist.delete
|
101
|
+
end
|
102
|
+
|
103
|
+
self
|
104
|
+
end
|
105
|
+
|
106
|
+
class Playlist
|
107
|
+
|
108
|
+
attr_accessor :inputs
|
109
|
+
|
110
|
+
def initialize(inputs)
|
111
|
+
@inputs = inputs
|
112
|
+
end
|
113
|
+
|
114
|
+
def file
|
115
|
+
@file ||= Tempfile.new(['sox-command-playlist','.m3u'])
|
116
|
+
end
|
117
|
+
|
118
|
+
def path
|
119
|
+
file.path
|
120
|
+
end
|
121
|
+
|
122
|
+
def create
|
123
|
+
::File.open(file.path,"w") do |playlist|
|
124
|
+
inputs.each do |input|
|
125
|
+
playlist.puts input.filename
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
file.path
|
130
|
+
end
|
131
|
+
|
132
|
+
def delete
|
133
|
+
if @file
|
134
|
+
@file.close(true)
|
135
|
+
@file = nil
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def useful?
|
140
|
+
inputs.all? { |input| input.options.empty? } and
|
141
|
+
inputs.sum { |i| i.filename.size } > 500
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
class File
|
147
|
+
|
148
|
+
attr_accessor :filename, :options
|
149
|
+
|
150
|
+
def initialize(filename, options = {})
|
151
|
+
@filename = filename
|
152
|
+
@options = options
|
153
|
+
end
|
154
|
+
|
155
|
+
def command_arguments
|
156
|
+
unless options.empty?
|
157
|
+
format_options = sorted_options.collect do |name, value|
|
158
|
+
"--#{name} #{value}"
|
159
|
+
end.join(' ') + " "
|
160
|
+
end
|
161
|
+
"#{format_options}#{filename}"
|
162
|
+
end
|
163
|
+
|
164
|
+
def sorted_options
|
165
|
+
options.to_a.sort_by { |pair| pair.first.to_s }
|
166
|
+
end
|
167
|
+
|
168
|
+
def ==(other)
|
169
|
+
other and
|
170
|
+
other.filename == filename and
|
171
|
+
other.options == options
|
172
|
+
end
|
173
|
+
|
174
|
+
end
|
175
|
+
|
176
|
+
class Effect
|
177
|
+
|
178
|
+
attr_accessor :name, :arguments
|
179
|
+
|
180
|
+
def initialize(name, *arguments)
|
181
|
+
@name = name
|
182
|
+
@arguments = arguments
|
183
|
+
end
|
184
|
+
|
185
|
+
def ==(other)
|
186
|
+
other and
|
187
|
+
other.name == name and
|
188
|
+
other.arguments == arguments
|
189
|
+
end
|
190
|
+
|
191
|
+
def command_arguments
|
192
|
+
[ @name, *arguments].join(' ')
|
193
|
+
end
|
194
|
+
|
195
|
+
end
|
196
|
+
|
197
|
+
end
|
198
|
+
|
199
|
+
|
200
|
+
end
|
data/lib/sox/stats.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
module Sox
|
2
|
+
class Stats
|
3
|
+
|
4
|
+
attr_reader :command
|
5
|
+
|
6
|
+
def initialize(file = nil)
|
7
|
+
@command = Sox::Command.new.tap do |command|
|
8
|
+
command.effect "stats"
|
9
|
+
command.input file if file
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
delegate :input, :to => :command
|
14
|
+
|
15
|
+
def raw_output
|
16
|
+
command.run!.run_output
|
17
|
+
end
|
18
|
+
|
19
|
+
def raw_values
|
20
|
+
if raw_output.chomp == "sox WARN stats: no audio"
|
21
|
+
raise "No audio found by sox"
|
22
|
+
else
|
23
|
+
raw_output.scan(/^(\w+( \w+)*) +([\w.-]+)/i)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def attributes
|
28
|
+
@attributes ||=
|
29
|
+
begin
|
30
|
+
paires = raw_values.collect do |key, _, value|
|
31
|
+
value = value.to_f if value =~ /^-?[0-9.]+$/
|
32
|
+
[key, value]
|
33
|
+
end
|
34
|
+
Hash[paires]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def rms_level
|
39
|
+
attributes['RMS lev dB']
|
40
|
+
end
|
41
|
+
|
42
|
+
def rms_peak
|
43
|
+
attributes['RMS Pk dB']
|
44
|
+
end
|
45
|
+
|
46
|
+
def silent?
|
47
|
+
rms_peak < -45
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "rsox-command"
|
6
|
+
s.version = "0.0.1"
|
7
|
+
s.authors = ["Alban Peignier"]
|
8
|
+
s.email = ["alban@tryphon.eu"]
|
9
|
+
s.homepage = "http://projects.tryphon.eu/rsox-command"
|
10
|
+
s.summary = %q{Wrapper to run sox}
|
11
|
+
s.description = %q{Ruby wrapper to run SoX, a sound command line utility}
|
12
|
+
|
13
|
+
s.rubyforge_project = "rsox-command"
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
|
20
|
+
# specify any dependencies here; for example:
|
21
|
+
s.add_development_dependency "rspec"
|
22
|
+
s.add_development_dependency "guard"
|
23
|
+
s.add_development_dependency "guard-rspec"
|
24
|
+
s.add_development_dependency "rake"
|
25
|
+
|
26
|
+
s.add_runtime_dependency "activesupport"
|
27
|
+
s.add_runtime_dependency "cocaine"
|
28
|
+
end
|
Binary file
|
@@ -0,0 +1,16 @@
|
|
1
|
+
Overall Left Right
|
2
|
+
DC offset 0.000010 0.000010 0.000010
|
3
|
+
Min level -1.000000 -1.000000 -1.000000
|
4
|
+
Max level 0.999969 0.999969 0.999969
|
5
|
+
Pk lev dB 0.00 0.00 0.00
|
6
|
+
RMS lev dB -2.98 -2.98 -2.98
|
7
|
+
RMS Pk dB -2.91 -2.92 -2.91
|
8
|
+
RMS Tr dB -3.06 -3.06 -3.06
|
9
|
+
Crest factor - 1.41 1.41
|
10
|
+
Flat factor 6.70 6.69 6.70
|
11
|
+
Pk count 37.8k 37.8k 37.8k
|
12
|
+
Bit-depth 16/16 16/16 16/16
|
13
|
+
Num samples 664k
|
14
|
+
Length s 15.050
|
15
|
+
Scale max 1.000000
|
16
|
+
Window s 0.050
|
@@ -0,0 +1,288 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Sox, "command" do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@command = mock(Sox::Command, :run => true)
|
7
|
+
Sox::Command.stub!(:new).and_return(@command)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should create a new Sox::Command" do
|
11
|
+
Sox::Command.should_receive(:new).and_return(@command)
|
12
|
+
Sox.command {}
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should yield the created Sox::Command" do
|
16
|
+
Sox.command { |sox| sox.should == @command }
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should run the Sox::Command" do
|
20
|
+
@command.should_receive(:run).and_return(true)
|
21
|
+
Sox.command {}.should be_true
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
describe Sox::Command do
|
27
|
+
|
28
|
+
it {
|
29
|
+
Sox::Command.new do |sox|
|
30
|
+
sox.input "input1.wav"
|
31
|
+
sox.input "input2", :type => "ogg"
|
32
|
+
|
33
|
+
sox.output "output", :type => "ogg", :compression => 8
|
34
|
+
end.command_line.command.should == "sox input1.wav --type ogg input2 --compression 8 --type ogg output 2>&1"
|
35
|
+
}
|
36
|
+
|
37
|
+
before(:each) do
|
38
|
+
@command = Sox::Command.new
|
39
|
+
|
40
|
+
@filename = "filename"
|
41
|
+
@options = { :option1 => "value1" }
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "input" do
|
45
|
+
|
46
|
+
it "should create a File with specified arguments and adds it in command inputs" do
|
47
|
+
@command.input @filename, @options
|
48
|
+
@command.inputs.should == [ Sox::Command::File.new(@filename, @options) ]
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "output" do
|
54
|
+
|
55
|
+
it "should create a File with specified arguments and adds it in command output" do
|
56
|
+
@command.output @filename, @options
|
57
|
+
@command.output.should == Sox::Command::File.new(@filename, @options)
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "effect" do
|
63
|
+
|
64
|
+
before(:each) do
|
65
|
+
@arguments = Array.new(3) { |n| "argument#{n}" }
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should create an Effect with specified argument and adds it in command effects" do
|
69
|
+
@command.effect :effect_name, @arguments
|
70
|
+
@command.effects.should == [ Sox::Command::Effect.new(:effect_name, @arguments) ]
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "command_arguments" do
|
76
|
+
|
77
|
+
def mock_file(command_arguments)
|
78
|
+
mock(Sox::Command::File, :command_arguments => command_arguments, :options => {}, :filename => "dummy")
|
79
|
+
end
|
80
|
+
|
81
|
+
def mock_effect(command_arguments)
|
82
|
+
mock(Sox::Command::Effect, :command_arguments => command_arguments)
|
83
|
+
end
|
84
|
+
|
85
|
+
before(:each) do
|
86
|
+
@command.inputs = Array.new(3) { |n| mock_file "input#{n}" }
|
87
|
+
@command.output = mock_file("output")
|
88
|
+
@command.effects = Array.new(3) { |n| mock_effect "effect#{n}" }
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should concat inputs, output and effects command arguments" do
|
92
|
+
@command.command_arguments.should == "input0 input1 input2 output effect0 : effect1 : effect2"
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should support null file in input" do
|
96
|
+
@command.inputs = []
|
97
|
+
@command.command_arguments.should match(/^-n output/)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should support null file in output" do
|
101
|
+
@command.output = nil
|
102
|
+
@command.command_arguments.should match(/^input0 input1 input2 -n/)
|
103
|
+
end
|
104
|
+
|
105
|
+
context "when playlist is useful " do
|
106
|
+
before(:each) do
|
107
|
+
@command.playlist.stub :useful? => true
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should concat playlist path, output and effects command arguments" do
|
111
|
+
@command.command_arguments.should == "#{@command.playlist.path} output effect0 : effect1 : effect2"
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should create playlist if needed" do
|
115
|
+
@command.playlist.should_receive(:create)
|
116
|
+
@command.command_arguments
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
describe "command_line" do
|
123
|
+
|
124
|
+
it "should concat sox binary path and command_arguments" do
|
125
|
+
@command.stub!(:command_arguments).and_return("command_arguments")
|
126
|
+
@command.command_line.command.should == "sox command_arguments 2>&1"
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
|
131
|
+
describe "run!" do
|
132
|
+
|
133
|
+
before(:each) do
|
134
|
+
@command.stub!(:command_line).and_return(mock(:run => "ok"))
|
135
|
+
end
|
136
|
+
|
137
|
+
it "should run the command_line" do
|
138
|
+
@command.command_line.should_receive(:run)
|
139
|
+
@command.run!
|
140
|
+
end
|
141
|
+
|
142
|
+
it "should delete playlist" do
|
143
|
+
@command.playlist.should_receive(:delete)
|
144
|
+
@command.run!
|
145
|
+
end
|
146
|
+
|
147
|
+
it "should not raise error when the command line is successful" do
|
148
|
+
@command.command_line.stub :run => "ok"
|
149
|
+
lambda { @command.run! }.should_not raise_error
|
150
|
+
end
|
151
|
+
|
152
|
+
it "should raise an error if command line fails" do
|
153
|
+
@command.command_line.stub(:run).and_raise(Cocaine::ExitStatusError)
|
154
|
+
lambda { @command.run! }.should raise_error
|
155
|
+
end
|
156
|
+
|
157
|
+
it "should capture sox output" do
|
158
|
+
@command.command_line.stub :run => "ok"
|
159
|
+
@command.run!
|
160
|
+
@command.run_output.should == "ok"
|
161
|
+
end
|
162
|
+
|
163
|
+
it "should return the Command instance" do
|
164
|
+
@command.run!.should == @command
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|
168
|
+
|
169
|
+
describe "run" do
|
170
|
+
|
171
|
+
it "should return false when Cocaine command line fails" do
|
172
|
+
@command.stub(:run!).and_raise(Cocaine::CommandLineError)
|
173
|
+
@command.run.should be_false
|
174
|
+
end
|
175
|
+
|
176
|
+
it "should return true when run! doesn't fail" do
|
177
|
+
@command.stub :run! => true
|
178
|
+
@command.run.should be_true
|
179
|
+
end
|
180
|
+
|
181
|
+
end
|
182
|
+
|
183
|
+
describe "playlist" do
|
184
|
+
|
185
|
+
it "should have .m3u extension (sox requirement)" do
|
186
|
+
@command.playlist.path.should match(/\.m3u$/)
|
187
|
+
end
|
188
|
+
|
189
|
+
after(:each) do
|
190
|
+
@command.playlist.delete
|
191
|
+
end
|
192
|
+
|
193
|
+
end
|
194
|
+
|
195
|
+
describe Sox::Command::File do
|
196
|
+
|
197
|
+
before(:each) do
|
198
|
+
@file = Sox::Command::File.new("test")
|
199
|
+
end
|
200
|
+
|
201
|
+
it "should create command_arguments filename only without options" do
|
202
|
+
@file.filename = "filename"
|
203
|
+
@file.options = {}
|
204
|
+
|
205
|
+
@file.command_arguments.should == "filename"
|
206
|
+
end
|
207
|
+
|
208
|
+
it "should create command_arguments with options and filename (--option1 value1 --option2 value2 ... filename)" do
|
209
|
+
@file.filename = "filename"
|
210
|
+
@file.options = {:option1 => "value1", :option2 => "value2"}
|
211
|
+
|
212
|
+
@file.command_arguments.should == "--option1 value1 --option2 value2 filename"
|
213
|
+
end
|
214
|
+
|
215
|
+
end
|
216
|
+
|
217
|
+
describe Sox::Command::Effect do
|
218
|
+
|
219
|
+
before(:each) do
|
220
|
+
@effect = Sox::Command::Effect.new("test")
|
221
|
+
end
|
222
|
+
|
223
|
+
it "should create command_arguments with name and arguments" do
|
224
|
+
@effect.name = "name"
|
225
|
+
@effect.arguments = ["argument1", "argument2"]
|
226
|
+
|
227
|
+
@effect.command_arguments.should == "name argument1 argument2"
|
228
|
+
end
|
229
|
+
|
230
|
+
end
|
231
|
+
|
232
|
+
describe Sox::Command::Playlist do
|
233
|
+
|
234
|
+
def mock_file(name, options = {})
|
235
|
+
mock Sox::Command::File, :filename => name, :options => options
|
236
|
+
end
|
237
|
+
|
238
|
+
subject { Sox::Command::Playlist.new [mock_file("input")] }
|
239
|
+
|
240
|
+
describe "create" do
|
241
|
+
|
242
|
+
it "should create a playlist file with input files" do
|
243
|
+
subject.stub :inputs => [mock_file("input1"), mock_file("input2")]
|
244
|
+
IO.read(subject.create).should == "input1\ninput2\n"
|
245
|
+
end
|
246
|
+
|
247
|
+
after(:each) do
|
248
|
+
subject.delete
|
249
|
+
end
|
250
|
+
|
251
|
+
end
|
252
|
+
|
253
|
+
describe "delete" do
|
254
|
+
|
255
|
+
it "should close playlist if exists" do
|
256
|
+
subject.instance_variable_set("@file", file = mock)
|
257
|
+
file.should_receive(:close).with(true)
|
258
|
+
subject.delete
|
259
|
+
end
|
260
|
+
|
261
|
+
it "should do nothing when file doesn't exist'" do
|
262
|
+
lambda { subject.delete }.should_not raise_error
|
263
|
+
end
|
264
|
+
|
265
|
+
end
|
266
|
+
|
267
|
+
describe "useful? " do
|
268
|
+
|
269
|
+
it "should be useful if concatenated filenames are longer than 500 characters" do
|
270
|
+
subject.stub :inputs => Array.new(51) { mock_file("a" * 10) }
|
271
|
+
subject.should be_useful
|
272
|
+
end
|
273
|
+
|
274
|
+
it "should not be useful if one of the input file has an option" do
|
275
|
+
subject.stub :inputs => [ mock_file("dummy", :option => true) ]
|
276
|
+
subject.should_not be_useful
|
277
|
+
end
|
278
|
+
|
279
|
+
it "should not be useful if concatenated filenames use less than 500 characters" do
|
280
|
+
subject.stub :inputs => Array.new(50) { mock_file("a" * 10) }
|
281
|
+
subject.should_not be_useful
|
282
|
+
end
|
283
|
+
|
284
|
+
end
|
285
|
+
|
286
|
+
end
|
287
|
+
|
288
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Sox::Stats do
|
4
|
+
|
5
|
+
subject { Sox::Stats.new }
|
6
|
+
|
7
|
+
describe "#raw_output" do
|
8
|
+
|
9
|
+
it "should return sox command output" do
|
10
|
+
subject.input("spec/fixtures/test.ogg")
|
11
|
+
subject.raw_output.should == IO.read("spec/fixtures/test.stats")
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#attributes" do
|
17
|
+
|
18
|
+
it "should read name and first value from raw output" do
|
19
|
+
subject.stub :raw_output => "A key in dB -3"
|
20
|
+
subject.attributes["A key in dB"].should == -3
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should read standard sox output" do
|
24
|
+
subject.stub :raw_output => IO.read("spec/fixtures/test.stats")
|
25
|
+
subject.attributes.should == {
|
26
|
+
"DC offset" => 0.000010,
|
27
|
+
"Min level" => -1.0,
|
28
|
+
"Max level" => 0.999969,
|
29
|
+
"Pk lev dB" => 0.0,
|
30
|
+
"RMS lev dB" => -2.98,
|
31
|
+
"RMS Pk dB" => -2.91,
|
32
|
+
"RMS Tr dB" => -3.06,
|
33
|
+
"Crest factor" => "-",
|
34
|
+
"Flat factor" => 6.70,
|
35
|
+
"Pk count" => "37.8k",
|
36
|
+
# "Bit-depth" => "16/16",
|
37
|
+
"Num samples" => "664k",
|
38
|
+
"Length s" => 15.050,
|
39
|
+
"Scale max" => 1.0,
|
40
|
+
"Window s" => 0.050
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "rms_level" do
|
47
|
+
|
48
|
+
it "should return 'RMS lev dB' found by sox" do
|
49
|
+
subject.stub :attributes => { 'RMS lev dB' => -3.0 }
|
50
|
+
subject.rms_level.should == -3.0
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,168 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rsox-command
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Alban Peignier
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2012-04-18 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
prerelease: false
|
22
|
+
type: :development
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 3
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
version: "0"
|
32
|
+
name: rspec
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
prerelease: false
|
36
|
+
type: :development
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
none: false
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
hash: 3
|
43
|
+
segments:
|
44
|
+
- 0
|
45
|
+
version: "0"
|
46
|
+
name: guard
|
47
|
+
version_requirements: *id002
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
prerelease: false
|
50
|
+
type: :development
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
hash: 3
|
57
|
+
segments:
|
58
|
+
- 0
|
59
|
+
version: "0"
|
60
|
+
name: guard-rspec
|
61
|
+
version_requirements: *id003
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
prerelease: false
|
64
|
+
type: :development
|
65
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
hash: 3
|
71
|
+
segments:
|
72
|
+
- 0
|
73
|
+
version: "0"
|
74
|
+
name: rake
|
75
|
+
version_requirements: *id004
|
76
|
+
- !ruby/object:Gem::Dependency
|
77
|
+
prerelease: false
|
78
|
+
type: :runtime
|
79
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
80
|
+
none: false
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
hash: 3
|
85
|
+
segments:
|
86
|
+
- 0
|
87
|
+
version: "0"
|
88
|
+
name: activesupport
|
89
|
+
version_requirements: *id005
|
90
|
+
- !ruby/object:Gem::Dependency
|
91
|
+
prerelease: false
|
92
|
+
type: :runtime
|
93
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ">="
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
hash: 3
|
99
|
+
segments:
|
100
|
+
- 0
|
101
|
+
version: "0"
|
102
|
+
name: cocaine
|
103
|
+
version_requirements: *id006
|
104
|
+
description: Ruby wrapper to run SoX, a sound command line utility
|
105
|
+
email:
|
106
|
+
- alban@tryphon.eu
|
107
|
+
executables:
|
108
|
+
- silent-file
|
109
|
+
- silent-files
|
110
|
+
extensions: []
|
111
|
+
|
112
|
+
extra_rdoc_files: []
|
113
|
+
|
114
|
+
files:
|
115
|
+
- .gitignore
|
116
|
+
- Gemfile
|
117
|
+
- Guardfile
|
118
|
+
- Rakefile
|
119
|
+
- bin/silent-file
|
120
|
+
- bin/silent-files
|
121
|
+
- lib/rsox-command.rb
|
122
|
+
- lib/sox/command.rb
|
123
|
+
- lib/sox/stats.rb
|
124
|
+
- rsox-command.gemspec
|
125
|
+
- spec/fixtures/test.ogg
|
126
|
+
- spec/fixtures/test.stats
|
127
|
+
- spec/lib/sox/command_spec.rb
|
128
|
+
- spec/lib/sox/stats_spec.rb
|
129
|
+
- spec/spec_helper.rb
|
130
|
+
homepage: http://projects.tryphon.eu/rsox-command
|
131
|
+
licenses: []
|
132
|
+
|
133
|
+
post_install_message:
|
134
|
+
rdoc_options: []
|
135
|
+
|
136
|
+
require_paths:
|
137
|
+
- lib
|
138
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
139
|
+
none: false
|
140
|
+
requirements:
|
141
|
+
- - ">="
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
hash: 3
|
144
|
+
segments:
|
145
|
+
- 0
|
146
|
+
version: "0"
|
147
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
148
|
+
none: false
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
hash: 3
|
153
|
+
segments:
|
154
|
+
- 0
|
155
|
+
version: "0"
|
156
|
+
requirements: []
|
157
|
+
|
158
|
+
rubyforge_project: rsox-command
|
159
|
+
rubygems_version: 1.8.15
|
160
|
+
signing_key:
|
161
|
+
specification_version: 3
|
162
|
+
summary: Wrapper to run sox
|
163
|
+
test_files:
|
164
|
+
- spec/fixtures/test.ogg
|
165
|
+
- spec/fixtures/test.stats
|
166
|
+
- spec/lib/sox/command_spec.rb
|
167
|
+
- spec/lib/sox/stats_spec.rb
|
168
|
+
- spec/spec_helper.rb
|