예제 #1
0
def findScoreByPitchThreshold(material, thresholdPitch, lowHigh):
    '''list, int, str --> [music21.stream.Score]
    It takes the list returned by the collectMaterial function, a pitch midi
    value, and the string "low" or "high" to look for those scores that contain
    pitchs lower or higher than the given threshold.
    '''

    scores = []

    for score in material:
        # Loading the score to get the parts list
        scorePath = score[0]
        scoreName = scorePath.split('/')[-1]
        loadedScore = converter.parse(scorePath)
        print(scoreName, 'parsed')
        parts = jS.findVoiceParts(loadedScore)
        # Work with each part
        for partIndex in range(1, len(score)):
            if len(score[partIndex]) == 0: continue  # Skip part if it's empty
            # Get the notes from the current part
            part = parts[partIndex - 1]
            notes = part.flat.notes.stream()
            # Find segments to analyze in the current part
            for startEnd in score[partIndex]:
                start = startEnd[0]
                end = startEnd[1]
                segment = notes.getElementsByOffset(start, end)
                ###############################################################
                ## Change here so that it returns scores with the notes      ##
                ## beyond the threshold colored in red.                      ##
                ###############################################################
                segmentAmbitus = segment.analyze('ambitus')
                ambitusStart = segmentAmbitus.noteStart.midi
                ambitusEnd = segmentAmbitus.noteEnd.midi
                if lowHigh == 'low':
                    if ambitusStart < pitch.Pitch(thresholdPitch).midi:
                        if scoreName not in scores:
                            scores.append(scoreName)
                if lowHigh == 'high':
                    if ambitusEnd > pitch.Pitch(thresholdPitch).midi:
                        if scoreName not in scores:
                            scores.append(scoreName)

    print('Done!')

    return scores
예제 #2
0
def getAmbitus(material):
    '''list --> music21.interval.Interval
    
    It takes the list returned by the collectMaterial function, and returns an
    interval from the lowest note found to the highest note found.
    '''

    ambitusStart = None
    ambitusEnd = None

    for score in material:
        # Loading the score to get the parts list
        scorePath = score[0]
        scoreName = scorePath.split('/')[-1]
        loadedScore = converter.parse(scorePath)
        print(scoreName, 'parsed')
        parts = jS.findVoiceParts(loadedScore)
        # Work with each part
        for partIndex in range(1, len(score)):
            if len(score[partIndex]) == 0: continue  # Skip part if it's empty
            # Get the notes from the current part
            part = parts[partIndex - 1]
            notes = part.flat.notes.stream()
            # Find segments to analyze in the current part
            for startEnd in score[partIndex]:
                start = startEnd[0]
                end = startEnd[1]
                segment = notes.getElementsByOffset(start, end)
                segmentAmbitus = segment.analyze('ambitus')
                if ambitusStart == None and ambitusEnd == None:
                    ambitusStart = segmentAmbitus.noteStart
                    ambitusEnd = segmentAmbitus.noteEnd
                else:
                    if segmentAmbitus.noteStart.midi < ambitusStart.midi:
                        ambitusStart = segmentAmbitus.noteStart
                    if segmentAmbitus.noteEnd.midi > ambitusEnd.midi:
                        ambitusEnd = segmentAmbitus.noteEnd

    ambitusInterval = interval.Interval(ambitusStart, ambitusEnd)

    print('Ambitus:', ambitusInterval.niceName + ', from',
          ambitusStart.nameWithOctave, 'to', ambitusEnd.nameWithOctave)

    return ambitusInterval
예제 #3
0
def findScoreByPitch(material, pitchList):
    '''
    '''

    scores = []

    for score in material[1:]:
        showScore = False
        pitchesFound = {}
        # Loading the score to get the parts list
        scorePath = score[0]
        scoreName = scorePath.split('/')[-1]
        loadedScore = converter.parse(scorePath)
        print(scoreName, 'parsed')
        parts = jS.findVoiceParts(loadedScore)
        # Work with each part
        for partIndex in range(1, len(score)):
            if len(score[partIndex]) == 0: continue  # Skip part if it's empty
            # Get the notes from the current part
            part = parts[partIndex - 1]
            notes = part.flat.notes.stream()
            # Find segments to analyze in the current part
            for startEnd in score[partIndex]:
                start = startEnd[0]
                end = startEnd[1]
                segment = notes.getElementsByOffset(start, end)
                for n in segment:
                    noteName = n.nameWithOctave
                    if noteName in pitchList:
                        n.color = 'red'
                        pitchesFound[noteName] = pitchesFound.get(noteName,
                                                                  0) + 1
                        showScore = True
                        if scorePath not in scores:
                            scores.append(scorePath)
        if showScore:
            for p in pitchesFound:
                print('\t' + str(pitchesFound[p]), 'samples of', p,
                      'found in this score')
            print('\tShowing', scoreName)
            loadedScore.show()

    return (scores)
예제 #4
0
def findLine(material, inputScore, patterns, a, b):
    '''list, list, list, int, int
    Inputs are the material, input score and patterns lists, and the index of
    the pattern and occurrence in the patterns list.
    '''
    line = patterns[a][b]
    loc = line[-1][0]
    init = line[-1][1]
    print('Original line:')
    originalLine = inputScore[loc]
    for n in originalLine:
        print(n)
    print('Found pattern:')
    for n in line:
        print(n)
    x = material[-1][loc]
    score = material[x[0]][0]
    segment = material[x[0]][x[1]][x[2]]
    segStart = float(segment[0])
    segEnd = float(segment[1])
    s = converter.parse(score)
    print(score.split('/')[-1], 'parsed')
    parts = jS.findVoiceParts(s)
    part = parts[x[1] - 1]
    notes = part.flat.notesAndRests.stream()
    seg2show = notes.getElementsByOffset(segStart, segEnd)
    i = 0
    while i < init:
        n = seg2show[i]
        i += 1
        if (n.tie != None) and (n.tie.type != 'start'):
            init += 1
    jump = 0
    for j in range(len(line) - 1):
        n = seg2show[init + j + jump]
        if (n.tie != None) and (n.tie.type != 'start'):
            n.color = 'red'
            jump += 1
        else:
            n.color = 'red'
    seg2show.show()
예제 #5
0
def showPatternsFromPickle(lyricsData, materialFile, inputScoreFile,
                           resultsFile):
    '''
    '''

    with open(lyricsData, 'r', encoding='utf-8') as f:
        data = f.readlines()

    with open(materialFile, 'rb') as f:
        material = pickle.load(f)

    with open(inputScoreFile, 'rb') as f:
        inputScore = pickle.load(f)

    with open(resultsFile, 'rb') as f:
        patterns = pickle.load(f)

    print(len(patterns), 'patterns to show')

    dataDict = {}
    currentScore = ''

    for l in data:
        strInfo = l.strip().split(',')
        score = strInfo[0]
        if score != '':
            currentScore = score
            dataDict[currentScore] = [[]]
            if 'Part' in l: continue
        else:
            if 'Part' in l:
                dataDict[currentScore].append([])
                continue
        info = strInfo[1] + ', ' + strInfo[2] + ', ' + strInfo[
            3] + ', ' + strInfo[4]
        start = strInfo[6]
        end = strInfo[7]
        dataDict[currentScore][-1].append([start, end, info])

    ks = key.KeySignature(4)

    for i in range(len(patterns)):
        pat = patterns[i]
        print('\nDisplaying pattern', i + 1, 'with', len(pat), 'occurrences')
        s1 = stream.Score()
        s1.insert(0, metadata.Metadata(movementName='Pattern ' + str(i + 1)))
        for j in range(len(pat)):
            occ = pat[j]
            locator = occ[-1]
            line = locator[0]
            init = locator[1]
            # Chek if the occurrence retrieved coincides with a fragment of the
            # input score
            origLine = inputScore[line]
            for k in range(len(occ) - 1):
                if occ[k] != origLine[k + init]:
                    print(origLine)
                    print(occ)
                    raise Exception('No match in result ' + str(i) + ', ' +
                                    str(j))
            lineCoordinates = material[-1][line]
            s = lineCoordinates[0]
            p = lineCoordinates[1]
            l = lineCoordinates[2]
            scorePath = material[s][0]
            segStart = material[s][p][l][0]
            segEnd = material[s][p][l][1]

            s2 = converter.parse(scorePath)
            parts = jS.findVoiceParts(s2)
            part = parts[p - 1]
            notes = part.flat.notesAndRests.stream()
            seg2red = notes.getElementsByOffset(segStart, segEnd)
            newInit = 0
            while newInit < init:
                note2check = seg2red[newInit]
                newInit += 1
                if (note2check.tie != None) and (note2check.tie.type !=
                                                 'start'):
                    init += 1
            tieJump = 0  # It stores how many tied notes are present
            for n in range(len(occ) - 1):
                note2red = seg2red[n + newInit + tieJump]
                while (note2red.tie != None) and (note2red.tie.type !=
                                                  'start'):
                    tieJump += 1
                    note2red = seg2red[n + newInit + tieJump]
                if note2red.isRest:
                    noteName = note2red.name
                else:
                    noteName = note2red.nameWithOctave
                if noteName != occ[n][0]:
                    print('ERROR: An exception will be raised')
                    findLine(material, inputScore, patterns, i, j)
                    raise Exception("Notes doesn't match at " + str(i) + ', ' +
                                    str(j) + ', ' + str(k) + ' (' + noteName +
                                    ', ' + occ[n][0] + ')')
                note2red.color = 'red'
                tieHop = n + newInit + tieJump + 1
                if note2red.tie != None:
                    while (seg2red[tieHop].tie != None
                           and seg2red[tieHop].tie.type != 'start'
                           and tieHop < len(occ)):
                        seg2red[tieHop].color = 'red'
                        tieHop += 1

            scoreName = scorePath.split('/')[-1]
            score = dataDict[scoreName]
            lineHop = 0
            dataLine = score[p - 1][lineHop]
            while not ((segStart >= float(dataLine[0])) and
                       (segStart < float(dataLine[1]))):
                lineHop += 1
                dataLine = score[p - 1][lineHop]

            segmentStart = float(dataLine[0])
            segmentEnd = float(dataLine[1])
            bsju = dataLine[2].split(', ')[2] + ', ' + dataLine[2].split(
                ', ')[3]
            referenceText = scoreName + ': ' + str(lineHop +
                                                   1) + ' (' + bsju + ')'
            te = expressions.TextExpression(referenceText)
            te.positionVertical = 30
            seg2add = notes.getElementsByOffset(segmentStart, segmentEnd)
            offsetHop = seg2add[0].offset
            for nn in seg2add:
                nn.offset += -offsetHop
            seg2add.insert(0, te)
            s1.insert(0, seg2add)

        for s1part in s1.parts:
            s1part.insert(0, ks)
        s1.makeNotation()
        s1.show()
예제 #6
0
def concatenateSegments(material, title=None):
    '''list --> music21.stream.Stream, list
    It takes the list returned by the collectMaterial function, and returns
    music21.stream.Stream with all the segments conatined in the material list
    concatenated into a single stave. It also returns the material list with a
    new list appended with the information to reconstruct the segments in their
    original scores from the new concatenated score. This new list contain a
    list of integers indicating:
    [start, end, score, part, segment]
    So that,
    - start: indicates the starting offset of a segment in the concatenated
             score
    - end: indicates the ending offset of a segment in the concatenated score
    - score: indicates the index in the material list of the score from where
             the original segment came from
    - part: indicates the index of the part in the previous score
    - segment: indicates the index of the segment as stored for the previous
               part in the material list
    If a title is given, it generates an xml file with the concatenated score
    and a pickle file with the material list
    '''

    # Gather search info to name the concatenated score
    searchString = ''
    searchInfo = material[0]
    # Add hangdang info
    hd = searchInfo['hd']
    if len(hd) != 2:
        for e in hd:
            searchString += e + '/'
        searchString = searchString[:-1] + ', '
    # Add shengqiang info
    sq = searchInfo['sq']
    if len(sq) != 2:
        for e in sq:
            searchString += e + '/'
        searchString = searchString[:-1] + ', '
    # Add banshi info
    bs = searchInfo['bs']
    if len(bs) != 8:
        for e in bs:
            searchString += e + '/'
        searchString = searchString[:-1] + ', '
    # Add ju info
    ju = searchInfo['ju']
    if len(ju) != 4:
        for e in ju:
            searchString += e + '/'
        searchString = searchString[:-1]

    concatenatedScore = stream.Stream()
    concatenatedSegments = []

    accumulatedOffset = 0

    for scoreIndex in range(1, len(material)):
        score = material[scoreIndex]
        scorePath = score[0]
        scoreName = scorePath.split('/')[-1]
        loadedScore = converter.parse(scorePath)
        print(scoreName, 'parsed')
        parts = jS.findVoiceParts(loadedScore)
        # Work with each part
        for partIndex in range(1, len(score)):
            if len(score[partIndex]) == 0: continue  # Skip part if it's empty
            # Get the notes from the current part
            part = parts[partIndex - 1]
            notes = part.flat.notesAndRests.stream()

            # Find segments to analyze in the current part
            for segmentIndex in range(len(score[partIndex])):
                startEnd = score[partIndex][segmentIndex]
                start = startEnd[0]
                end = startEnd[1]
                segment = notes.getElementsByOffset(start, end)
                # Reassigning offsets
                newSegment = [accumulatedOffset]
                startingOffset = segment[0].offset
                endingOffset = segment[-1].offset
                for n in segment:
                    n.offset += -startingOffset + accumulatedOffset
                    concatenatedScore.append(n)
                accumulatedOffset += (endingOffset - startingOffset)
                newSegment.append(accumulatedOffset)
                newSegment.extend([scoreIndex, partIndex, segmentIndex])
                accumulatedOffset += segment[-1].quarterLength
                concatenatedSegments.append(newSegment)

    extendedMaterial = copy.deepcopy(material)
    extendedMaterial.append(concatenatedSegments)

    # Check that the newSegments are equally long to the original segments:
    for newSegment in extendedMaterial[-1]:
        newSegmentStart = newSegment[0]
        newSegmentEnd = newSegment[1]
        length1 = newSegmentEnd - newSegmentStart
        score = newSegment[2]
        part = newSegment[3]
        segment = newSegment[4]
        originalSegment = extendedMaterial[score][part][segment]
        originalSegmentStart = originalSegment[0]
        originalSegmentEnd = originalSegment[1]
        length2 = originalSegmentEnd - originalSegmentStart
        if length1 != length2:
            print('Possible error with ' + extendedMaterial[score][0] +
                  ', part ' + str(part) + ', segment ' +
                  str(extendedMaterial[score][part][segment]) +
                  ', and the new segment ' + str(newSegment[:2]))

    if title != None:
        print('Segments concatenated\nCreating files')
        concatenatedScore.insert(0, metadata.Metadata())
        concatenatedScore.title = title
        concatenatedScore.write(fp=title + '.xml')
        with open(title + '.pkl', 'wb') as f:
            pickle.dump(extendedMaterial, f, protocol=2)

    print('Done!')

    return concatenatedScore, extendedMaterial
예제 #7
0
def recodeScore(material, title=None, graceNoteValue=2.0, noteName='pitch'):
    '''
    '''

    # Check that the given noteName is valid:
    if noteName not in ['pitch', 'midi']:
        raise Exception('The given noteName is invalid')

    print('The duration unit is a 64th note')

    print('The duration value for grace notes is ' + str(graceNoteValue) +
          ' duration units')

    # List the recoded score
    recodedScore = []

    # Store information for line retrieval
    lineInfo = []

    for scoreIndex in range(1, len(material)):
        score = material[scoreIndex]
        scorePath = score[0]
        scoreName = scorePath.split('/')[-1]
        loadedScore = converter.parse(scorePath)
        print(scoreName, 'parsed')
        parts = jS.findVoiceParts(loadedScore)
        # Work with each part
        for partIndex in range(1, len(score)):
            if len(score[partIndex]) == 0: continue  # Skip part if it's empty
            # Get the notes from the current part
            part = parts[partIndex - 1]
            notes = part.flat.notesAndRests.stream()
            # Find segments to analyze in the current part
            for segmentIndex in range(len(score[partIndex])):
                startEnd = score[partIndex][segmentIndex]
                start = startEnd[0]
                end = startEnd[1]
                segment = notes.getElementsByOffset(start, end)
                # For validation
                segmentDuration = 0
                for n in segment:
                    segmentDuration += n.quarterLength * 16
                if segment[-1].isRest:
                    segmentDuration += -segment[-1].quarterLength * 16
                    r = -2
                    while segment[r].quarterLength == 0:
                        segmentDuration += graceNoteValue
                        r += -1
                if segment[-1].quarterLength == 0:
                    segmentDuration += graceNoteValue

                # START RECODING
                line = []
                lineInfo.append([scoreIndex, partIndex, segmentIndex])
                graceNote = 0  # It stores the accumulated dur of grace notes
                # to be substracted
                notePreGrace = None  # It stores the index of the note before
                # grace notes found
                includeLyric = True  # Check if there are several syllables into
                # brackets that shouldn't be included
                lyricAdjustment = 0  # Stores how many grace notes back the
                # lyric should be added
                for i in range(len(segment)):
                    n = segment[i]
                    # Check if n is note or rest
                    if n.isRest:
                        name = n.name
                        dur = n.quarterLength * 16
                        lyr = False
                    else:  # If it is a note
                        # Check if it is a grace note
                        if n.quarterLength == 0:  # It is a grace note, then
                            # Set name
                            if noteName == 'pitch':
                                name = n.nameWithOctave
                            elif noteName == 'midi':
                                name = n.pitch.midi
                            # Set duration with the value given
                            dur = graceNoteValue
                            # Accumulate grace note value to be subtracted
                            graceNote += graceNoteValue
                            # Store the index of the previous note, if there is
                            # one and is not a grace note
                            if (notePreGrace == None) and (len(line) > 0):
                                notePreGrace = len(line) - 1
                            # Set lyric
                            lyr = False
                            # Update lyricAdjustment
                            lyricAdjustment += -1
                        else:
                            # If it's not a grace note, then
                            # Set name
                            if noteName == 'pitch':
                                name = n.nameWithOctave
                            elif noteName == 'midi':
                                name = n.pitch.midi

                            # Set duration
                            currentNoteDur = n.quarterLength * 16
                            # Check if there is some grace note value to be
                            # subtracted
                            if graceNote > 0:
                                # There is grace note(s) duration to be subtracted
                                if n.hasLyrics():
                                    # Subtract grace note value from the current
                                    # note.
                                    # But check first if its duration is bigger
                                    # than the one of the grace note(s)
                                    if currentNoteDur > graceNote:
                                        dur = currentNoteDur - graceNote
                                    else:
                                        # Try to substract it from previous note
                                        if notePreGrace != None:
                                            # There is a previous note...
                                            lastNote = line[notePreGrace]
                                            lastNoteDur = lastNote[1]
                                            if lastNoteDur > graceNote:
                                                # ... and its duration is bigger
                                                # than the grace note(s) duration
                                                lastNote[1] += -graceNote
                                                dur = currentNoteDur
                                            else:
                                                # But if not, adjust
                                                adjustment = 0
                                                for j in range(
                                                        notePreGrace + 1, i):
                                                    note2adjust = line[j]
                                                    note2adjust[1] += -1
                                                    adjustment += 1
                                                dur = (currentNoteDur -
                                                       graceNote + adjustment)
                                        else:
                                            # There is no previous note, so adjust
                                            adjustment = 0
                                            for j in range(i):
                                                note2adjust = line[j]
                                                note2adjust[1] += -1
                                                adjustment += 1
                                            dur = (currentNoteDur - graceNote +
                                                   adjustment)
                                else:
                                    # Current note has no lyrics, the grace note(s)
                                    # duration is subtracted from the previous note
                                    # But check first if its duration is bigger
                                    # than the one of the grace note(s)
                                    lastNote = line[notePreGrace]
                                    lastNoteDur = lastNote[1]
                                    if lastNoteDur > graceNote:
                                        # It is bigger, duration of grace note(s)
                                        # subtracted from previous note
                                        lastNote[1] += -graceNote
                                        dur = currentNoteDur
                                    else:
                                        # It is not bigger
                                        # Check if the current note duration is
                                        # bigger than the grace note(s) duration
                                        if currentNoteDur > graceNote:
                                            # It is bigger, so subtract
                                            dur = currentNoteDur - graceNote
                                        else:
                                            # It is not bigger, so adjust
                                            adjustment = 0
                                            for j in range(notePreGrace, i):
                                                note2adjust = line[j]
                                                note2adjust[1] += -1
                                                adjustment += 1
                                            lastNote[1] += (-graceNote +
                                                            adjustment)
                                            dur = currentNoteDur
                                    # Set lyricAdjustment to 0
                                    lyricAdjustment = 0
                            else:
                                # There is no grace note(s) duration to subtract
                                dur = currentNoteDur

                            #Check if it has a tie
                            if n.tie != None:
                                if n.tie.type != 'start':
                                    # Check if there is a grace note
                                    if graceNote > 0:
                                        # There is a grace note, so current note
                                        # counts as not tied
                                        dur = currentNoteDur
                                    else:
                                        # There is no grace note, so add the dur
                                        # to the previous tied note
                                        line[-1][1] += currentNoteDur
                                        continue

                            # Set lyric
                            if n.hasLyrics():
                                # Check if the lyric is a padding syllable
                                if ('(' in n.lyric) and (')' in n.lyric):
                                    lyr = False
                                elif ('(' in n.lyric) and (')' not in n.lyric):
                                    lyr = False
                                    includeLyric = False
                                elif ('(' not in n.lyric) and (')' in n.lyric):
                                    lyr = False
                                    includeLyric = True
                                else:
                                    if includeLyric:
                                        # It is not a padding syllable
                                        if lyricAdjustment == 0:
                                            # It has no grace notes:
                                            lyr = True
                                        else:
                                            # It has grace note(s):
                                            line[lyricAdjustment][2] = True
                                            lyr = False
                                    else:
                                        lyr = False
                            else:
                                lyr = False

                            # Set all counters to start mode
                            notePreGrace = None
                            graceNote = 0
                            lyricAdjustment = 0

                    if dur <= 0:
                        pos = str(n.offset)
                        message = ('\tDuration ' + str(dur) + ' in ' +
                                   scoreName + ', ' + pos)
                        print(message)
                    line.append([name, dur, lyr])

                # Check if last note is a rest
                if line[-1][0] == 'rest':
                    line.pop(-1)

                # For validation:
                lineDuration = 0
                for n in line:
                    lineDuration += n[1]
                if segmentDuration != lineDuration:
                    print("\tDurations don't match at line", len(recodedScore))
                    print("\tSegment length: " + str(segmentDuration) +
                          ", line length: " + str(lineDuration))
                recodedScore.append(line)

    # Extend material list
    if len(lineInfo) != len(recodedScore):
        print('Possible problem with the information for line retrieval')
    extendedMaterial = copy.deepcopy(material)
    extendedMaterial.append(lineInfo)

    # Dump the list into a pickle file
    if title != None:
        with open(title, 'wb') as f:
            pickle.dump(recodedScore, f, protocol=2)
        with open(title[:-4] + '_material.pkl', 'wb') as f:
            pickle.dump(extendedMaterial, f, protocol=2)

    return recodedScore, extendedMaterial
예제 #8
0
def findCadentialNotes(judouMaterial, includeGraceNotes=True):
    '''
    '''

    cadNotCount = [{}, {}, {}]

    for score in judouMaterial[1:]:
        scorePath = score[0]
        loadedScore = converter.parse(scorePath)
        scoreName = scorePath.split('/')[-1]
        print(scoreName, 'parsed')
        parts = jS.findVoiceParts(loadedScore)
        # Work with each part
        for partIndex in range(1, len(score)):
            if len(score[partIndex]) == 0: continue  # Skip part if it's empty
            # Get the notes from the current part
            part = parts[partIndex - 1]
            notes = part.flat.notesAndRests.stream()
            # Find segments to analyze in the current part
            for segInd in range(len(score[partIndex])):
                startEnd = score[partIndex][segInd]
                start = startEnd[0]
                end = startEnd[1]
                segment = notes.getElementsByOffset(start, end)
                i = -1
                lastNote = segment[i]
                while lastNote.isRest:
                    i += -1
                    lastNote = segment[i]
                if includeGraceNotes:
                    cadenceNote = lastNote.nameWithOctave
                else:
                    while lastNote.quarterLength == 0:
                        print('Grace note omitted in ' + scoreName + ', ' +
                              str(partIndex))
                        i += -1
                        lastNote = segment[i]
                    cadenceNote = lastNote.nameWithOctave
                secInd = segInd % 3
                sec = cadNotCount[secInd]
                sec[cadenceNote] = sec.get(cadenceNote, 0) + 1

    noteNames = {}

    for secCount in cadNotCount:
        for noteName in secCount.keys():
            noteNames[pitch.Pitch(noteName).midi] = noteName

    sortedNoteNames = [noteNames[j] for j in sorted(noteNames.keys())]

    for secCount in cadNotCount:
        counts = np.array([k for k in secCount.values()])
        toPerCent = 100 / sum(counts)
        for noteName in secCount:
            secCount[noteName] = secCount[noteName] * toPerCent

    sortedValues = []

    for noteName in sortedNoteNames:
        row = []
        for secCount in cadNotCount:
            row.append(secCount.get(noteName, 0))
        sortedValues.append(np.array(row))


#    for i in range(len(cadNotCount)):
#        toDiscard, noteNames, noteCount = sortDict(cadNotCount[i])
#        noteCount = np.array(noteCount)
#        toPerCent = 100 / np.sum(noteCount)
#        notePerCent = noteCount * toPerCent

    return sortedNoteNames, sortedValues
예제 #9
0
def melodicDensity(material, includeGraceNotes=True, notesOrDuration='notes'):
    '''list --> box plot
    
    It takes the list returned by the collectMaterial function, and returns
    '''

    if notesOrDuration not in ['notes', 'duration']:
        raise Exception('The given value for notesOrDuration is not correct')

    syllables = []
    totalCount = []
    accumulatedCount = []

    for score in material[1:]:
        # Loading the score to get the parts list
        scorePath = score[0]
        scoreName = scorePath.split('/')[-1]
        loadedScore = converter.parse(scorePath)
        print(scoreName, 'parsed')
        localCount = []
        parts = jS.findVoiceParts(loadedScore)
        # Work with each part
        for partIndex in range(1, len(score)):
            if len(score[partIndex]) == 0: continue  # Skip part if it's empty
            # Get the notes from the current part
            part = parts[partIndex - 1]
            notes = part.flat.notesAndRests.stream()
            # Find segments to analyze in the current part
            for startEnd in score[partIndex]:
                start = startEnd[0]
                end = startEnd[1]
                segment = notes.getElementsByOffset(start, end)
                openParenthesis = False
                graceNote = False
                for i in range(len(segment)):
                    n = segment[i]
                    if notesOrDuration == 'notes':
                        value = 1
                    else:
                        value = n.quarterLength
                    if n.isRest: continue
                    if n.quarterLength == 0:
                        if not includeGraceNotes: continue
                        j = 1
                        while (i + j < len(segment)
                               and segment[i + j].quarterLength == 0):
                            j += 1
                        if i + j == len(segment): continue
                        n2 = segment[i + j]
                        if n2.hasLyrics():
                            if (('(' in n2.lyric) or (')' in n2.lyric)
                                    or openParenthesis):
                                localCount[-1] += value
                                accumulatedCount[-1] += value
                            else:
                                if graceNote:
                                    localCount[-1] += value
                                    accumulatedCount[-1] += value
                                else:
                                    localCount.append(value)
                                    accumulatedCount.append(value)
                                    syllables.append(n2.lyric)
                                    graceNote = True
                        else:
                            localCount[-1] += value
                            accumulatedCount[-1] += value
                    else:
                        if n.hasLyrics():
                            # Check if the lyric is a padding syllable
                            if ('(' in n.lyric) and (')' in n.lyric):
                                localCount[-1] += value
                                accumulatedCount[-1] += value
                            elif ('(' in n.lyric) and (')' not in n.lyric):
                                localCount[-1] += value
                                accumulatedCount[-1] += value
                                openParenthesis = True
                            elif ('(' not in n.lyric) and (')' in n.lyric):
                                localCount[-1] += value
                                accumulatedCount[-1] += value
                                openParenthesis = False
                            else:
                                if openParenthesis:
                                    localCount[-1] += value
                                    accumulatedCount[-1] += value
                                elif graceNote:
                                    localCount[-1] += value
                                    accumulatedCount[-1] += value
                                    graceNote = False
                                else:
                                    localCount.append(value)
                                    accumulatedCount.append(value)
                                    syllables.append(n.lyric)
                        else:
                            localCount[-1] += value
                            accumulatedCount[-1] += value
        totalCount.append(localCount)


#    for i in range(len(syllables)):
#        print(syllables[i], notesPerSyl[i])

    totalCount.append(accumulatedCount)

    #    notesPerSyl = np.array(notesPerSyl)

    xLabels = [str(i) for i in range(1, len(totalCount))]
    xLabels.append('Avg')

    plt.boxplot(totalCount)
    plt.xticks(range(1, len(totalCount) + 1), xLabels, fontsize=20)
    plt.yticks(fontsize=18)
    plt.axvline(x=len(totalCount) - 0.5, ls='--', color='red')
    plt.ylim(0, 27)
    plt.xlabel('Sample scores', fontsize=26)
    plt.ylabel('Duration per quarter note', fontsize=26)
    plt.tight_layout()
    plt.show()

    return totalCount
예제 #10
0
def intervalHistogram(material,
                      count='sum',
                      directedInterval=False,
                      silence2ignore=0.25,
                      ignoreGraceNotes=False,
                      makePlot=True):
    '''list --> , bar plot
    
    It takes the list returned by the collectMaterial function, and returns
    
    For the bar diagram to be plotted, the values can be normalised according
    to count:
    - if count=='sum', they are normalised to their summation,
    - if count=='max', they are normalised to their maximun value
    - if count=='abs', they are not normalised, but absolute values given    
    '''

    intervalCount = {}

    for score in material[1:]:
        # Loading the score to get the parts list
        scorePath = score[0]
        scoreName = scorePath.split('/')[-1]
        loadedScore = converter.parse(scorePath)
        print(scoreName, 'parsed')
        parts = jS.findVoiceParts(loadedScore)
        # Work with each part
        for partIndex in range(1, len(score)):
            if len(score[partIndex]) == 0: continue  # Skip part if it's empty
            # Get the notes from the current part
            part = parts[partIndex - 1]
            notes = part.flat.notesAndRests.stream()
            # Find segments to analyze in the current part
            for startEnd in score[partIndex]:
                start = startEnd[0]
                end = startEnd[1]
                segment = notes.getElementsByOffset(start, end)
                # Count intervals in the current segment
                # Find the last note that is not a grace note
                i = 1
                lastn = segment[-i]
                while lastn.quarterLength == 0:
                    i += 1
                    lastn = segment[-i]

                for j in range(len(segment) - i):
                    n1 = segment[j]
                    if n1.isRest: continue
                    if ignoreGraceNotes:
                        if n1.quarterLength == 0: continue
                    k = 1
                    while True:
                        n2 = segment[j + k]
                        if n2.isRest:
                            if n2.quarterLength <= silence2ignore:
                                k += 1
                            else:
                                n2 = None
                                break
                        elif (n2.quarterLength == 0) and (ignoreGraceNotes
                                                          == True):
                            j += 1
                        else:
                            break
                    if n2 == None: continue
                    intvl = interval.Interval(n1, n2)
                    if directedInterval:
                        intvlName = intvl.directedName
                    else:
                        intvlName = intvl.name
                    intervalCount[intvlName] = (
                        intervalCount.get(intvlName, 0) + 1)

    # Sorting intervals per size
    intvlNames = intervalCount.keys()
    toSort = {i: interval.Interval(i).semitones for i in intvlNames}
    sortedIntvl = sorted(toSort.items(), key=lambda x: x[1])
    xPositions = np.array([i[1] for i in sortedIntvl])
    # Check if there repeated positions
    for i in range(1, len(xPositions)):
        if xPositions[i] != xPositions[i - 1]: continue
        for j in range(i):
            xPositions[j] += -1
    xLabels = [i[0] for i in sortedIntvl]
    yValues = np.array([intervalCount[l] for l in xLabels])

    ## Setting the parameters for plotting
    yValues, limX, yLabel, col, h = plottingParameters(material, count,
                                                       yValues)

    if makePlot:
        # Start plotting
        print('Plotting...')

        # Setting x limits
        limX = None

        # Setting y limits
        limY = None
        if count == 'sum':
            if directedInterval:
                limY = [0, 0.27]
            else:
                limY = [0, 0.5]

        plotting(xPositions,
                 xLabels,
                 yValues,
                 limX=limX,
                 xLabel='Interval',
                 limY=limY,
                 yLabel=yLabel,
                 col=col,
                 h=h,
                 scaleGuides=True,
                 width=0.8)

    # List to return
    results = []
    for i in range(len(xLabels)):
        results.append([xLabels[i], yValues[i]])

    return results
예제 #11
0
def pitchHistogram(material, count='sum', countGraceNotes=True, makePlot=True):
    '''list --> dict, bar plot
    
    It takes the list returned by the collectMaterial function, and returns a
    dictionary with all the existing pitches' nameWithOctave as keys and its
    aggregated duration in quarterLengths as values.
    
    For the bar diagram to be plotted, the values can be normalised according
    to count:
    - if count=='sum', they are normalised to their summation,
    - if count=='max', they are normalised to their maximun value
    - if count=='abs', they are not normalised, but absolute values given
    
    If countGraceNotes==True, the grace notes will be counted with a duration
    value equivalent to the minimum one present in the analysed segments, but
    with a maximum value of 0.25. If countGraceNotes==False, grace notes will
    be ignored and not counted.
    '''

    pitchCount = {}

    for score in material[1:]:
        # Loading the score to get the parts list
        scorePath = score[0]
        scoreName = scorePath.split('/')[-1]
        loadedScore = converter.parse(scorePath)
        print(scoreName, 'parsed')
        parts = jS.findVoiceParts(loadedScore)
        # Work with each part
        for partIndex in range(1, len(score)):
            if len(score[partIndex]) == 0: continue  # Skip part if it's empty
            # Get the notes from the current part
            part = parts[partIndex - 1]
            notes = part.flat.notes.stream()

            # Set the duration of grace notes if needed
            if countGraceNotes:
                minDur = 0.25
                for n in notes:
                    noteDur = n.quarterLength
                    if noteDur != 0 and noteDur < minDur:
                        minDur = noteDur

            # Find segments to analyze in the current part
            for startEnd in score[partIndex]:
                start = startEnd[0]
                end = startEnd[1]
                segment = notes.getElementsByOffset(start, end)
                # Count pitches in the current segment
                for n in segment:
                    noteName = n.nameWithOctave
                    noteDur = n.quarterLength
                    if noteDur == 0:
                        if not countGraceNotes: continue
                        noteDur = minDur
                    pitchCount[noteName] = pitchCount.get(noteName,
                                                          0) + noteDur

    # Sorting duration per pitch class frequency
    pitches = pitchCount.keys()
    toSort = {p: pitch.Pitch(p).midi for p in pitches}
    sortedPitches = sorted(toSort.items(), key=lambda x: x[1])
    xPositions = np.array([p[1] for p in sortedPitches])
    xLabels = [p[0] for p in sortedPitches]
    yValues = np.array([pitchCount[l] for l in xLabels])

    # Setting the parameters for plotting
    yValues, limX, yLabel, col, h = plottingParameters(material, count,
                                                       yValues)

    if makePlot:
        # Start plotting
        print('Plotting...')

        # Setting y limits
        limY = None
        if count == 'sum':
            limY = [0, 0.31]

        plotting(xPositions,
                 xLabels,
                 yValues,
                 limX=limX,
                 xLabel='Pitch',
                 limY=limY,
                 yLabel=yLabel,
                 col=col,
                 h=h,
                 scaleGuides=True,
                 width=0.8)

    # List to return
    results = []
    for i in range(len(xLabels)):
        results.append([xLabels[i], yValues[i]])

    return results
예제 #12
0
def findScoreByInterval(material,
                        intvlList,
                        directedInterval=False,
                        silence2ignore=0.25,
                        ignoreGraceNotes=False):
    '''
    '''
    for score in material[1:]:
        showScore = False
        intvlsFound = {}
        # Loading the score to get the parts list
        scorePath = score[0]
        scoreName = scorePath.split('/')[-1]
        loadedScore = converter.parse(scorePath)
        print(scoreName, 'parsed')
        parts = jS.findVoiceParts(loadedScore)
        # Work with each part
        for partIndex in range(1, len(score)):
            if len(score[partIndex]) == 0: continue  # Skip part if it's empty
            # Get the notes from the current part
            part = parts[partIndex - 1]
            notes = part.flat.notesAndRests.stream()
            # Find segments to analyze in the current part
            for startEnd in score[partIndex]:
                start = startEnd[0]
                end = startEnd[1]
                segment = notes.getElementsByOffset(start, end)
                # Count intervals in the current segment
                # Find the last note that is not a grace note
                i = 1
                lastn = segment[-i]
                while lastn.quarterLength == 0:
                    i += 1
                    lastn = segment[-i]

                for j in range(len(segment) - i):
                    n1 = segment[j]
                    if n1.isRest: continue
                    if ignoreGraceNotes:
                        if n1.quarterLength == 0: continue
                    k = 1
                    while True:
                        n2 = segment[j + k]
                        if n2.isRest:
                            if n2.quarterLength <= silence2ignore:
                                k += 1
                            else:
                                n2 = None
                                break
                        elif (n2.quarterLength == 0) and (ignoreGraceNotes
                                                          == True):
                            j += 1
                        else:
                            break
                    if n2 == None: continue
                    currentIntvl = interval.Interval(n1, n2)
                    if directedInterval:
                        intvlName = currentIntvl.directedName
                    else:
                        intvlName = currentIntvl.name
                    if intvlName in intvlList:
                        n1.color = 'red'
                        n2.color = 'red'
                        intvlsFound[intvlName] = intvlsFound.get(intvlName,
                                                                 0) + 1
                        showScore = True
        if showScore:
            for k in intvlsFound:
                print('\t' + str(intvlsFound[k]), 'samples of', k,
                      'found in this score')
            print('\tShowing', scoreName)
            loadedScore.show()


###############################################################################
###############################################################################
## TO IMPROVE                                                                ##
## 1. Keep the banshi information in material, so that the graceNoteDur can  ##
##    be adjusted accordingly.                                               ##
## 2. Check if the arguments given to collectMaterial make no match at all   ##
##    and raise a message                                                    ##
###############################################################################
###############################################################################