MusicMaster 0.0.1.20101110 → 1.0.0.20120307
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/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
|