def initialize (cls, aacCommandLine, audioProcessorMap, ffmpegCommand, midiToWavCommandLine, soundStyleNameToEffectsMap, intermediateFilesAreKept): """Sets some global processing data like e.g. the command paths.""" Logging.trace(">>: aac = %r, audioProcessor = %r," + " ffmpeg = %r, midiToWavCommand = %r," + " soundStyleNameToEffectsMap = %r," + " debugging = %r", aacCommandLine, audioProcessorMap, ffmpegCommand, midiToWavCommandLine, soundStyleNameToEffectsMap, intermediateFilesAreKept) cls._aacCommandLine = aacCommandLine cls._audioProcessorMap = audioProcessorMap cls._intermediateFilesAreKept = intermediateFilesAreKept cls._ffmpegCommand = ffmpegCommand cls._midiToWavRenderingCommandList = tokenize(midiToWavCommandLine) cls._soundStyleNameToEffectsMap = soundStyleNameToEffectsMap # check whether sox is used as audio processor commandList = tokenize(cls._audioProcessorMap["refinementCommandLine"]) command = commandList[0].lower() cls._audioProcessorIsSox = (command.endswith("sox") or command.endswith("sox.exe")) Logging.trace("<<")
def _compressAudio (self, audioFilePath, songTitle, targetFilePath): """Compresses audio file with <songTitle> in path with <audioFilePath> to AAC file at <targetFilePath>""" Logging.trace(">>: audioFile = %r, title = %r," + " targetFile = %r", audioFilePath, songTitle, targetFilePath) cls = self.__class__ OperatingSystem.showMessageOnConsole("== convert to AAC: " + songTitle) commandLine = iif(cls._aacCommandLine != "", cls._aacCommandLine, ("%s -loglevel %s -aac_tns 0" + " -i ${infile} -y ${outfile}") % (cls._ffmpegCommand, _ffmpegLogLevel)) variableMap = { "infile" : audioFilePath, "outfile" : targetFilePath } command = cls._replaceVariablesByValues(tokenize(commandLine), variableMap) OperatingSystem.executeCommand(command, True) Logging.trace("<<")
def _shiftAudioFileExternally (cls, commandLine, audioFilePath, shiftedFilePath, shiftOffset): """Shifts audio file in <audioFilePath> to shifted audio in <shiftedFilePath> with silence prefix of length <shiftOffset> using external command with <commandLine>""" Logging.trace(">>: commandLine = %r," + " infile = %r, outfile = %r," + " shiftOffset = %7.3f", commandLine, audioFilePath, shiftedFilePath, shiftOffset) variableMap = { "infile" : audioFilePath, "outfile" : shiftedFilePath, "duration" : "%7.3f" % shiftOffset } command = cls._replaceVariablesByValues(tokenize(commandLine), variableMap) OperatingSystem.executeCommand(command, True, stdout=OperatingSystem.nullDevice) Logging.trace("<<")
def _mixdownToWavFileExternally (self, sourceFilePathList, volumeFactorList, masteringEffectList, amplificationLevel, targetFilePath): """Mixes WAV audio files given in <sourceFilePathList> to target WAV file with <targetFilePath> with volumes given by <volumeFactorList> with loudness amplification given by <amplificationLevel> using external command; <masteringEffectList> gives the refinement effects for this track (if any) to be applied after mixdown""" Logging.trace(">>: sourceFiles = %r, volumeFactors = %r," + " masteringEffects = %r, level = %4.3f," + " targetFile = %r", sourceFilePathList, volumeFactorList, masteringEffectList, amplificationLevel, targetFilePath) cls = self.__class__ # some shorthands audioProcMap = cls._audioProcessorMap replaceVariables = cls._replaceVariablesByValues # check whether mastering is done after mixdown masteringPassIsRequired = (amplificationLevel != 0 or masteringEffectList > "") intermediateFilePath = self._audioDirectoryPath + "/result-mix.wav" intermediateFilePath = iif(masteringPassIsRequired, intermediateFilePath, targetFilePath) Logging.trace("--: masteringPass = %r, intermediateFile = %r", masteringPassIsRequired, intermediateFilePath) # do the mixdown of the audio sources commandRegexp = re.compile(r"([^\[]*)\[([^\]]+)\](.*)") mixingCommandLine = audioProcMap["mixingCommandLine"] match = commandRegexp.search(mixingCommandLine) if match is None: Logging.trace("--: bad command line format for mix - %r", mixingCommandLine) else: commandPrefix = tokenize(match.group(1)) commandRepeatingPart = tokenize(match.group(2)) commandSuffix = tokenize(match.group(3)) elementCount = len(sourceFilePathList) command = [] for i in range(elementCount): volumeFactor = volumeFactorList[i] filePath = sourceFilePathList[i] variableMap = { "factor" : volumeFactor, "infile" : filePath } part = replaceVariables(commandRepeatingPart, variableMap) command.extend(part) Logging.trace("--: repeating part = %r", command) commandList = commandPrefix + command + commandSuffix variableMap = { "outfile" : intermediateFilePath } command = replaceVariables(commandList, variableMap) OperatingSystem.executeCommand(command, True, stdout=OperatingSystem.nullDevice) if masteringPassIsRequired: # do mastering and amplification amplificationEffect = audioProcMap["amplificationEffect"] amplificationEffectTokenList = tokenize(amplificationEffect) variableMap = { "amplificationLevel" : amplificationLevel } nmEffectPartList = replaceVariables(amplificationEffectTokenList, variableMap) effectList = (tokenize(masteringEffectList) + nmEffectPartList) refinementCommandLine = audioProcMap["refinementCommandLine"] refinementCommandList = tokenize(refinementCommandLine) variableMap = { "infile" : intermediateFilePath, "outfile" : targetFilePath, "effects" : effectList } command = replaceVariables(refinementCommandList, variableMap) OperatingSystem.executeCommand(command, True) OperatingSystem.removeFile(intermediateFilePath, cls._intermediateFilesAreKept) Logging.trace("<<")
def _processAudioRefinement (self, voiceName, audioProcessingEffects): """Handles audio processing given by <audioProcessingEffects>""" Logging.trace(">>: voice = %s, effects = %r", voiceName, audioProcessingEffects) cls = self.__class__ debugFileCount = 0 separator = cls._audioProcessorMap["chainSeparator"] chainCommandList = splitAndStrip(audioProcessingEffects, separator) chainCommandCount = len(chainCommandList) commandList = tokenize(cls._audioProcessorMap["refinementCommandLine"]) for chainIndex, chainProcessingEffects in enumerate(chainCommandList): Logging.trace("--: chain[%d] = %r", chainIndex, chainProcessingEffects) chainPosition = iif3(chainCommandCount == 1, "SINGLE", chainIndex == 0, "FIRST", chainIndex == chainCommandCount - 1, "LAST", "OTHER") chainPartCommandList = splitAndStrip(chainProcessingEffects, "tee ") partCount = len(chainPartCommandList) for partIndex, partProcessingEffects \ in enumerate(chainPartCommandList): partPosition = iif3(partCount == 1, "SINGLE", partIndex == 0, "FIRST", partIndex == partCount - 1, "LAST", "OTHER") partCommandTokenList = tokenize(partProcessingEffects) sourceList, currentTarget, debugFileCount = \ self._extractEffectListSrcAndTgt(voiceName, chainPosition, partPosition, debugFileCount, partCommandTokenList) if (len(partCommandTokenList) == 0 or partCommandTokenList[0] != "mix"): currentSource = sourceList[0] variableMap = { "infile" : currentSource, "outfile" : currentTarget, "effects" : partCommandTokenList } command = cls._replaceVariablesByValues(commandList, variableMap) OperatingSystem.executeCommand(command, True) else: volumeList = partCommandTokenList[1:] if len(volumeList) < len(sourceList): Logging.trace("--: bad argument pairing for mix") else: for i in range(len(sourceList)): volume = volumeList[i] valueName = "value %d in mix" % (i+1) ValidityChecker.isNumberString(volume, valueName, True) volumeList[i] = float(volume) self._mixdownToWavFile(sourceList, volumeList, "", 0.0, currentTarget) Logging.trace("<<")