MusicMaster 0.0.1.20101110 → 1.0.0.20120307
Sign up to get free protection for your applications and to get access to all the features.
- data/AUTHORS +4 -1
- data/ChangeLog +28 -0
- data/LICENSE +1 -1
- data/README +2 -5
- data/ReleaseInfo +8 -8
- data/bin/Calibrate.rb +55 -0
- data/bin/Clean.rb +55 -0
- data/bin/DBConvert.rb +3 -1
- data/bin/Deliver.rb +73 -42
- data/bin/Mix.rb +39 -78
- data/bin/Process.rb +55 -0
- data/bin/Record.rb +63 -116
- data/bin/{Album.rb → old/Album.rb} +18 -18
- data/bin/{AnalyzeAlbum.rb → old/AnalyzeAlbum.rb} +11 -11
- data/bin/{DeliverAlbum.rb → old/DeliverAlbum.rb} +12 -12
- data/bin/{Fct2Wave.rb → old/Fct2Wave.rb} +11 -11
- data/{album.conf.rb.example → bin/old/album.conf.rb.example} +0 -0
- data/lib/MusicMaster/FilesNamer.rb +253 -0
- data/lib/MusicMaster/Formats/MP3.rb +50 -0
- data/lib/MusicMaster/Formats/Test.rb +44 -0
- data/lib/MusicMaster/Formats/Wave.rb +80 -0
- data/lib/MusicMaster/Hash.rb +20 -0
- data/lib/MusicMaster/Launcher.rb +241 -0
- data/lib/MusicMaster/Processes/ApplyVolumeFct.rb +4 -8
- data/lib/MusicMaster/Processes/Compressor.rb +50 -47
- data/lib/MusicMaster/Processes/Custom.rb +3 -3
- data/lib/MusicMaster/Processes/{AddSilence.rb → Cut.rb} +8 -4
- data/lib/MusicMaster/Processes/CutFirstSignal.rb +6 -3
- data/lib/MusicMaster/Processes/DCShifter.rb +30 -0
- data/lib/MusicMaster/Processes/GVerb.rb +3 -2
- data/lib/MusicMaster/Processes/Normalize.rb +7 -6
- data/lib/MusicMaster/Processes/SilenceInserter.rb +31 -0
- data/lib/MusicMaster/Processes/Test.rb +39 -0
- data/lib/MusicMaster/Processes/VolCorrection.rb +3 -3
- data/lib/MusicMaster/RakeProcesses.rb +1014 -0
- data/lib/MusicMaster/Symbol.rb +12 -0
- data/lib/MusicMaster/Task.rb +29 -0
- data/lib/MusicMaster/Utils.rb +467 -0
- data/lib/MusicMaster/old/Common.rb +101 -0
- data/musicmaster.conf.rb.example +42 -59
- data/record.conf.rb.example +374 -30
- metadata +91 -41
- data/TODO +0 -3
- data/bin/Master.rb +0 -60
- data/bin/PrepareMix.rb +0 -422
- data/lib/MusicMaster/Common.rb +0 -197
- data/lib/MusicMaster/ConfLoader.rb +0 -56
- data/lib/MusicMaster/musicmaster.conf.rb +0 -96
- data/master.conf.rb.example +0 -13
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c) 2009-
|
2
|
+
# Copyright (c) 2009 - 2012 Muriel Salvan (muriel@x-aeon.com)
|
3
3
|
# Licensed under the terms specified in LICENSE file. No warranty is provided.
|
4
4
|
#++
|
5
5
|
|
@@ -21,7 +21,7 @@ module MusicMaster
|
|
21
21
|
|
22
22
|
# Execute the process
|
23
23
|
#
|
24
|
-
# Parameters
|
24
|
+
# Parameters::
|
25
25
|
# * *iInputFileName* (_String_): File name we want to apply effects to
|
26
26
|
# * *iOutputFileName* (_String_): File name to write
|
27
27
|
# * *iTempDir* (_String_): Temporary directory that can be used
|
@@ -31,12 +31,8 @@ module MusicMaster
|
|
31
31
|
lFunctionFile = "#{iTempDir}/#{File.basename(iInputFileName)[0..-5]}.fct.rb"
|
32
32
|
lFunction = WSK::Functions::Function.new
|
33
33
|
lFunction.set(iParams[:Function])
|
34
|
-
lFunction.
|
35
|
-
|
36
|
-
if (iParams[:DBUnits])
|
37
|
-
lStrUnitDB = '1'
|
38
|
-
end
|
39
|
-
MusicMaster::wsk(iInputFileName, iOutputFileName, 'ApplyVolumeFct', "--function \"#{lFunctionFile}\" --begin \"#{iParams[:Begin]}\" --end \"#{iParams[:End]}\" --unitdb #{lStrUnitDB}")
|
34
|
+
lFunction.write_to_file(lFunctionFile)
|
35
|
+
wsk(iInputFileName, iOutputFileName, 'ApplyVolumeFct', "--function \"#{lFunctionFile}\" --begin \"#{iParams[:Begin]}\" --end \"#{iParams[:End]}\" --unitdb #{(iParams[:DBUnits]) ? '1' : '0'}")
|
40
36
|
end
|
41
37
|
|
42
38
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c) 2009-
|
2
|
+
# Copyright (c) 2009 - 2012 Muriel Salvan (muriel@x-aeon.com)
|
3
3
|
# Licensed under the terms specified in LICENSE file. No warranty is provided.
|
4
4
|
#++
|
5
5
|
|
@@ -16,10 +16,10 @@ module MusicMaster
|
|
16
16
|
# * *:Threshold* (_Float_): The threshold below which there is no compression (in DB if :DBUnit is true, else in a [0..1] scale)
|
17
17
|
# * *:Ratio* (_Float_): Compression ratio to apply above threshold.
|
18
18
|
# * *:AttackDuration* (_String_): The attack duration (either in seconds or in samples)
|
19
|
-
# * *:AttackDamping* (
|
19
|
+
# * *:AttackDamping* (_Float_): The attack damping value in the duration previously defined (in DB if :DBUnit is true, else in a [0..1] scale). The compressor will never attack more than :AttackDamping values during a duration of :AttackDuration.
|
20
20
|
# * *:AttackLookAhead* (_Boolean_): Is the attack to be forecast before it happens ?
|
21
21
|
# * *:ReleaseDuration* (_String_): The release duration (either in seconds or in samples)
|
22
|
-
# * *:ReleaseDamping* (
|
22
|
+
# * *:ReleaseDamping* (_Float_): The release damping value in the duration previously defined (in DB if :DBUnit is true, else in a [0..1] scale). The compressor will never release more than :ReleaseDamping values during a duration of :ReleaseDuration.
|
23
23
|
# * *:ReleaseLookAhead* (_Boolean_): Is the attack to be forecast before it happens ?
|
24
24
|
# * *:MinChangeDuration* (_String_): The minimal duration a change in volume should have (either in seconds or in samples)
|
25
25
|
# * *:RMSRatio* (_Float_): Ratio of RMS vs Peak level measurement used when profiling Wave files volumes. 0.0 = Use only Peak level. 1.0 = Use only RMS level. Other values in-between will produce a mix of both.
|
@@ -29,9 +29,12 @@ module MusicMaster
|
|
29
29
|
# -Infinity
|
30
30
|
MINUS_INFINITY = -1.0/0.0
|
31
31
|
|
32
|
+
# Interval used to profile the volume
|
33
|
+
PROFILEVOLUME_INTERVAL = '0.1s'
|
34
|
+
|
32
35
|
# Execute the process
|
33
36
|
#
|
34
|
-
# Parameters
|
37
|
+
# Parameters::
|
35
38
|
# * *iInputFileName* (_String_): File name we want to apply effects to
|
36
39
|
# * *iOutputFileName* (_String_): File name to write
|
37
40
|
# * *iTempDir* (_String_): Temporary directory that can be used
|
@@ -46,35 +49,35 @@ module MusicMaster
|
|
46
49
|
if (lDBUnits)
|
47
50
|
# Threshold must be < 0
|
48
51
|
if (iParams[:Threshold] >= 0)
|
49
|
-
|
52
|
+
log_err "Threshold (#{iParams[:Threshold]}db) has to be < 0db"
|
50
53
|
lParamsOK = false
|
51
54
|
end
|
52
55
|
else
|
53
56
|
# Threshold must be < 1
|
54
57
|
if (iParams[:Threshold] >= 1)
|
55
|
-
|
58
|
+
log_err "Threshold (#{iParams[:Threshold]}) has to be < 1"
|
56
59
|
lParamsOK = false
|
57
60
|
end
|
58
61
|
# Threshold must be > 0
|
59
62
|
if (iParams[:Threshold] <= 0)
|
60
|
-
|
63
|
+
log_err "Threshold (#{iParams[:Threshold]}) has to be > 0"
|
61
64
|
lParamsOK = false
|
62
65
|
end
|
63
66
|
end
|
64
67
|
# Ratio must be > 1
|
65
68
|
if (iParams[:Ratio] <= 1)
|
66
|
-
|
69
|
+
log_err "Ratio (#{iParams[:Ratio]}) has to be > 1"
|
67
70
|
lParamsOK = false
|
68
71
|
end
|
69
72
|
if (lParamsOK)
|
70
73
|
# Get the volume profile of the Wave file
|
71
74
|
lTempVolProfileFile = "#{iTempDir}/#{File.basename(iInputFileName)[0..-5]}.ProfileFct.rb"
|
72
75
|
if (File.exists?(lTempVolProfileFile))
|
73
|
-
|
76
|
+
log_warn "File #{lTempVolProfileFile} already exists. Will not overwrite it."
|
74
77
|
else
|
75
78
|
lTempWaveFile = "#{iTempDir}/Dummy.wav"
|
76
79
|
# Get the volume profile
|
77
|
-
|
80
|
+
wsk(iInputFileName, lTempWaveFile, 'VolumeProfile', "--function \"#{lTempVolProfileFile}\" --begin 0 --end -1 --interval \"#{PROFILEVOLUME_INTERVAL}\" --rmsratio #{iParams[:RMSRatio]}")
|
78
81
|
File::unlink(lTempWaveFile)
|
79
82
|
end
|
80
83
|
|
@@ -83,7 +86,7 @@ module MusicMaster
|
|
83
86
|
File.open(iInputFileName, 'rb') do |iFile|
|
84
87
|
lError, lHeader = readHeader(iFile)
|
85
88
|
if (lError != nil)
|
86
|
-
|
89
|
+
log_err "An error occurred while reading header: #{lError}"
|
87
90
|
end
|
88
91
|
end
|
89
92
|
|
@@ -92,16 +95,16 @@ module MusicMaster
|
|
92
95
|
# This value will be used to replace -Infinity
|
93
96
|
lMinimalDBValue = nil
|
94
97
|
lCompressorFunction = WSK::Functions::Function.new
|
95
|
-
lBDThreshold =
|
98
|
+
lBDThreshold = iParams[:Threshold].to_r
|
96
99
|
if (lDBUnits)
|
97
100
|
# The minimal DB value is the smallest ratio possible for RMS values of this file (1/2^(BPS-1)) converted in DB and minus 1 to not mix it with the ratio 1/2^(BPS-1)
|
98
|
-
lMinimalDBValue = lCompressorFunction.
|
101
|
+
lMinimalDBValue = lCompressorFunction.value_val_2_db(Rational(1), Rational(2)**(lHeader.NbrBitsPerSample-1)) - 1
|
99
102
|
lCompressorFunction.set( {
|
100
103
|
:FunctionType => WSK::Functions::FCTTYPE_PIECEWISE_LINEAR,
|
101
104
|
:Points => [
|
102
105
|
[lMinimalDBValue, lMinimalDBValue],
|
103
106
|
[lBDThreshold, lBDThreshold],
|
104
|
-
[0, lBDThreshold - lBDThreshold/
|
107
|
+
[0, lBDThreshold - lBDThreshold/(iParams[:Ratio].to_r) ]
|
105
108
|
]
|
106
109
|
} )
|
107
110
|
else
|
@@ -110,26 +113,26 @@ module MusicMaster
|
|
110
113
|
:Points => [
|
111
114
|
[0, 0],
|
112
115
|
[lBDThreshold, lBDThreshold],
|
113
|
-
[1, lBDThreshold + (1-lBDThreshold)/
|
116
|
+
[1, lBDThreshold + (1-lBDThreshold)/(iParams[:Ratio].to_r) ]
|
114
117
|
]
|
115
118
|
} )
|
116
119
|
end
|
117
|
-
|
120
|
+
log_info "Compressor transfer function: #{lCompressorFunction.function_data[:Points].map{ |p| next [ sprintf('%.2f', p[0]), sprintf('%.2f', p[1]) ] }.inspect}"
|
118
121
|
|
119
122
|
# Compute the volume transformation function based on the profile function and the Compressor's parameters
|
120
123
|
lTempVolTransformFile = "#{iTempDir}/#{File.basename(iInputFileName)[0..-5]}.VolumeFct.rb"
|
121
124
|
if (File.exists?(lTempVolTransformFile))
|
122
|
-
|
125
|
+
log_warn "File #{lTempVolTransformFile} already exists. Will not overwrite it."
|
123
126
|
else
|
124
127
|
# Read the Profile function
|
125
|
-
|
128
|
+
log_info 'Create volume profile function ...'
|
126
129
|
lProfileFunction = WSK::Functions::Function.new
|
127
|
-
lProfileFunction.
|
130
|
+
lProfileFunction.read_from_file(lTempVolProfileFile)
|
128
131
|
if (lDBUnits)
|
129
132
|
# Convert the Profile function in DB units
|
130
|
-
lProfileFunction.
|
133
|
+
lProfileFunction.convert_to_db(Rational(1))
|
131
134
|
# Replace -Infinity with lMinimalDBValue
|
132
|
-
lProfileFunction.
|
135
|
+
lProfileFunction.function_data[:Points].each do |ioPoint|
|
133
136
|
if (ioPoint[1] == MINUS_INFINITY)
|
134
137
|
ioPoint[1] = lMinimalDBValue
|
135
138
|
end
|
@@ -140,30 +143,30 @@ module MusicMaster
|
|
140
143
|
|
141
144
|
# Clone the profile function before applying the map
|
142
145
|
lNewProfileFunction = WSK::Functions::Function.new
|
143
|
-
lNewProfileFunction.set(lProfileFunction.
|
146
|
+
lNewProfileFunction.set(lProfileFunction.function_data.clone)
|
144
147
|
|
145
148
|
# Transform the Profile function with the Compressor function
|
146
|
-
|
147
|
-
lNewProfileFunction.
|
149
|
+
log_info 'Apply compressor transfer function ...'
|
150
|
+
lNewProfileFunction.apply_map_function(lCompressorFunction)
|
148
151
|
|
149
152
|
#dumpDebugFct(iInputFileName, lNewProfileFunction, 'NewProfileDB', lDBUnits, iTempDir)
|
150
153
|
|
151
154
|
# The difference of the functions will give the volume transformation profile
|
152
|
-
|
155
|
+
log_info 'Compute differing function ...'
|
153
156
|
lDiffProfileFunction = WSK::Functions::Function.new
|
154
|
-
lDiffProfileFunction.set(lNewProfileFunction.
|
157
|
+
lDiffProfileFunction.set(lNewProfileFunction.function_data.clone)
|
155
158
|
if (lDBUnits)
|
156
159
|
# The volume transformation will be a DB difference
|
157
|
-
lDiffProfileFunction.
|
160
|
+
lDiffProfileFunction.substract_function(lProfileFunction)
|
158
161
|
else
|
159
162
|
# The volume transformation will be a ratio
|
160
|
-
lDiffProfileFunction.
|
163
|
+
lDiffProfileFunction.divide_by_function(lProfileFunction)
|
161
164
|
end
|
162
165
|
|
163
|
-
|
166
|
+
dumpDebugFct(iInputFileName, lDiffProfileFunction, 'RawDiffProfileDB', lDBUnits, iTempDir)
|
164
167
|
|
165
168
|
# Apply damping for attack and release times
|
166
|
-
|
169
|
+
log_info 'Damp differing function with attack and release ...'
|
167
170
|
lAttackDuration = Rational(readDuration(iParams[:AttackDuration], lHeader.SampleRate))
|
168
171
|
lAttackSlope = iParams[:AttackDamping].to_f.to_r/lAttackDuration
|
169
172
|
lReleaseDuration = Rational(readDuration(iParams[:ReleaseDuration], lHeader.SampleRate))
|
@@ -176,26 +179,26 @@ module MusicMaster
|
|
176
179
|
if ((iParams[:AttackLookAhead] == true) or
|
177
180
|
(iParams[:ReleaseLookAhead] == true))
|
178
181
|
# Look-Aheads are implemented by applying damping on the reverted function
|
179
|
-
lDiffProfileFunction.
|
182
|
+
lDiffProfileFunction.invert_abscisses
|
180
183
|
if (iParams[:AttackLookAhead] == false)
|
181
|
-
lDiffProfileFunction.
|
184
|
+
lDiffProfileFunction.apply_damping(nil, -lReleaseSlope)
|
182
185
|
elsif (iParams[:ReleaseLookAhead] == false)
|
183
|
-
lDiffProfileFunction.
|
186
|
+
lDiffProfileFunction.apply_damping(lAttackSlope, nil)
|
184
187
|
else
|
185
|
-
lDiffProfileFunction.
|
188
|
+
lDiffProfileFunction.apply_damping(lAttackSlope, -lReleaseSlope)
|
186
189
|
end
|
187
|
-
lDiffProfileFunction.
|
190
|
+
lDiffProfileFunction.invert_abscisses
|
188
191
|
end
|
189
192
|
if (iParams[:AttackLookAhead] == true)
|
190
193
|
if (iParams[:ReleaseLookAhead] == false)
|
191
|
-
lDiffProfileFunction.
|
194
|
+
lDiffProfileFunction.apply_damping(lReleaseSlope, nil)
|
192
195
|
end
|
193
196
|
elsif (iParams[:ReleaseLookAhead] == true)
|
194
197
|
if (iParams[:AttackLookAhead] == false)
|
195
|
-
lDiffProfileFunction.
|
198
|
+
lDiffProfileFunction.apply_damping(nil, -lAttackSlope)
|
196
199
|
end
|
197
200
|
else
|
198
|
-
lDiffProfileFunction.
|
201
|
+
lDiffProfileFunction.apply_damping(lReleaseSlope, -lAttackSlope)
|
199
202
|
end
|
200
203
|
|
201
204
|
#dumpDebugFct(iInputFileName, lDiffProfileFunction, 'DampedDiffProfileDB', lDBUnits, iTempDir)
|
@@ -203,13 +206,13 @@ module MusicMaster
|
|
203
206
|
# Eliminate glitches in the function.
|
204
207
|
# This is done by deleting intermediate abscisses that are too close to each other
|
205
208
|
|
206
|
-
|
207
|
-
lDiffProfileFunction.
|
209
|
+
log_info 'Smooth differing function ...'
|
210
|
+
lDiffProfileFunction.remove_noise_abscisses(Rational(readDuration(iParams[:MinChangeDuration], lHeader.SampleRate)))
|
208
211
|
|
209
|
-
|
212
|
+
dumpDebugFct(iInputFileName, lDiffProfileFunction, 'SmoothedDiffProfileDB', lDBUnits, iTempDir)
|
210
213
|
|
211
214
|
# Save the volume transformation file
|
212
|
-
lDiffProfileFunction.
|
215
|
+
lDiffProfileFunction.write_to_file(lTempVolTransformFile)
|
213
216
|
end
|
214
217
|
|
215
218
|
# Apply the volume transformation to the Wave file
|
@@ -217,14 +220,14 @@ module MusicMaster
|
|
217
220
|
if (lDBUnits)
|
218
221
|
lStrUnitDB = 1
|
219
222
|
end
|
220
|
-
|
223
|
+
wsk(iInputFileName, iOutputFileName, 'ApplyVolumeFct', "--function \"#{lTempVolTransformFile}\" --begin 0 --end -1 --unitdb #{lStrUnitDB}")
|
221
224
|
end
|
222
225
|
end
|
223
226
|
|
224
227
|
# Dump a function into a Wave file.
|
225
228
|
# This is used for debugging purposes only.
|
226
229
|
#
|
227
|
-
# Parameters
|
230
|
+
# Parameters::
|
228
231
|
# * *iInputFileName* (_String_): Name of the input file
|
229
232
|
# * *iFunction* (<em>WSK::Functions::Function</em>): The function to dump
|
230
233
|
# * *iName* (_String_): Name given to this function
|
@@ -234,9 +237,9 @@ module MusicMaster
|
|
234
237
|
lBaseFileName = File.basename(iInputFileName)[0..-5]
|
235
238
|
# Clone the function to round it first
|
236
239
|
lRoundedFunction = WSK::Functions::Function.new
|
237
|
-
lRoundedFunction.set(iFunction.
|
238
|
-
lRoundedFunction.
|
239
|
-
|
240
|
+
lRoundedFunction.set(iFunction.function_data.clone)
|
241
|
+
lRoundedFunction.write_to_file("#{iTempDir}/_#{lBaseFileName}_#{iName}.fct.rb", :Floats => true)
|
242
|
+
wsk(iInputFileName, "#{iTempDir}/_#{lBaseFileName}_#{iName}.wav", 'DrawFct', "--function \"#{iTempDir}/_#{lBaseFileName}_#{iName}.fct.rb\" --unitdb #{iDBUnits ? '1' : '0'}")
|
240
243
|
end
|
241
244
|
|
242
245
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c) 2009-
|
2
|
+
# Copyright (c) 2009 - 2012 Muriel Salvan (muriel@x-aeon.com)
|
3
3
|
# Licensed under the terms specified in LICENSE file. No warranty is provided.
|
4
4
|
#++
|
5
5
|
|
@@ -11,13 +11,13 @@ module MusicMaster
|
|
11
11
|
|
12
12
|
# Execute the process
|
13
13
|
#
|
14
|
-
# Parameters
|
14
|
+
# Parameters::
|
15
15
|
# * *iInputFileName* (_String_): File name we want to apply effects to
|
16
16
|
# * *iOutputFileName* (_String_): File name to write
|
17
17
|
# * *iTempDir* (_String_): Temporary directory that can be used
|
18
18
|
# * *iParams* (<em>map<Symbol,Object></em>): Parameters
|
19
19
|
def execute(iInputFileName, iOutputFileName, iTempDir, iParams)
|
20
|
-
|
20
|
+
log_info "Copying #{iInputFileName} => #{iOutputFileName} to apply custom process ..."
|
21
21
|
FileUtils::cp(iInputFileName, iOutputFileName)
|
22
22
|
puts "Apply custom process on file #{iOutputFileName}. Parameters: #{iParams.inspect}"
|
23
23
|
puts 'Press Enter when done ...'
|
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c) 2009-
|
2
|
+
# Copyright (c) 2009 - 2012 Muriel Salvan (muriel@x-aeon.com)
|
3
3
|
# Licensed under the terms specified in LICENSE file. No warranty is provided.
|
4
4
|
#++
|
5
5
|
|
@@ -7,17 +7,21 @@ module MusicMaster
|
|
7
7
|
|
8
8
|
module Processes
|
9
9
|
|
10
|
-
class
|
10
|
+
class Cut
|
11
|
+
|
12
|
+
# Parameters of this process:
|
13
|
+
# * *:Begin* (_String_): The begin marker (either in seconds or in samples)
|
14
|
+
# * *:End* (_String_): The end marker (either in seconds or in samples)
|
11
15
|
|
12
16
|
# Execute the process
|
13
17
|
#
|
14
|
-
# Parameters
|
18
|
+
# Parameters::
|
15
19
|
# * *iInputFileName* (_String_): File name we want to apply effects to
|
16
20
|
# * *iOutputFileName* (_String_): File name to write
|
17
21
|
# * *iTempDir* (_String_): Temporary directory that can be used
|
18
22
|
# * *iParams* (<em>map<Symbol,Object></em>): Parameters
|
19
23
|
def execute(iInputFileName, iOutputFileName, iTempDir, iParams)
|
20
|
-
|
24
|
+
wsk(iInputFileName, iOutputFileName, 'Cut', "--begin #{iParams[:Begin]} --end #{iParams[:End]}")
|
21
25
|
end
|
22
26
|
|
23
27
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c) 2009-
|
2
|
+
# Copyright (c) 2009 - 2012 Muriel Salvan (muriel@x-aeon.com)
|
3
3
|
# Licensed under the terms specified in LICENSE file. No warranty is provided.
|
4
4
|
#++
|
5
5
|
|
@@ -9,15 +9,18 @@ module MusicMaster
|
|
9
9
|
|
10
10
|
class CutFirstSignal
|
11
11
|
|
12
|
+
# Parameters of this process:
|
13
|
+
# * *:SilenceMin* (_String_): The minimal duration a silent part must have to be considered as splitting the first non-silent signal from the rest of the audio (either in seconds or in samples)
|
14
|
+
|
12
15
|
# Execute the process
|
13
16
|
#
|
14
|
-
# Parameters
|
17
|
+
# Parameters::
|
15
18
|
# * *iInputFileName* (_String_): File name we want to apply effects to
|
16
19
|
# * *iOutputFileName* (_String_): File name to write
|
17
20
|
# * *iTempDir* (_String_): Temporary directory that can be used
|
18
21
|
# * *iParams* (<em>map<Symbol,Object></em>): Parameters
|
19
22
|
def execute(iInputFileName, iOutputFileName, iTempDir, iParams)
|
20
|
-
|
23
|
+
wsk(iInputFileName, iOutputFileName, 'CutFirstSignal', "--silencethreshold 0 --noisefft none --silencemin \"#{iParams[:SilenceMin]}\"")
|
21
24
|
end
|
22
25
|
|
23
26
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2009 - 2012 Muriel Salvan (muriel@x-aeon.com)
|
3
|
+
# Licensed under the terms specified in LICENSE file. No warranty is provided.
|
4
|
+
#++
|
5
|
+
|
6
|
+
module MusicMaster
|
7
|
+
|
8
|
+
module Processes
|
9
|
+
|
10
|
+
class DCShifter
|
11
|
+
|
12
|
+
# Parameters of this process:
|
13
|
+
# * *:Offset* (_Integer_): The DC offset to apply (can be negative). The value's effect depends on the bit depth. A value of 64 in a 8 bits file will shift 50%. A value of 64 in a 16 bits file will shift 0.2%.
|
14
|
+
|
15
|
+
# Execute the process
|
16
|
+
#
|
17
|
+
# Parameters::
|
18
|
+
# * *iInputFileName* (_String_): File name we want to apply effects to
|
19
|
+
# * *iOutputFileName* (_String_): File name to write
|
20
|
+
# * *iTempDir* (_String_): Temporary directory that can be used
|
21
|
+
# * *iParams* (<em>map<Symbol,Object></em>): Parameters
|
22
|
+
def execute(iInputFileName, iOutputFileName, iTempDir, iParams)
|
23
|
+
wsk(iInputFileName, iOutputFileName, 'DCShifter', "--offset \"#{iParams[:Offset]}\"")
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c) 2009-
|
2
|
+
# Copyright (c) 2009 - 2012 Muriel Salvan (muriel@x-aeon.com)
|
3
3
|
# Licensed under the terms specified in LICENSE file. No warranty is provided.
|
4
4
|
#++
|
5
5
|
|
@@ -11,12 +11,13 @@ module MusicMaster
|
|
11
11
|
|
12
12
|
# Execute the process
|
13
13
|
#
|
14
|
-
# Parameters
|
14
|
+
# Parameters::
|
15
15
|
# * *iInputFileName* (_String_): File name we want to apply effects to
|
16
16
|
# * *iOutputFileName* (_String_): File name to write
|
17
17
|
# * *iTempDir* (_String_): Temporary directory that can be used
|
18
18
|
# * *iParams* (<em>map<Symbol,Object></em>): Parameters
|
19
19
|
def execute(iInputFileName, iOutputFileName, iTempDir, iParams)
|
20
|
+
# TODO: Use a real GVerb library, and implement regression too
|
20
21
|
puts "===> Apply GVerb from Audacity to file #{iInputFileName} and write file #{iOutputFileName}"
|
21
22
|
puts "===> Parameters: #{iParams.inspect}"
|
22
23
|
puts 'Press Enter when done.'
|
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c) 2009-
|
2
|
+
# Copyright (c) 2009 - 2012 Muriel Salvan (muriel@x-aeon.com)
|
3
3
|
# Licensed under the terms specified in LICENSE file. No warranty is provided.
|
4
4
|
#++
|
5
5
|
|
@@ -11,18 +11,19 @@ module MusicMaster
|
|
11
11
|
|
12
12
|
# Execute the process
|
13
13
|
#
|
14
|
-
# Parameters
|
14
|
+
# Parameters::
|
15
15
|
# * *iInputFileName* (_String_): File name we want to apply effects to
|
16
16
|
# * *iOutputFileName* (_String_): File name to write
|
17
17
|
# * *iTempDir* (_String_): Temporary directory that can be used
|
18
18
|
# * *iParams* (<em>map<Symbol,Object></em>): Parameters
|
19
19
|
def execute(iInputFileName, iOutputFileName, iTempDir, iParams)
|
20
|
+
require 'rational'
|
20
21
|
# First, analyze
|
21
22
|
lAnalyzeResultFileName = "#{iTempDir}/#{File.basename(iInputFileName)}.analyze"
|
22
23
|
if (File.exists?(lAnalyzeResultFileName))
|
23
|
-
|
24
|
+
log_warn "File #{lAnalyzeResultFileName} already exists. Will not overwrite it."
|
24
25
|
else
|
25
|
-
|
26
|
+
wsk(iInputFileName, "#{iTempDir}/Dummy.wav", 'Analyze')
|
26
27
|
File.unlink("#{iTempDir}/Dummy.wav")
|
27
28
|
FileUtils::mv('analyze.result', lAnalyzeResultFileName)
|
28
29
|
end
|
@@ -40,8 +41,8 @@ module MusicMaster
|
|
40
41
|
if (lCoeffNormalizeMin < lCoeff)
|
41
42
|
lCoeff = lCoeffNormalizeMin
|
42
43
|
end
|
43
|
-
|
44
|
-
|
44
|
+
log_info "Maximal value: #{lMaxDataValue}/#{lMaxPossibleValue}. Minimal value: #{lMinDataValue}/#{lMinPossibleValue}. Volume correction: #{lCoeff}."
|
45
|
+
wsk(iInputFileName, iOutputFileName, 'Multiply', "--coeff \"#{lCoeff.numerator}/#{lCoeff.denominator}\"")
|
45
46
|
end
|
46
47
|
|
47
48
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2009 - 2012 Muriel Salvan (muriel@x-aeon.com)
|
3
|
+
# Licensed under the terms specified in LICENSE file. No warranty is provided.
|
4
|
+
#++
|
5
|
+
|
6
|
+
module MusicMaster
|
7
|
+
|
8
|
+
module Processes
|
9
|
+
|
10
|
+
class SilenceInserter
|
11
|
+
|
12
|
+
# Parameters of this process:
|
13
|
+
# * *:Begin* (_String_): Length of silence to insert in samples or in float seconds (ie. '234' or '25.3s') at the beginning of the file
|
14
|
+
# * *:End* (_String_): Length of silence to insert in samples or in float seconds (ie. '234' or '25.3s') at the end of the file
|
15
|
+
|
16
|
+
# Execute the process
|
17
|
+
#
|
18
|
+
# Parameters::
|
19
|
+
# * *iInputFileName* (_String_): File name we want to apply effects to
|
20
|
+
# * *iOutputFileName* (_String_): File name to write
|
21
|
+
# * *iTempDir* (_String_): Temporary directory that can be used
|
22
|
+
# * *iParams* (<em>map<Symbol,Object></em>): Parameters
|
23
|
+
def execute(iInputFileName, iOutputFileName, iTempDir, iParams)
|
24
|
+
wsk(iInputFileName, iOutputFileName, 'SilenceInserter', "--begin \"#{iParams[:Begin]}\" --end \"#{iParams[:End]}\"")
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2009 - 2012 Muriel Salvan (muriel@x-aeon.com)
|
3
|
+
# Licensed under the terms specified in LICENSE file. No warranty is provided.
|
4
|
+
#++
|
5
|
+
|
6
|
+
module MusicMaster
|
7
|
+
|
8
|
+
module Processes
|
9
|
+
|
10
|
+
class Test
|
11
|
+
|
12
|
+
# Execute the process
|
13
|
+
#
|
14
|
+
# Parameters::
|
15
|
+
# * *iInputFileName* (_String_): File name we want to apply effects to
|
16
|
+
# * *iOutputFileName* (_String_): File name to write
|
17
|
+
# * *iTempDir* (_String_): Temporary directory that can be used
|
18
|
+
# * *iParams* (<em>map<Symbol,Object></em>): Parameters
|
19
|
+
def execute(iInputFileName, iOutputFileName, iTempDir, iParams)
|
20
|
+
log_info "Copying #{iInputFileName} => #{iOutputFileName} for testing purposes ..."
|
21
|
+
FileUtils::cp(iInputFileName, iOutputFileName)
|
22
|
+
# Dump parameters in a file
|
23
|
+
# list<map<Symbol,Object>>
|
24
|
+
lProcesses = (File.exists?('Process_Test.rb')) ? eval(File.read('Process_Test.rb')) : []
|
25
|
+
lProcesses << {
|
26
|
+
:InputFileName => iInputFileName,
|
27
|
+
:OutputFileName => iOutputFileName,
|
28
|
+
:Params => iParams
|
29
|
+
}
|
30
|
+
File.open('Process_Test.rb', 'w') do |oFile|
|
31
|
+
oFile.write(lProcesses.inspect)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c) 2009-
|
2
|
+
# Copyright (c) 2009 - 2012 Muriel Salvan (muriel@x-aeon.com)
|
3
3
|
# Licensed under the terms specified in LICENSE file. No warranty is provided.
|
4
4
|
#++
|
5
5
|
|
@@ -14,13 +14,13 @@ module MusicMaster
|
|
14
14
|
|
15
15
|
# Execute the process
|
16
16
|
#
|
17
|
-
# Parameters
|
17
|
+
# Parameters::
|
18
18
|
# * *iInputFileName* (_String_): File name we want to apply effects to
|
19
19
|
# * *iOutputFileName* (_String_): File name to write
|
20
20
|
# * *iTempDir* (_String_): Temporary directory that can be used
|
21
21
|
# * *iParams* (<em>map<Symbol,Object></em>): Parameters
|
22
22
|
def execute(iInputFileName, iOutputFileName, iTempDir, iParams)
|
23
|
-
|
23
|
+
wsk(iInputFileName, iOutputFileName, 'Multiply', "--coeff \"#{iParams[:Factor]}\"")
|
24
24
|
end
|
25
25
|
|
26
26
|
end
|