Module: MusicMaster

Defined in:
lib/MusicMaster/ConfLoader.rb,
lib/MusicMaster/Common.rb,
lib/MusicMaster/Processes/GVerb.rb,
lib/MusicMaster/Processes/Custom.rb,
lib/MusicMaster/Processes/Normalize.rb,
lib/MusicMaster/Processes/AddSilence.rb,
lib/MusicMaster/Processes/Compressor.rb,
lib/MusicMaster/Processes/VolCorrection.rb,
lib/MusicMaster/Processes/ApplyVolumeFct.rb,
lib/MusicMaster/Processes/CutFirstSignal.rb

Overview

– Copyright © 2009-2010 Muriel Salvan ([email protected]) Licensed under the terms specified in LICENSE file. No warranty is provided. ++

Defined Under Namespace

Modules: Processes

Class Method Summary collapse

Class Method Details

.applyProcesses(iEffects, iFileName, iDir) ⇒ Object

Apply given record effects on a Wave file. It modifies the given Wave file. It saves original and intermediate Wave files before modifications.

Parameters:

  • iEffects (list<map<Symbol,Object>>): List of effects to apply

  • iFileName (String): File name to apply effects to

  • iDir (String): The directory where temporary files are stored



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/MusicMaster/Common.rb', line 48

def self.applyProcesses(iEffects, iFileName, iDir)
  lFileNameNoExt = File.basename(iFileName[0..-5])
  iEffects.each_with_index do |iEffectInfo, iIdxEffect|
    begin
      accessPlugin('Processes', iEffectInfo[:Name]) do |ioActionPlugin|
        # Save the file before using the plugin
        lSave = true
        lSaveFileName = "#{iDir}/#{lFileNameNoExt}.Before_#{iIdxEffect}_#{iEffectInfo[:Name]}.wav"
        if (File.exists?(lSaveFileName))
          puts "!!! File #{lSaveFileName} already exists. Overwrite and apply effect ? [y='yes']"
          lSave = ($stdin.gets.chomp == 'y')
        end
        if (lSave)
          logInfo "Saving file #{iFileName} to #{lSaveFileName} ..."
          FileUtils::mv(iFileName, lSaveFileName)
          logInfo "===== Apply Effect #{iEffectInfo[:Name]} to #{iFileName} ====="
          ioActionPlugin.execute(lSaveFileName, iFileName, iDir, iEffectInfo.clone.delete_if{|iKey, iValue| next (iKey == :Name)})
        end
      end
    rescue Exception
      logErr "An error occurred while processing #{iFileName} with process #{iEffectInfo[:Name]}: #{$!}."
      raise
    end
  end
end

.loadConfObject



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/MusicMaster/ConfLoader.rb', line 11

def self.loadConf
  $MusicMasterConf = nil
  lConfSource = nil
  # 1. Find from the environment
  lConfigFileName = ENV['MUSICMASTER_CONF_PATH']
  if (lConfigFileName == nil)
    # 2. Find from the MusicMaster directory
    lConfigFileName = "#{File.dirname(__FILE__)}/musicmaster.conf.rb"
    if (File.exists?(lConfigFileName))
      lConfSource = 'MusicMaster package local libraries'
    else
      # 3. Find from the current directory
      lConfigFileName = "musicmaster.conf.rb"
      if (File.exists?(lConfigFileName))
        lConfSource = 'current directory'
      else
        # 4. Failure
      end
    end
  else
    lConfSource = 'MUSICMASTER_CONF_PATH environment variable'
  end

  # Check the configuration
  if (lConfSource == nil)
    logErr "No MusicMaster configuration file could be found. You can set it by setting MUSICMASTER_CONF_PATH environment variable, or create a musicmaster.conf.rb file either in #{File.dirname(__FILE__)} or the current directory."
  else
    if (File.exists?(lConfigFileName))
      File.open(lConfigFileName, 'r') do |iFile|
        begin
          $MusicMasterConf = eval(iFile.read)
        rescue Exception
          logErr "Invalid configuration file #{lConfigFileName} specified in #{lConfSource}: #{$!}"
          $MusicMasterConf = nil
        end
      end
    else
      logErr "Missing file #{lConfigFileName}, specified in #{lConfSource}"
    end
  end

end

.parsePluginsObject

Parse plugins



33
34
35
36
37
38
# File 'lib/MusicMaster/Common.rb', line 33

def self.parsePlugins
  require 'rUtilAnts/Plugins'
  RUtilAnts::Plugins::initializePlugins
  lLibDir = File.expand_path(File.dirname(__FILE__))
  parsePluginsFromDir('Processes', "#{lLibDir}/Processes", 'MusicMaster::Processes')
end

.readRecordConf(iConfFile) ⇒ Object

Read record configuration. Perform basic checks on it.

Parameters:

  • iConfFile (String): Configuration file

Return:

  • Exception: Error, or nil in case of success

  • map<Symbol,Object>: The configuration



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/MusicMaster/Common.rb', line 82

def self.readRecordConf(iConfFile)
  rError = nil
  rConf = nil

  if (!File.exists?(iConfFile))
    rError = RuntimeError.new("Missing configuration file: #{iConfFile}")
  else
    File.open(iConfFile, 'r') do |iFile|
      rConf = eval(iFile.read)
    end
    # Check that all tracks are assigned somewhere, just once
    lLstTracks = nil
    if (rConf[:Patches] != nil)
      lLstTracks = rConf[:Patches].keys.clone
    else
      lLstTracks = []
    end
    if (rConf[:Performs] != nil)
      rConf[:Performs].each do |iLstPerform|
        lLstTracks.concat(iLstPerform)
      end
    end
    lAssignedTracks = {}
    lLstTracks.each do |iIdxTrack|
      if (lAssignedTracks.has_key?(iIdxTrack))
        rError = RuntimeError.new("Track #{iIdxTrack} is recorded twice.")
        break
      else
        lAssignedTracks[iIdxTrack] = nil
      end
    end
    if (rError == nil)
      if (rConf[:Patches] != nil)
        rConf[:Patches].each do |iIdxTrack, iTrackConf|
          if ((iTrackConf.has_key?(:VolCorrection)) and
              (iTrackConf.has_key?(:VolCompareCuts)))
            rError = RuntimeError.new("Patch track #{iIdxTrack} has both :VolCorrection and :VolCompareCuts values defined.")
          elsif ((!iTrackConf.has_key?(:VolCorrection)) and
                 (!iTrackConf.has_key?(:VolCompareCuts)))
            rError = RuntimeError.new("Patch track #{iIdxTrack} has neither :VolCorrection nor :VolCompareCuts values defined.")
          end
        end
      end
      if (rError == nil)
        lAssignedTracks.size.times do |iIdxTrack|
          if (!lAssignedTracks.has_key?(iIdxTrack+1))
            logWarn "Track #{iIdxTrack+1} is never recorded."
          end
        end
      end
    end
  end

  return rError, rConf
end

.src(iSrcFile, iDstFile, iParams) ⇒ Object

Convert a Wave file to another

Parameters:

  • iSrcFile (String): Source WAVE file

  • iDstFile (String): Destination WAVE file

  • iParams (map<Symbol,Object>): The parameters:

** :SampleRate (Integer): The new sample rate in Hz ** :BitDepth (Integer): The new bit depth (only for Wave) [optional = nil] ** :Dither (Boolean): Do we apply dither (only for Wave) ? [optional = false] ** :BitRate (Integer): Bit rate in kbps (only for MP3) [optional = 320] ** :FileFormat (Symbol); File format. Here are the possible values: [optional = :Wave] *** :Wave: Uncompressed PCM Wave file *** :MP3: MP3 file



151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/MusicMaster/Common.rb', line 151

def self.src(iSrcFile, iDstFile, iParams)
  if ((iParams[:FileFormat] != nil) and
      (iParams[:FileFormat] == :MP3))
    # MP3 conversion
    lTranslatedParams = []
    iParams.each do |iParam, iValue|
      case iParam
      when :SampleRate
        lTranslatedParams << "Sample rate: #{iValue} Hz"
      when :BitRate
        lTranslatedParams << "Bit rate: #{iValue} kbps"
      when :FileFormat
        # Nothing to do
      else
        logErr "Unknown MP3 parameter: #{iParam} (value #{iValue.inspect}). Ignoring it."
      end
    end
    puts "Convert file #{iSrcFile} into file #{iDstFile} in MP3 format with following parameters: #{lTranslatedParams.join(', ')}"
    puts 'Press Enter when done.'
    $stdin.gets
  else
    # Wave conversion
    lTranslatedParams = [ '--profile standard', '--twopass' ]
    iParams.each do |iParam, iValue|
      case iParam
      when :SampleRate
        lTranslatedParams << "--rate #{iValue}"
      when :BitDepth
        lTranslatedParams << "--bits #{iValue}"
      when :Dither
        if (iValue == true)
          lTranslatedParams << '--dither 4'
        end
      when :FileFormat
        # Nothing to do
      else
        logErr "Unknown Wave parameter: #{iParam} (value #{iValue.inspect}). Ignoring it."
      end
    end
    FileUtils::mkdir_p(File.dirname(iDstFile))
    lCmd = "#{$MusicMasterConf[:SRCCmdLine]} #{lTranslatedParams.join(' ')} \"#{iSrcFile}\" \"#{iDstFile}\""
    logInfo "=> #{lCmd}"
    system(lCmd)
  end
end

.wsk(iInputFile, iOutputFile, iAction, iParams = '') ⇒ Object

Call WSK

Parameters:

  • iInputFile (String): The input file

  • iOutputFile (String): The output file

  • iAction (String): The action

  • iParams (String): Action parameters [optional = ”]



18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/MusicMaster/Common.rb', line 18

def self.wsk(iInputFile, iOutputFile, iAction, iParams = '')
  logInfo ''
  logInfo "========== Processing #{iInputFile} ==#{iAction}==> #{iOutputFile} | #{iParams} ..."
  system("#{$MusicMasterConf[:WSKCmdLine]} --input \"#{iInputFile}\" --output \"#{iOutputFile}\" --action #{iAction} -- #{iParams}")
  lErrorCode = $?.exitstatus
  if (lErrorCode == 0)
    logInfo "========== Processing #{iInputFile} ==#{iAction}==> #{iOutputFile} | #{iParams} ... OK"
  else
    logErr "========== Processing #{iInputFile} ==#{iAction}==> #{iOutputFile} | #{iParams} ... ERROR #{lErrorCode}"
    raise RuntimeError, "Processing #{iInputFile} ==#{iAction}==> #{iOutputFile} | #{iParams} ... ERROR #{lErrorCode}"
  end
  logInfo ''
end