예제 #1
0
def resynthesizePitch(praatEXE,
                      inputWavFN,
                      pitchFN,
                      outputWavFN,
                      minPitch,
                      maxPitch,
                      scriptFN=None,
                      pointList=None):
    '''
    Resynthesizes the pitch in a wav file with the given pitch contour file
    
    The pitch track to use can optionally be passed in as pointList.  If
    so, it will be saved as pitchFN for praat to be able to use.
    '''
    if scriptFN is None:
        scriptFN = join(utils.scriptsPath, "resynthesize_pitch.praat")

    if pointList is not None:
        dur = audioio.WavQueryObj(inputWavFN).getDuration()
        pointObj = dataio.PointObject2D(pointList, dataio.PITCH, 0, dur)
        pointObj.save(pitchFN)

    utils.runPraatScript(
        praatEXE, scriptFN,
        [inputWavFN, pitchFN, outputWavFN, minPitch, maxPitch])
예제 #2
0
def segment_audio(audiodir, wavdir, tgs, long2iso):
    print('Segmenting %s from %s to %s'%(str([x for x in tgs.keys()]),wavdir,audiodir))
    outputnames = []
    for (filename,tg) in tgs.items():
        entryList = tg.tierDict['seg'].entryList
        entryList = [ entry for entry in entryList if not entry[2].isspace() ]
        outdir = os.path.join(audiodir,filename)
        os.makedirs(outdir,exist_ok=True)
        inputfile = os.path.join(wavdir, filename+'.wav')
        wavQObj = audioio.WavQueryObj(inputfile)        
        for entry in entryList:
            start, stop, label = entry
            if not label.isnumeric():
                raise RunTimeError('TextGrid %s contains non-numeric label %s'%(filename,label))
            outputname = os.path.join(outdir, '%s_%4.4d.wav'%(filename,int(label)))
            frames = wavQObj.getFrames(start, stop)
            wavQObj.outputModifiedWav(frames, outputname)            
            outputnames.append(outputname)
예제 #3
0
def deleteVowels(inputTGFN,
                 inputWavFN,
                 outputPath,
                 doShrink,
                 atZeroCrossing=True):

    utils.makeDir(outputPath)

    wavFN = os.path.split(inputWavFN)[1]
    tgFN = os.path.split(inputTGFN)[1]
    outputWavFN = join(outputPath, wavFN)
    outputTGFN = join(outputPath, tgFN)

    if atZeroCrossing is True:
        zeroCrossingTGPath = join(outputPath, "zero_crossing_tgs")
        zeroCrossingTGFN = join(zeroCrossingTGPath, tgFN)
        utils.makeDir(zeroCrossingTGPath)

        tg = tgio.openTextgrid(inputTGFN)
        wavObj = audioio.WavQueryObj(inputWavFN)

        praatio_scripts.tgBoundariesToZeroCrossings(tg, wavObj,
                                                    zeroCrossingTGFN)

    else:
        tg = tgio.openTextgrid(inputTGFN)

    keepList = tg.tierDict["phone"].entryList
    keepList = [entry for entry in keepList if not isVowel(entry[2])]
    deleteList = utils.invertIntervalList(keepList, tg.maxTimestamp)

    wavObj = audioio.openAudioFile(inputWavFN,
                                   keepList=keepList,
                                   doShrink=doShrink)
    wavObj.save(outputWavFN)

    shrunkTG = copy.deepcopy(tg)
    for start, stop in sorted(deleteList, reverse=True):
        shrunkTG = shrunkTG.eraseRegion(start, stop, doShrink=doShrink)

    shrunkTG.save(outputTGFN)
예제 #4
0
from praatio import tgio
from praatio import audioio

path = join(".", "files")
outputPath = join(path, "anonymized_data")

if not os.path.exists(outputPath):
    os.mkdir(outputPath)

for wavFN, tgFN in (("mary.wav", "mary.TextGrid"), ("bobby.wav",
                                                    "bobby_words.TextGrid")):

    outputWavFN = join(outputPath, wavFN)

    # Find the word(s) to anonymize
    # (One could imagine a search for common names or identification of
    # some sort of code ('section-to-anonymize') rather than what I have
    # done here.
    deleteList = []
    tg = tgio.openTextgrid(join(path, tgFN))
    deleteList.append(tg.tierDict['word'].entryList[0])

    # Get only time information from entries (i.e. remove label information)
    deleteList = [(start, stop) for start, stop, _ in deleteList]

    # Replace segments with a sine wave
    wavQObj = audioio.WavQueryObj(join(path, wavFN))
    wavQObj.deleteWavSections(outputWavFN,
                              deleteList=deleteList,
                              operation="sine wave")
originalPitchFN = "mary1.pitch"
outputWavFN = "mary1_accented.wav"
outputPitchFN = "mary1_accented.pitch"
minPitch = 75
maxPitch = 450

if not os.path.exists(rootOutputPath):
    os.mkdir(rootOutputPath)

# 1st - get pitch
piList = pitch_and_intensity.extractPI(join(root, wavFN),
                                       join(rootOutputPath, pitchIntensityFN),
                                       praatEXE, minPitch, maxPitch)
pitchList = [(timeV, pitchV) for timeV, pitchV, _ in piList]

dur = audioio.WavQueryObj(join(root, wavFN)).getDuration()
pointObj = dataio.PointObject2D(pitchList, dataio.PITCH, 0, dur)
pointObj.save(join(rootOutputPath, originalPitchFN))

# 2nd - get region to manipulate.  Let's make the subject more emphatic!
tg = tgio.openTextgrid(join(root, "mary1.TextGrid"))
tier = tg.tierDict["words"]
start, stop, _ = tier.entryList[0]  # Getting info for the first word

targetPitchList = [(timeV, pitchV) for timeV, pitchV in pitchList
                   if timeV >= start and timeV <= stop]

# 3rd - make manipulation
accent = modify_pitch_accent.PitchAccent(targetPitchList)
accent.addPlateau(0.05)  # Peak is dragged out for 0.05 seconds
accent.adjustPeakHeight(60)  # Plateau is raised by 60 hz
예제 #6
0
def splitAudioOnTier(wavFN, tgFN, tierName, outputPath,
                     outputTGFlag=False, nameStyle=None,
                     noPartialIntervals=False, silenceLabel=None):
    '''
    Outputs one subwav for each entry in the tier of a textgrid
    
    outputTGFlag: If True, outputs paired, cropped textgrids
                  If is type str (a tier name), outputs a paired, cropped
                  textgrid with only the specified tier
    nameStyle: if 'append': append interval label to output name
               if 'append_no_i': append label but not interval to output name
               if 'label': output name is the same as label
               if None: output name plus the interval number
    noPartialIntervals: if True: intervals in non-target tiers that are
                                  not wholly contained by an interval in
                                  the target tier will not be included in
                                  the output textgrids
    silenceLabel: the label for silent regions.  If silences are unlabeled
                  intervals (i.e. blank) then leave this alone.  If silences
                  are labeled using praat's "annotate >> to silences"
                  then this value should be "silences"
    '''
    if not os.path.exists(outputPath):
        os.mkdir(outputPath)
    
    if noPartialIntervals is True:
        mode = 'strict'
    else:
        mode = 'truncated'
    
    tg = tgio.openTextgrid(tgFN)
    entryList = tg.tierDict[tierName].entryList
    
    if silenceLabel is not None:
        entryList = [entry for entry in entryList
                     if entry[2] != silenceLabel]
    
    # Build the output name template
    name = os.path.splitext(os.path.split(wavFN)[1])[0]
    orderOfMagnitude = int(math.floor(math.log10(len(entryList))))
    
    # We want one more zero in the output than the order of magnitude
    outputTemplate = "%s_%%0%dd" % (name, orderOfMagnitude + 1)
    
    firstWarning = True
    
    # If we're using the 'label' namestyle for outputs, all of the
    # interval labels have to be unique, or wave files with those
    # labels as names, will be overwritten
    if nameStyle == 'label':
        wordList = [word for _, _, word in entryList]
        multipleInstList = []
        for word in set(wordList):
            if wordList.count(word) > 1:
                multipleInstList.append(word)
        
        if len(multipleInstList) > 0:
            instListTxt = "\n".join(multipleInstList)
            print(("Overwriting wave files in: %s\n" +
                   "Intervals exist with the same name:\n%s")
                  % (outputPath, instListTxt))
            firstWarning = False
    
    # Output wave files
    outputFNList = []
    wavQObj = audioio.WavQueryObj(wavFN)
    for i, entry in enumerate(entryList):
        start, stop, label = entry
        
        # Resolve output name
        outputName = outputTemplate % i
        if nameStyle == "append":
            outputName += "_" + label
        elif nameStyle == "append_no_i":
            outputName = name + "_" + label
        elif nameStyle == "label":
            outputName = label
        
        outputFNFullPath = join(outputPath, outputName + ".wav")

        if os.path.exists(outputFNFullPath) and firstWarning:
            print(("Overwriting wave files in: %s\n" +
                   "Files existed before or intervals exist with " +
                   "the same name:\n%s")
                  % (outputPath, outputName))
        
        frames = wavQObj.getFrames(start, stop)
        wavQObj.outputModifiedWav(frames, outputFNFullPath)
        
        outputFNList.append((start, stop, outputName + ".wav"))
        
        # Output the textgrid if requested
        if outputTGFlag is not False:
            subTG = tg.crop(start, stop, mode, True)
            
            if isinstance(outputTGFlag, str):
                for tierName in subTG.tierNameList:
                    if tierName != outputTGFlag:
                        subTG.removeTier(tierName)
            
            subTG.save(join(outputPath, outputName + ".TextGrid"))
    
    return outputFNList