MusicMaster 0.0.1.20101110
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 +1 -0
- data/ChangeLog +5 -0
- data/Credits +6 -0
- data/LICENSE +31 -0
- data/README +18 -0
- data/ReleaseInfo +8 -0
- data/TODO +3 -0
- data/album.conf.rb.example +78 -0
- data/bin/Album.rb +81 -0
- data/bin/AnalyzeAlbum.rb +66 -0
- data/bin/DBConvert.rb +36 -0
- data/bin/Deliver.rb +42 -0
- data/bin/DeliverAlbum.rb +68 -0
- data/bin/Fct2Wave.rb +58 -0
- data/bin/Master.rb +60 -0
- data/bin/Mix.rb +99 -0
- data/bin/PrepareMix.rb +422 -0
- data/bin/Record.rb +145 -0
- data/lib/MusicMaster/Common.rb +197 -0
- data/lib/MusicMaster/ConfLoader.rb +56 -0
- data/lib/MusicMaster/Processes/AddSilence.rb +27 -0
- data/lib/MusicMaster/Processes/ApplyVolumeFct.rb +46 -0
- data/lib/MusicMaster/Processes/Compressor.rb +246 -0
- data/lib/MusicMaster/Processes/Custom.rb +31 -0
- data/lib/MusicMaster/Processes/CutFirstSignal.rb +27 -0
- data/lib/MusicMaster/Processes/GVerb.rb +30 -0
- data/lib/MusicMaster/Processes/Normalize.rb +51 -0
- data/lib/MusicMaster/Processes/VolCorrection.rb +30 -0
- data/lib/MusicMaster/musicmaster.conf.rb +96 -0
- data/master.conf.rb.example +13 -0
- data/musicmaster.conf.rb.example +95 -0
- data/record.conf.rb.example +45 -0
- metadata +104 -0
data/AUTHORS
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
= Muriel Salvan (murielsalvan@users.sourceforge.net)
|
data/ChangeLog
ADDED
data/Credits
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
|
2
|
+
The license stated herein is a copy of the BSD License (modified on July 1999).
|
3
|
+
The AUTHOR mentionned below refers to the list of people involved in the
|
4
|
+
creation and modification of any file included in the delivered package.
|
5
|
+
This list is found in the file named AUTHORS.
|
6
|
+
The AUTHORS and LICENSE files have to be included in any release of software
|
7
|
+
embedding source code of this package, or using it as a derivative software.
|
8
|
+
|
9
|
+
Copyright (c) 2010 Muriel Salvan (murielsalvan@users.sourceforge.net)
|
10
|
+
|
11
|
+
Redistribution and use in source and binary forms, with or without
|
12
|
+
modification, are permitted provided that the following conditions are met:
|
13
|
+
|
14
|
+
1. Redistributions of source code must retain the above copyright notice,
|
15
|
+
this list of conditions and the following disclaimer.
|
16
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
17
|
+
this list of conditions and the following disclaimer in the documentation
|
18
|
+
and/or other materials provided with the distribution.
|
19
|
+
3. The name of the author may not be used to endorse or promote products
|
20
|
+
derived from this software without specific prior written permission.
|
21
|
+
|
22
|
+
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
23
|
+
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
24
|
+
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
25
|
+
EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
26
|
+
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
27
|
+
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
28
|
+
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
29
|
+
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
30
|
+
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
31
|
+
OF SUCH DAMAGE.
|
data/README
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
-- This file is best viewed when processed by rdoc.
|
2
|
+
++
|
3
|
+
|
4
|
+
= Music Master
|
5
|
+
|
6
|
+
Command-line utility handling Mixing, Mastering and Delivering processes of music projects.
|
7
|
+
|
8
|
+
== Where is the documentation ?
|
9
|
+
|
10
|
+
Check the website at http://musicmaster.sourceforge.net
|
11
|
+
|
12
|
+
== Who wrote it ?
|
13
|
+
|
14
|
+
Check the AUTHORS[link:files/AUTHORS.html] file.
|
15
|
+
|
16
|
+
== What is the license ?
|
17
|
+
|
18
|
+
You can find out in the LICENSE[link:files/LICENSE.html] file.
|
data/ReleaseInfo
ADDED
data/TODO
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
{
|
2
|
+
# Recorded files of a Track should be in directories <TracksDir>/<TrackName>/<TrackVersion>/<TracksFilesSubDir>
|
3
|
+
|
4
|
+
# Path to the Tracks directories.
|
5
|
+
# Each Track is a sub-directory of this one, with its version (ie. ./Track2/0.1)
|
6
|
+
:TracksDir => '/path/to/Tracks',
|
7
|
+
|
8
|
+
# Sub-path to the recorded files
|
9
|
+
# Each Track is a sub-directory of this one, with its version (ie. Record/Files/)
|
10
|
+
# !!! Don't forget trailing /
|
11
|
+
:TracksFilesSubDir => 'sub/path/to/files/',
|
12
|
+
|
13
|
+
# Tracks to include in the album
|
14
|
+
:Tracks => [
|
15
|
+
|
16
|
+
{ # 01
|
17
|
+
# Beginning of the Track's directory name
|
18
|
+
:TrackID => 'Track112',
|
19
|
+
# Track's version
|
20
|
+
:Version => '0.0.1.20100924',
|
21
|
+
# Additional steps for Mastering the Track in the album's scope
|
22
|
+
:AdditionalMastering => [
|
23
|
+
{ :Name => 'CutFirstSignal' },
|
24
|
+
{ :Name => 'Normalize' },
|
25
|
+
{ :Name => 'VolCorrection', :Factor => '-2db' },
|
26
|
+
{ :Name => 'Compressor' },
|
27
|
+
{ :Name => 'AddSilence', :Begin => '1.2s', :End => '2.4s' }
|
28
|
+
]
|
29
|
+
},
|
30
|
+
|
31
|
+
{ # 02
|
32
|
+
:TrackID => 'Track114',
|
33
|
+
:Version => '0.0.1.20100924',
|
34
|
+
:AdditionalMastering => [
|
35
|
+
{ :Name => 'CutFirstSignal' },
|
36
|
+
{ :Name => 'Normalize' },
|
37
|
+
{ :Name => 'VolCorrection', :Factor => '-2db' },
|
38
|
+
{ :Name => 'Compressor' },
|
39
|
+
{ :Name => 'AddSilence', :Begin => '1.2s', :End => '1s' }
|
40
|
+
]
|
41
|
+
}
|
42
|
+
],
|
43
|
+
|
44
|
+
# Specify in which formats this album should be delivered
|
45
|
+
:Deliveries => {
|
46
|
+
|
47
|
+
# Name of the delivery
|
48
|
+
'Wave 96k 24b' => {
|
49
|
+
# Parameters
|
50
|
+
:SampleRate => 96000
|
51
|
+
},
|
52
|
+
|
53
|
+
'Wave 48k 24b' => {
|
54
|
+
:SampleRate => 48000
|
55
|
+
},
|
56
|
+
|
57
|
+
'Wave 44k 16b' => {
|
58
|
+
# By default :FileFormat is :Wave
|
59
|
+
:FileFormat => :Wave,
|
60
|
+
:SampleRate => 44100,
|
61
|
+
:BitDepth => 16,
|
62
|
+
:Dither => true
|
63
|
+
},
|
64
|
+
|
65
|
+
'MP3 48k 320kbps' => {
|
66
|
+
:FileFormat => :MP3,
|
67
|
+
:SampleRate => 48000,
|
68
|
+
:BitRate => 320
|
69
|
+
},
|
70
|
+
|
71
|
+
'MP3 44k 128kbps' => {
|
72
|
+
:FileFormat => :MP3,
|
73
|
+
:SampleRate => 44100,
|
74
|
+
:BitRate => 128
|
75
|
+
}
|
76
|
+
|
77
|
+
}
|
78
|
+
}
|
data/bin/Album.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
#!env ruby
|
2
|
+
#--
|
3
|
+
# Copyright (c) 2009-2010 Muriel Salvan (murielsalvan@users.sourceforge.net)
|
4
|
+
# Licensed under the terms specified in LICENSE file. No warranty is provided.
|
5
|
+
#++
|
6
|
+
|
7
|
+
require 'fileutils'
|
8
|
+
require 'MusicMaster/Common'
|
9
|
+
require 'rUtilAnts/Logging'
|
10
|
+
RUtilAnts::Logging::initializeLogging('', '')
|
11
|
+
require 'MusicMaster/ConfLoader'
|
12
|
+
|
13
|
+
module MusicMaster
|
14
|
+
|
15
|
+
# Execute the album
|
16
|
+
#
|
17
|
+
# Parameters:
|
18
|
+
# * *iConf* (<em>map<Symbol,Object></em>): Configuration of the album
|
19
|
+
def self.execute(iConf)
|
20
|
+
lTracksDir = iConf[:TracksDir]
|
21
|
+
if (!File.exists?(lTracksDir))
|
22
|
+
logErr "Missing directory #{lTracksDir}"
|
23
|
+
raise RuntimeError.new("Missing directory #{lTracksDir}")
|
24
|
+
else
|
25
|
+
iConf[:Tracks].each_with_index do |iTrackInfo, iIdxTrack|
|
26
|
+
logInfo "===== Mastering Track #{iIdxTrack}: #{iTrackInfo[:TrackID]} version #{iTrackInfo[:Version]} ====="
|
27
|
+
lAlbumFile = "#{$MusicMasterConf[:Album][:Dir]}/#{iIdxTrack}_#{iTrackInfo[:TrackID]}.wav"
|
28
|
+
lCancel = false
|
29
|
+
if (File.exists?(lAlbumFile))
|
30
|
+
puts "File #{lAlbumFile} already exists. Overwrite it by mastering a new one ? [y='yes']"
|
31
|
+
lCancel = ($stdin.gets.chomp != 'y')
|
32
|
+
end
|
33
|
+
if (!lCancel)
|
34
|
+
# Find the last Master file for this Track
|
35
|
+
lMasterFiles = Dir.glob("#{lTracksDir}/#{iTrackInfo[:TrackID]}*/#{iTrackInfo[:Version]}/#{iConf[:TracksFilesSubDir]}#{$MusicMasterConf[:Master][:Dir]}/*.wav")
|
36
|
+
if (lMasterFiles.empty?)
|
37
|
+
logErr "No Master files found for Track #{iTrackInfo[:TrackID]} version #{iTrackInfo[:Version]}"
|
38
|
+
else
|
39
|
+
# Find the last one
|
40
|
+
lFinalMasterFileName = lMasterFiles.sort[-1]
|
41
|
+
logInfo "Found final Master file from Track #{iTrackInfo[:TrackID]} version #{iTrackInfo[:Version]} in #{lFinalMasterFileName}"
|
42
|
+
# Copy it
|
43
|
+
logInfo "Copying Master file to #{lAlbumFile} ..."
|
44
|
+
FileUtils::cp(lFinalMasterFileName, lAlbumFile)
|
45
|
+
if (iTrackInfo[:AdditionalMastering] != nil)
|
46
|
+
lMasterTempDir = "#{$MusicMasterConf[:Album][:TempDir]}/#{iTrackInfo[:TrackID]}.#{iTrackInfo[:Version]}"
|
47
|
+
FileUtils::mkdir_p(lMasterTempDir)
|
48
|
+
MusicMaster::applyProcesses(iTrackInfo[:AdditionalMastering], lAlbumFile, lMasterTempDir)
|
49
|
+
end
|
50
|
+
# Done.
|
51
|
+
logInfo "Setting file #{iIdxTrack} for Track #{iTrackInfo[:TrackID]} from #{lAlbumFile}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
logInfo ''
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
rErrorCode = 0
|
62
|
+
lConfFile = ARGV[0]
|
63
|
+
if (lConfFile == nil)
|
64
|
+
logErr 'Usage: Album <ConfFile>'
|
65
|
+
rErrorCode = 1
|
66
|
+
elsif (!File.exists?(lConfFile))
|
67
|
+
logErr "File #{lConfFile} does not exist."
|
68
|
+
rErrorCode = 2
|
69
|
+
else
|
70
|
+
MusicMaster::parsePlugins
|
71
|
+
FileUtils::mkdir_p($MusicMasterConf[:Album][:Dir])
|
72
|
+
FileUtils::mkdir_p($MusicMasterConf[:Album][:TempDir])
|
73
|
+
lConf = nil
|
74
|
+
File.open(lConfFile, 'r') do |iFile|
|
75
|
+
lConf = eval(iFile.read)
|
76
|
+
end
|
77
|
+
MusicMaster::execute(lConf)
|
78
|
+
logInfo "===== Album finished in #{$MusicMasterConf[:Album][:Dir]}"
|
79
|
+
end
|
80
|
+
|
81
|
+
exit rErrorCode
|
data/bin/AnalyzeAlbum.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
#!env ruby
|
2
|
+
#--
|
3
|
+
# Copyright (c) 2009-2010 Muriel Salvan (murielsalvan@users.sourceforge.net)
|
4
|
+
# Licensed under the terms specified in LICENSE file. No warranty is provided.
|
5
|
+
#++
|
6
|
+
|
7
|
+
require 'fileutils'
|
8
|
+
require 'MusicMaster/Common'
|
9
|
+
require 'rUtilAnts/Logging'
|
10
|
+
RUtilAnts::Logging::initializeLogging('', '')
|
11
|
+
require 'MusicMaster/ConfLoader'
|
12
|
+
|
13
|
+
module MusicMaster
|
14
|
+
|
15
|
+
# Execute the album
|
16
|
+
#
|
17
|
+
# Parameters:
|
18
|
+
# * *iConf* (<em>map<Symbol,Object></em>): Configuration of the album
|
19
|
+
def self.execute(iConf)
|
20
|
+
lTracksDir = iConf[:TracksDir]
|
21
|
+
if (!File.exists?(lTracksDir))
|
22
|
+
logErr "Missing directory #{lTracksDir}"
|
23
|
+
raise RuntimeError.new("Missing directory #{lTracksDir}")
|
24
|
+
else
|
25
|
+
# Analyze results, per Track
|
26
|
+
lAnalyzeResults = []
|
27
|
+
iConf[:Tracks].each_with_index do |iTrackInfo, iIdxTrack|
|
28
|
+
lTrackFileName = "#{$MusicMasterConf[:Album][:Dir]}/#{iIdxTrack}_#{iTrackInfo[:TrackID]}.wav"
|
29
|
+
MusicMaster::wsk(lTrackFileName, 'Dummy.wav', 'Analyze')
|
30
|
+
File.unlink('Dummy.wav')
|
31
|
+
File.open('analyze.result', 'rb') do |iFile|
|
32
|
+
lAnalyzeResults << Marshal.load(iFile.read)
|
33
|
+
end
|
34
|
+
File.unlink('analyze.result')
|
35
|
+
end
|
36
|
+
# Display analyze results
|
37
|
+
logInfo ''
|
38
|
+
logInfo '===== Analyze results:'
|
39
|
+
iConf[:Tracks].each_with_index do |iTrackInfo, iIdxTrack|
|
40
|
+
lStrDBRMSValues = lAnalyzeResults[iIdxTrack][:DBRMSValues].map do |iValue|
|
41
|
+
next sprintf('%.2f', iValue)
|
42
|
+
end
|
43
|
+
logInfo "[#{iIdxTrack} - #{iTrackInfo[:TrackID]}]: RMS=(#{lStrDBRMSValues.join('db, ')}db) Max=#{sprintf('%.2f', lAnalyzeResults[iIdxTrack][:DBAbsMaxValue])}db Length=#{sprintf('%.2f', lAnalyzeResults[iIdxTrack][:DataLength])}s"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
rErrorCode = 0
|
51
|
+
lConfFile = ARGV[0]
|
52
|
+
if (lConfFile == nil)
|
53
|
+
logErr 'Usage: AnalyzeAlbum <ConfFile>'
|
54
|
+
rErrorCode = 1
|
55
|
+
elsif (!File.exists?(lConfFile))
|
56
|
+
logErr "File #{lConfFile} does not exist."
|
57
|
+
rErrorCode = 2
|
58
|
+
else
|
59
|
+
lConf = nil
|
60
|
+
File.open(lConfFile, 'r') do |iFile|
|
61
|
+
lConf = eval(iFile.read)
|
62
|
+
end
|
63
|
+
MusicMaster::execute(lConf)
|
64
|
+
end
|
65
|
+
|
66
|
+
exit rErrorCode
|
data/bin/DBConvert.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
#!env ruby
|
2
|
+
#--
|
3
|
+
# Copyright (c) 2009-2010 Muriel Salvan (murielsalvan@users.sourceforge.net)
|
4
|
+
# Licensed under the terms specified in LICENSE file. No warranty is provided.
|
5
|
+
#++
|
6
|
+
|
7
|
+
def val2db(iRatio)
|
8
|
+
if (iRatio == 0)
|
9
|
+
return -1.0/0
|
10
|
+
else
|
11
|
+
return (6*Math.log(iRatio))/Math.log(2.0)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def db2val(iDB)
|
16
|
+
return 2**(iDB/6)
|
17
|
+
end
|
18
|
+
|
19
|
+
lArg = ARGV[0]
|
20
|
+
|
21
|
+
if (lArg == nil)
|
22
|
+
puts 'Usage: DBConvert.rb <Value>'
|
23
|
+
puts ' <Value>: Either a ratio (0.43) or a db value (4.1db)'
|
24
|
+
exit 1
|
25
|
+
end
|
26
|
+
|
27
|
+
lMatch = lArg.match(/^(.*)db$/)
|
28
|
+
if (lMatch == nil)
|
29
|
+
# The argument is a ratio
|
30
|
+
lRatio = lArg.to_f
|
31
|
+
puts "#{lRatio} = #{val2db(lRatio)}db"
|
32
|
+
else
|
33
|
+
lDB = lArg.to_f
|
34
|
+
puts "#{lDB}db = #{db2val(lDB)}"
|
35
|
+
end
|
36
|
+
|
data/bin/Deliver.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
#!env ruby
|
2
|
+
#--
|
3
|
+
# Copyright (c) 2009-2010 Muriel Salvan (murielsalvan@users.sourceforge.net)
|
4
|
+
# Licensed under the terms specified in LICENSE file. No warranty is provided.
|
5
|
+
#++
|
6
|
+
|
7
|
+
require 'MusicMaster/Common'
|
8
|
+
require 'rUtilAnts/Logging'
|
9
|
+
RUtilAnts::Logging::initializeLogging('', '')
|
10
|
+
require 'MusicMaster/ConfLoader'
|
11
|
+
|
12
|
+
module MusicMaster
|
13
|
+
|
14
|
+
# Execute the delivery
|
15
|
+
#
|
16
|
+
# Parameters:
|
17
|
+
# * *iWaveFile* (_String_): Wave file to deliver
|
18
|
+
def self.execute(iWaveFile)
|
19
|
+
lRealBaseName = File.basename(iWaveFile)[0..-5]
|
20
|
+
MusicMaster::src(iWaveFile, "#{$MusicMasterConf[:Deliver][:Dir]}/#{lRealBaseName}_96_24.wav", :SampleRate => 96000)
|
21
|
+
MusicMaster::src(iWaveFile, "#{$MusicMasterConf[:Deliver][:Dir]}/#{lRealBaseName}_48_24.wav", :SampleRate => 48000)
|
22
|
+
MusicMaster::src(iWaveFile, "#{$MusicMasterConf[:Deliver][:Dir]}/#{lRealBaseName}_44_16.wav", :SampleRate => 44100, :BitDepth => 16, :Dither => true)
|
23
|
+
# TODO: Deliver MP3 files too
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
rErrorCode = 0
|
29
|
+
lWaveFile = ARGV[0]
|
30
|
+
if (lWaveFile == nil)
|
31
|
+
logErr 'Please specify the WAVE file.'
|
32
|
+
rErrorCode = 1
|
33
|
+
elsif (!File.exists?(lWaveFile))
|
34
|
+
logErr "File #{lWaveFile} does not exist."
|
35
|
+
rErrorCode = 2
|
36
|
+
else
|
37
|
+
FileUtils::mkdir_p($MusicMasterConf[:Deliver][:Dir])
|
38
|
+
MusicMaster::execute(lWaveFile)
|
39
|
+
logInfo "===== Delivery finished in #{$MusicMasterConf[:Deliver][:Dir]}"
|
40
|
+
end
|
41
|
+
|
42
|
+
exit rErrorCode
|
data/bin/DeliverAlbum.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
#!env ruby
|
2
|
+
#--
|
3
|
+
# Copyright (c) 2009-2010 Muriel Salvan (murielsalvan@users.sourceforge.net)
|
4
|
+
# Licensed under the terms specified in LICENSE file. No warranty is provided.
|
5
|
+
#++
|
6
|
+
|
7
|
+
require 'MusicMaster/Common'
|
8
|
+
require 'rUtilAnts/Logging'
|
9
|
+
RUtilAnts::Logging::initializeLogging('', '')
|
10
|
+
require 'MusicMaster/ConfLoader'
|
11
|
+
|
12
|
+
module MusicMaster
|
13
|
+
|
14
|
+
# Execute the delivery of the album
|
15
|
+
#
|
16
|
+
# Parameters:
|
17
|
+
# * *iConf* (<em>map<Symbol,Object></em>): Configuration of the album
|
18
|
+
def self.execute(iConf)
|
19
|
+
lDeliveries = iConf[:Deliveries]
|
20
|
+
if (lDeliveries == nil)
|
21
|
+
logWarn 'Configuration does not specify any delivery. Nothing to deliver.'
|
22
|
+
else
|
23
|
+
lTracksDir = iConf[:TracksDir]
|
24
|
+
if (!File.exists?(lTracksDir))
|
25
|
+
logErr "Missing directory #{lTracksDir}"
|
26
|
+
raise RuntimeError.new("Missing directory #{lTracksDir}")
|
27
|
+
else
|
28
|
+
iConf[:Tracks].each_with_index do |iTrackInfo, iIdxTrack|
|
29
|
+
lBaseFileName = "#{iIdxTrack}_#{iTrackInfo[:TrackID]}"
|
30
|
+
lSourceFile = "#{$MusicMasterConf[:Album][:Dir]}/#{lBaseFileName}.wav"
|
31
|
+
if (!File.exists?(lSourceFile))
|
32
|
+
logErr "Missing file #{lSourceFile}"
|
33
|
+
else
|
34
|
+
lDeliveries.each do |iDeliveryName, iDeliveryConf|
|
35
|
+
lExt = 'wav'
|
36
|
+
if ((iDeliveryConf[:FileFormat] != nil) and
|
37
|
+
(iDeliveryConf[:FileFormat] == :MP3))
|
38
|
+
lExt = 'mp3'
|
39
|
+
end
|
40
|
+
MusicMaster::src(lSourceFile, "#{$MusicMasterConf[:AlbumDeliver][:Dir]}/#{iDeliveryName}/#{lBaseFileName}.#{lExt}", iDeliveryConf)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
rErrorCode = 0
|
51
|
+
lConfFile = ARGV[0]
|
52
|
+
if (lConfFile == nil)
|
53
|
+
logErr 'Usage: DeliverAlbum <ConfFile>'
|
54
|
+
rErrorCode = 1
|
55
|
+
elsif (!File.exists?(lConfFile))
|
56
|
+
logErr "File #{lConfFile} does not exist."
|
57
|
+
rErrorCode = 2
|
58
|
+
else
|
59
|
+
FileUtils::mkdir_p($MusicMasterConf[:AlbumDeliver][:Dir])
|
60
|
+
lConf = nil
|
61
|
+
File.open(lConfFile, 'r') do |iFile|
|
62
|
+
lConf = eval(iFile.read)
|
63
|
+
end
|
64
|
+
MusicMaster::execute(lConf)
|
65
|
+
logInfo "===== Album delivered in #{$MusicMasterConf[:AlbumDeliver][:Dir]}"
|
66
|
+
end
|
67
|
+
|
68
|
+
exit rErrorCode
|
data/bin/Fct2Wave.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
#!env ruby
|
2
|
+
#--
|
3
|
+
# Copyright (c) 2009-2010 Muriel Salvan (murielsalvan@users.sourceforge.net)
|
4
|
+
# Licensed under the terms specified in LICENSE file. No warranty is provided.
|
5
|
+
#++
|
6
|
+
|
7
|
+
require 'fileutils'
|
8
|
+
require 'MusicMaster/Common'
|
9
|
+
require 'rUtilAnts/Logging'
|
10
|
+
RUtilAnts::Logging::initializeLogging('', '')
|
11
|
+
require 'MusicMaster/ConfLoader'
|
12
|
+
|
13
|
+
module MusicMaster
|
14
|
+
|
15
|
+
# Execute the mastering
|
16
|
+
#
|
17
|
+
# Parameters:
|
18
|
+
# * *iConf* (<em>map<Symbol,Object></em>): Configuration of the master
|
19
|
+
# * *iWaveFile* (_String_): Wave file to master
|
20
|
+
# Return:
|
21
|
+
# * _String_: Name of the Wave file containing the result
|
22
|
+
def self.execute(iConf, iWaveFile)
|
23
|
+
rWaveFileToProcess = "#{$MusicMasterConf[:Master][:Dir]}/#{File.basename(iWaveFile)}"
|
24
|
+
|
25
|
+
logInfo 'Copying Master file ...'
|
26
|
+
FileUtils::cp(iWaveFile, rWaveFileToProcess)
|
27
|
+
# Execute each step of the mastering to the wave file
|
28
|
+
if (iConf[:Mastering] != nil)
|
29
|
+
self.applyProcesses(iConf[:Mastering], rWaveFileToProcess, $MusicMasterConf[:Master][:Dir])
|
30
|
+
end
|
31
|
+
|
32
|
+
return rWaveFileToProcess
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
rErrorCode = 0
|
38
|
+
lFctFile, lInputWaveFile, lOutputWaveFile, lUnitDB = ARGV[0..4]
|
39
|
+
if ((lFctFile == nil) or
|
40
|
+
(lInputWaveFile == nil) or
|
41
|
+
(lOutputWaveFile == nil))
|
42
|
+
logErr 'Usage: Master <FctFile> <InputWaveFile> <OutputWaveFile> [--unitdb]'
|
43
|
+
rErrorCode = 1
|
44
|
+
elsif (!File.exists?(lFctFile))
|
45
|
+
logErr "File #{lFctFile} does not exist."
|
46
|
+
rErrorCode = 2
|
47
|
+
elsif (!File.exists?(lInputWaveFile))
|
48
|
+
logErr "File #{lInputWaveFile} does not exist."
|
49
|
+
rErrorCode = 3
|
50
|
+
else
|
51
|
+
lStrUnitDB = '0'
|
52
|
+
if (lUnitDB == '--unitdb')
|
53
|
+
lStrUnitDB = '1'
|
54
|
+
end
|
55
|
+
MusicMaster::wsk(lInputWaveFile, lOutputWaveFile, 'DrawFct', "--function \"#{lFctFile}\" --unitdb #{lStrUnitDB}")
|
56
|
+
end
|
57
|
+
|
58
|
+
exit rErrorCode
|
data/bin/Master.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
#!env ruby
|
2
|
+
#--
|
3
|
+
# Copyright (c) 2009-2010 Muriel Salvan (murielsalvan@users.sourceforge.net)
|
4
|
+
# Licensed under the terms specified in LICENSE file. No warranty is provided.
|
5
|
+
#++
|
6
|
+
|
7
|
+
require 'fileutils'
|
8
|
+
require 'MusicMaster/Common'
|
9
|
+
require 'rUtilAnts/Logging'
|
10
|
+
RUtilAnts::Logging::initializeLogging('', '')
|
11
|
+
require 'MusicMaster/ConfLoader'
|
12
|
+
|
13
|
+
module MusicMaster
|
14
|
+
|
15
|
+
# Execute the mastering
|
16
|
+
#
|
17
|
+
# Parameters:
|
18
|
+
# * *iConf* (<em>map<Symbol,Object></em>): Configuration of the master
|
19
|
+
# * *iWaveFile* (_String_): Wave file to master
|
20
|
+
# Return:
|
21
|
+
# * _String_: Name of the Wave file containing the result
|
22
|
+
def self.execute(iConf, iWaveFile)
|
23
|
+
rWaveFileToProcess = "#{$MusicMasterConf[:Master][:Dir]}/#{File.basename(iWaveFile)}"
|
24
|
+
|
25
|
+
logInfo 'Copying Master file ...'
|
26
|
+
FileUtils::cp(iWaveFile, rWaveFileToProcess)
|
27
|
+
# Execute each step of the mastering to the wave file
|
28
|
+
if (iConf[:Mastering] != nil)
|
29
|
+
self.applyProcesses(iConf[:Mastering], rWaveFileToProcess, $MusicMasterConf[:Master][:Dir])
|
30
|
+
end
|
31
|
+
|
32
|
+
return rWaveFileToProcess
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
rErrorCode = 0
|
38
|
+
lConfFile, lWaveFile = ARGV[0..1]
|
39
|
+
if ((lConfFile == nil) or
|
40
|
+
(lWaveFile == nil))
|
41
|
+
logErr 'Usage: Master <ConfFile> <WaveFile>'
|
42
|
+
rErrorCode = 1
|
43
|
+
elsif (!File.exists?(lConfFile))
|
44
|
+
logErr "File #{lConfFile} does not exist."
|
45
|
+
rErrorCode = 2
|
46
|
+
elsif (!File.exists?(lWaveFile))
|
47
|
+
logErr "File #{lWaveFile} does not exist."
|
48
|
+
rErrorCode = 3
|
49
|
+
else
|
50
|
+
MusicMaster::parsePlugins
|
51
|
+
FileUtils::mkdir_p($MusicMasterConf[:Master][:Dir])
|
52
|
+
lConf = nil
|
53
|
+
File.open(lConfFile, 'r') do |iFile|
|
54
|
+
lConf = eval(iFile.read)
|
55
|
+
end
|
56
|
+
lFinalWave = MusicMaster::execute(lConf, lWaveFile)
|
57
|
+
logInfo "===== Mastering finished in #{lFinalWave}"
|
58
|
+
end
|
59
|
+
|
60
|
+
exit rErrorCode
|
data/bin/Mix.rb
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
#!env ruby
|
2
|
+
#--
|
3
|
+
# Copyright (c) 2009-2010 Muriel Salvan (murielsalvan@users.sourceforge.net)
|
4
|
+
# Licensed under the terms specified in LICENSE file. No warranty is provided.
|
5
|
+
#++
|
6
|
+
|
7
|
+
require 'MusicMaster/Common'
|
8
|
+
require 'rUtilAnts/Logging'
|
9
|
+
RUtilAnts::Logging::initializeLogging('', '')
|
10
|
+
require 'MusicMaster/ConfLoader'
|
11
|
+
|
12
|
+
module MusicMaster
|
13
|
+
|
14
|
+
# Execute the Mix
|
15
|
+
#
|
16
|
+
# Parameters:
|
17
|
+
# * *iConfig* (<em>map<Symbol,Object></em>): The Mix configuration
|
18
|
+
# Return:
|
19
|
+
# * _String_: The resulting mix file
|
20
|
+
def self.execute(iConfig)
|
21
|
+
rPerformMixFile = nil
|
22
|
+
|
23
|
+
lMixInputFile = nil
|
24
|
+
lLstMixFiles = []
|
25
|
+
lMissingFiles = []
|
26
|
+
iConfig[:MixFiles].each do |iMixFileInfo|
|
27
|
+
if (!File.exists?(iMixFileInfo[:FileName]))
|
28
|
+
logErr "File #{iMixFileInfo[:FileName]} does not exist."
|
29
|
+
lMissingFiles << iMixFileInfo[:FileName]
|
30
|
+
else
|
31
|
+
lResultFileName = executeOperations(iMixFileInfo[:FileName], iMixFileInfo[:Operations])
|
32
|
+
if (lMixInputFile == nil)
|
33
|
+
lMixInputFile = lResultFileName
|
34
|
+
else
|
35
|
+
lLstMixFiles << lResultFileName
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
if (!lMissingFiles.empty?)
|
40
|
+
logErr "Mix will not be performed as some files were missing: #{lMissingFiles.join(', ')}"
|
41
|
+
else
|
42
|
+
if (lLstMixFiles.empty?)
|
43
|
+
logInfo "Single perform file to mix: #{lMixInputFile}"
|
44
|
+
rPerformMixFile = lMixInputFile
|
45
|
+
else
|
46
|
+
rPerformMixFile = "#{$MusicMasterConf[:Mix][:TempDir]}/Perform.Mix.wav"
|
47
|
+
wsk(lMixInputFile, rPerformMixFile, 'Mix', "--files \"#{lLstMixFiles.join('|1|')}|1\" ")
|
48
|
+
end
|
49
|
+
logInfo "Perform mix result in #{rPerformMixFile}"
|
50
|
+
end
|
51
|
+
|
52
|
+
return rPerformMixFile
|
53
|
+
end
|
54
|
+
|
55
|
+
# Execute operations on a Wave file, then give back the resulting file
|
56
|
+
#
|
57
|
+
# Parameters:
|
58
|
+
# * *iInputFile* (_String_): The input wave file
|
59
|
+
# * *iOperations* (<em>list<[String,String]></em>): The list of operations to execute: [Action,Parameters].
|
60
|
+
# Return:
|
61
|
+
# * _String_: The resulting file name
|
62
|
+
def self.executeOperations(iInputFile, iOperations)
|
63
|
+
rResultFileName = iInputFile
|
64
|
+
|
65
|
+
lBaseName = "#{$MusicMasterConf[:Mix][:TempDir]}/#{File.basename(iInputFile)[0..-5]}"
|
66
|
+
iOperations.each_with_index do |iOperationInfo, iIdxOperation|
|
67
|
+
iAction, iParameters = iOperationInfo
|
68
|
+
lInputFileName = rResultFileName.clone
|
69
|
+
rResultFileName = "#{lBaseName}.#{iIdxOperation}.#{iAction}.wav"
|
70
|
+
# Call wsk if the file does not exist already
|
71
|
+
if (!File.exists?(rResultFileName))
|
72
|
+
wsk(lInputFileName, rResultFileName, iAction, iParameters)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
return rResultFileName
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
rErrorCode = 0
|
82
|
+
lConfigFile = ARGV[0]
|
83
|
+
if (lConfigFile == nil)
|
84
|
+
logErr 'Please specify the configuration file.'
|
85
|
+
rErrorCode = 1
|
86
|
+
elsif (!File.exists?(lConfigFile))
|
87
|
+
logErr "File #{lConfigFile} does not exist."
|
88
|
+
rErrorCode = 2
|
89
|
+
else
|
90
|
+
FileUtils::mkdir_p($MusicMasterConf[:Mix][:TempDir])
|
91
|
+
lConfig = nil
|
92
|
+
File.open(lConfigFile, 'r') do |iFile|
|
93
|
+
lConfig = eval(iFile.read)
|
94
|
+
end
|
95
|
+
lMixFile = MusicMaster::execute(lConfig)
|
96
|
+
logInfo "===== Mix saved in #{lMixFile}"
|
97
|
+
end
|
98
|
+
|
99
|
+
exit rErrorCode
|