Ejemplo n.º 1
0
    def _makePdf(cls, processingPhase, targetFileNamePrefix, voiceNameList):
        """Processes lilypond file and generates extract or score PDF
           file."""

        Logging.trace(">>: targetFilePrefix = %r, voiceNameList=%r",
                      targetFileNamePrefix, voiceNameList)

        configData = cls._configData
        tempLilypondFilePath = configData.tempLilypondFilePath
        lilypondFile = LilypondFile(tempLilypondFilePath)
        lilypondFile.generate(
            configData.includeFilePath, configData.lilypondVersion,
            processingPhase, voiceNameList, configData.title,
            configData.songComposerText, configData.voiceNameToChordsMap,
            configData.voiceNameToLyricsMap,
            configData.voiceNameToScoreNameMap, configData.measureToTempoMap,
            configData.phaseAndVoiceNameToClefMap,
            configData.phaseAndVoiceNameToStaffListMap)
        cls._processLilypond(tempLilypondFilePath, targetFileNamePrefix)
        OperatingSystem.moveFile(targetFileNamePrefix + ".pdf",
                                 configData.targetDirectoryPath)
        OperatingSystem.removeFile(tempLilypondFilePath,
                                   configData.intermediateFilesAreKept)

        Logging.trace("<<")
    def generateRawAudio (self, midiFilePath, voiceName, shiftOffset):
        """Generates audio wave file for <voiceName> from midi file
           with <midiFilePath> in target directory; if several midi
           tracks match voice name, the resulting audio files are
           mixed; output is dry (no chorus, reverb and delay) and
           contains leading and trailing silent passages; if
           <shiftOffset> is greater that zero, the target file is
           shifted by that amount"""

        Logging.trace(">>: voice = %s, midiFile = %r, shiftOffset = %7.3f",
                      voiceName, midiFilePath, shiftOffset)

        cls = self.__class__
        tempMidiFilePath = "tempRender.mid"
        isShifted = (shiftOffset > 0)
        defaultTemplate = "%s/%s.wav"
        filePathTemplate = iif(isShifted, "%s/%s-raw.wav", defaultTemplate)
        audioFilePath = filePathTemplate % (self._audioDirectoryPath,
                                            voiceName)

        self._makeFilteredMidiFile(voiceName, midiFilePath, tempMidiFilePath)
        self._convertMidiToAudio(tempMidiFilePath, audioFilePath)

        if isShifted:
            targetFilePath = defaultTemplate % (self._audioDirectoryPath,
                                                voiceName)
            cls._shiftAudioFile(audioFilePath, targetFilePath, shiftOffset)
            OperatingSystem.removeFile(audioFilePath,
                                       cls._intermediateFilesAreKept)

        OperatingSystem.removeFile(tempMidiFilePath,
                                   cls._intermediateFilesAreKept)

        Logging.trace("<<")
    def cleanUpConditionally (cls, filesAreKept):
        """Cleans up subtitle file if <filesAreKept> is unset,
           otherwise moves it to directory given by <targetPath>"""

        Logging.trace(">>: %r", filesAreKept)

        if cls.fileName == cls._tempFileName:
            OperatingSystem.removeFile(cls.fileName, filesAreKept)

        Logging.trace("<<")
    def cleanup (self):
        """Deletes all intermediate files."""

        Logging.trace(">>")

        filesAreKept = self._intermediateFilesAreKept
        OperatingSystem.removeFile(self._postscriptFileName, filesAreKept)
        MP4Video.cleanUpConditionally(filesAreKept)
        SubtitleFile.cleanUpConditionally(filesAreKept)

        Logging.trace("<<")
Ejemplo n.º 5
0
    def processMidi(cls):
        """Generates midi file from lilypond file."""

        Logging.trace(">>")

        configData = cls._configData
        intermediateFilesAreKept = configData.intermediateFilesAreKept
        tempLilypondFilePath = configData.tempLilypondFilePath
        lilypondFile = LilypondFile(tempLilypondFilePath)
        lilypondFile.generate(
            configData.includeFilePath, configData.lilypondVersion, "midi",
            configData.midiVoiceNameList, configData.title,
            configData.songComposerText, configData.voiceNameToChordsMap,
            configData.voiceNameToLyricsMap,
            configData.voiceNameToScoreNameMap, configData.measureToTempoMap,
            configData.phaseAndVoiceNameToClefMap,
            configData.phaseAndVoiceNameToStaffListMap)

        tempMidiFileNamePrefix = (configData.intermediateFileDirectoryPath +
                                  cls._pathSeparator +
                                  configData.fileNamePrefix + "-temp")
        tempMidiFileName = tempMidiFileNamePrefix + ".mid"
        targetMidiFileName = (cls._midiFileNameTemplate %
                              configData.fileNamePrefix)

        cls._processLilypond(tempLilypondFilePath, tempMidiFileNamePrefix)

        # postprocess MIDI file
        OperatingSystem.showMessageOnConsole("== adapting MIDI into " +
                                             targetMidiFileName)
        trackToSettingsMap = cls._calculateTrackToSettingsMap()

        midiTransformer = MidiTransformer(tempMidiFileName,
                                          intermediateFilesAreKept)
        midiTransformer.addMissingTrackNames()
        midiTransformer.humanizeTracks(
            configData.countInMeasureCount,
            configData.measureToHumanizationStyleNameMap)
        midiTransformer.positionInstruments(trackToSettingsMap)
        midiTransformer.addProcessingDateToTracks(trackToSettingsMap.keys())
        midiTransformer.save(targetMidiFileName)

        OperatingSystem.moveFile(targetMidiFileName,
                                 configData.targetDirectoryPath)
        OperatingSystem.removeFile(tempMidiFileName, intermediateFilesAreKept)
        OperatingSystem.removeFile(tempLilypondFilePath,
                                   intermediateFilesAreKept)

        Logging.trace("<<")
    def cleanUpConditionally (cls, filesAreKept):
        """Deletes all intermediate files when <filesAreKept> is unset"""

        Logging.trace(">>: %r", filesAreKept)

        for page in range(1, cls._pageCount + 1):
            Logging.trace("--: %d", page)
            fileName = cls._intermediateFileNameTemplate % page
            OperatingSystem.removeFile(fileName, filesAreKept)
            fileName = cls._pageFileNameTemplate % page
            OperatingSystem.removeFile(fileName, filesAreKept)

        OperatingSystem.removeFile(cls._concatSpecificationFileName,
                                 filesAreKept)

        if cls.fileName and cls.fileName == cls._tempFileName:
            OperatingSystem.removeFile(cls.fileName, filesAreKept)

        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("<<")
Ejemplo n.º 8
0
    def processSilentVideo(cls):
        """Generates video without audio from lilypond file."""

        Logging.trace(">>")

        mmPerInch = 25.4
        configData = cls._configData
        intermediateFilesAreKept = configData.intermediateFilesAreKept
        intermediateFileDirectoryPath = \
            configData.intermediateFileDirectoryPath
        targetDirectoryPath = configData.targetDirectoryPath
        targetSubtitleFileName = (
            targetDirectoryPath + cls._pathSeparator +
            (subtitleFileNameTemplate % configData.fileNamePrefix))
        tempLilypondFilePath = configData.tempLilypondFilePath

        for _, videoFileKind in configData.videoFileKindMap.items():
            message = ("== generating silent video for %s" %
                       videoFileKind.name)
            OperatingSystem.showMessageOnConsole(message)
            videoTargetName = videoFileKind.target

            if videoTargetName not in configData.videoTargetMap:
                Logging.trace("--: unknown video target %s for file kind %s",
                              videoTargetName, videoFileKind.name)
            else:
                videoTarget = configData.videoTargetMap[videoTargetName]
                effectiveVideoResolution = (videoTarget.resolution *
                                            videoTarget.scalingFactor)
                factor = mmPerInch / videoTarget.resolution
                videoWidth = videoTarget.width * factor
                videoHeight = videoTarget.height * factor
                videoLineWidth = videoWidth - 2 * videoTarget.leftRightMargin
                lilypondFile = LilypondFile(tempLilypondFilePath)
                lilypondFile.setVideoParameters(videoTarget.name,
                                                effectiveVideoResolution,
                                                videoTarget.systemSize,
                                                videoTarget.topBottomMargin,
                                                videoWidth, videoHeight,
                                                videoLineWidth)
                lilypondFile.generate(
                    configData.includeFilePath, configData.lilypondVersion,
                    "video", videoFileKind.voiceNameList, configData.title,
                    configData.songComposerText,
                    configData.voiceNameToChordsMap,
                    configData.voiceNameToLyricsMap,
                    configData.voiceNameToScoreNameMap,
                    configData.measureToTempoMap,
                    configData.phaseAndVoiceNameToClefMap,
                    configData.phaseAndVoiceNameToStaffListMap)
                targetMp4FileName = (
                    targetDirectoryPath + cls._pathSeparator +
                    (silentVideoFileNameTemplate %
                     (configData.fileNamePrefix, videoFileKind.fileNameSuffix))
                )
                videoGenerator = \
                    LilypondPngVideoGenerator(tempLilypondFilePath,
                                              targetMp4FileName,
                                              targetSubtitleFileName,
                                              configData.measureToTempoMap,
                                              countInMeasures,
                                              videoTarget.frameRate,
                                              videoTarget.scalingFactor,
                                              videoTarget.ffmpegPresetName,
                                              intermediateFileDirectoryPath,
                                              intermediateFilesAreKept)
                videoGenerator.process()
                videoGenerator.cleanup()

                ##OperatingSystem.moveFile(targetMp4FileName,
                ##                         configData.targetDirectoryPath)
                ##OperatingSystem.moveFile(targetSubtitleFileName,
                ##                         configData.targetDirectoryPath)

        OperatingSystem.removeFile(tempLilypondFilePath,
                                   intermediateFilesAreKept)

        Logging.trace("<<")
Ejemplo n.º 9
0
    def processFinalVideo(cls):
        """Generates final videos from silent video, audio tracks and
           subtitle files."""

        Logging.trace(">>")

        configData = cls._configData
        tempSubtitleFilePath = "tempSubtitle.srt"
        tempMp4FilePath = "tempVideoWithSubtitles.mp4"

        # --- shift subtitles ---
        subtitleFilePath = "%s/%s" % (configData.targetDirectoryPath,
                                      (subtitleFileNameTemplate %
                                       configData.fileNamePrefix))
        VideoAudioCombiner.shiftSubtitleFile(subtitleFilePath,
                                             tempSubtitleFilePath,
                                             configData.shiftOffset)

        for _, videoFileKind in configData.videoFileKindMap.items():
            silentMp4FilePath = (
                ("%s/" + silentVideoFileNameTemplate) %
                (configData.targetDirectoryPath, configData.fileNamePrefix,
                 videoFileKind.fileNameSuffix))
            videoTargetName = videoFileKind.target

            if videoTargetName not in configData.videoTargetMap:
                Logging.trace("--: unknown video target %s for file kind %s",
                              videoTargetName, videoFileKind.name)
            else:
                videoTarget = configData.videoTargetMap[videoTargetName]

                if not videoTarget.subtitlesAreHardcoded:
                    videoFilePath = silentMp4FilePath
                    effectiveSubtitleFilePath = tempSubtitleFilePath
                else:
                    videoFilePath = tempMp4FilePath
                    effectiveSubtitleFilePath = ""
                    VideoAudioCombiner.insertHardSubtitles( \
                                            silentMp4FilePath,
                                            tempSubtitleFilePath,
                                            videoFilePath,
                                            configData.shiftOffset,
                                            videoTarget.subtitleColor,
                                            videoTarget.subtitleFontSize,
                                            videoTarget.ffmpegPresetName)

                targetDirectoryPath = videoFileKind.directoryPath
                ValidityChecker.isDirectory(targetDirectoryPath,
                                            "video target directory")
                targetVideoFilePath = (
                    "%s/%s%s-%s.mp4" %
                    (targetDirectoryPath, configData.targetFileNamePrefix,
                     configData.fileNamePrefix, videoTarget.name))
                trackDataList = \
                   AudioTrackManager.constructSettingsForAudioTracks(configData)

                VideoAudioCombiner.combine(videoFileKind.voiceNameList,
                                           trackDataList, videoFilePath,
                                           targetVideoFilePath,
                                           effectiveSubtitleFilePath)

                mediaType = "TV Show"
                VideoAudioCombiner.tagVideoFile(targetVideoFilePath,
                                                configData.albumName,
                                                configData.artistName,
                                                configData.albumArtFilePath,
                                                configData.title, mediaType,
                                                configData.songYear)

        intermediateFilesAreKept = configData.intermediateFilesAreKept
        OperatingSystem.removeFile(tempSubtitleFilePath,
                                   intermediateFilesAreKept)
        OperatingSystem.removeFile(tempMp4FilePath, intermediateFilesAreKept)

        Logging.trace("<<")