Ejemplo n.º 1
0
    def _createRecipTokenFromDuration(duration: HumNumIn) -> HumdrumToken:
        dur: HumNum = opFrac(duration)
        dur = opFrac(dur / opFrac(4))  # convert to quarter note units

        durFraction: Fraction = Fraction(dur)
        if durFraction.numerator == 0:
            # if the GridSlice is at the end of a measure, the
            # time between the starttime/endtime of the GridSlice should
            # be subtracted from the endtime of the current GridMeasure.
            return HumdrumToken('g')

        if durFraction.numerator == 1:
            return HumdrumToken(str(durFraction.denominator))

        if durFraction.numerator % 3 == 0:
            dotdur: HumNum = dur * opFrac(Fraction(2, 3))
            dotdurFraction: Fraction = Fraction(dotdur)
            if dotdurFraction.numerator == 1:
                return HumdrumToken(str(dotdurFraction.denominator) + '.')

        # try to fit to two dots here

        # try to fit to three dots here

        return HumdrumToken(
            str(durFraction.denominator) + '%' + str(durFraction.numerator))
Ejemplo n.º 2
0
    def transferSidesFromStaff(line: HumdrumLine, staff: GridStaff,
                               emptyStr: str, maxxcount: int, maxdcount: int,
                               maxvcount: int):
        sides: GridSide = staff.sides
        vcount: int = sides.verseCount

        # XMLID
        if maxxcount > 0:
            xmlId: HumdrumToken = sides.xmlId
            if xmlId is not None:
                line.appendToken(xmlId)
            else:
                line.appendToken(HumdrumToken(emptyStr))

        # DYNAMICS
        if maxdcount > 0:
            dynamics: HumdrumToken = sides.dynamics
            if dynamics is not None:
                line.appendToken(dynamics)
            else:
                line.appendToken(HumdrumToken(emptyStr))

        # VERSES
        for i in range(0, vcount):
            verse: HumdrumToken = sides.getVerse(i)
            if verse is not None:
                line.appendToken(verse)
            else:
                line.appendToken(HumdrumToken(emptyStr))

        for i in range(vcount, maxvcount):
            line.appendToken(HumdrumToken(emptyStr))
Ejemplo n.º 3
0
    def addLayoutParameter(self, associatedSlice: GridSlice,
                           partIndex: int, staffIndex: int, voiceIndex: int,
                           locomment: str) -> None:
        # add this '!LO:' string just before this associatedSlice
        if len(self.slices) == 0:
            # something strange happened: expecting at least one item in measure.
            # associatedSlice is supposed to already be in the measure.
            return

        associatedSliceIdx: t.Optional[int] = None
        if associatedSlice is None:
            # place at end of measure (associate with imaginary slice just off the end)
            associatedSliceIdx = len(self.slices)
        else:
            # find owning line (associatedSlice)
            foundIt: bool = False
            for associatedSliceIdx in range(len(self.slices) - 1, -1, -1):
                gridSlice: GridSlice = self.slices[associatedSliceIdx]
                if gridSlice is associatedSlice:
                    foundIt = True
                    break
            if not foundIt:
                # cannot find owning line (a.k.a. associatedSlice is not in this GridMeasure)
                return

        # see if the previous slice is a layout slice we can use
        prevIdx: int = associatedSliceIdx - 1
        prevSlice: GridSlice = self.slices[prevIdx]
        if prevSlice.isLocalLayoutSlice:
            prevStaff: GridStaff = prevSlice.parts[partIndex].staves[staffIndex]
            prevVoice: GridVoice = self._getIndexedVoice_AppendingIfNecessary(prevStaff.voices,
                                                                              voiceIndex)
            if prevVoice.token is None or prevVoice.token.text == '!':
                prevVoice.token = HumdrumToken(locomment)
                return

        # if we get here, we couldn't use the previous slice, so we need to insert
        # a new Layout slice to use, just before the associated slice.
        insertPoint: int = associatedSliceIdx
        newSlice: GridSlice

        if associatedSlice is not None:
            newSlice = GridSlice(self, associatedSlice.timestamp, SliceType.Layouts)
            newSlice.initializeBySlice(associatedSlice)
            self.slices.insert(insertPoint, newSlice)
        else:
            newSlice = GridSlice(self, self.timestamp + self.duration, SliceType.Layouts)
            newSlice.initializeBySlice(self.slices[-1])
            self.slices.append(newSlice)

        newStaff: GridStaff = newSlice.parts[partIndex].staves[staffIndex]
        newVoice: GridVoice = self._getIndexedVoice_AppendingIfNecessary(newStaff.voices,
                                                                         voiceIndex)
        newVoice.token = HumdrumToken(locomment)
Ejemplo n.º 4
0
    def createTokensFromLine(self) -> int:  # returns number of tokens created
        '''
        // delete previous tokens (will need to re-analyze structure
        // of file after this).
        '''
        self._tokens = []
        self._numTabsAfterToken = []

        if self.text == '':
            # one empty token
            token = HumdrumToken()
            token.ownerLine = self
            self._tokens = [token]
            self._numTabsAfterToken = [0]
            return 1

        if self.text.startswith('!!'):
            # global, so just one token for the whole line
            token = HumdrumToken(self.text)
            token.ownerLine = self
            self._tokens = [token]
            self._numTabsAfterToken = [0]
            return 1

        # tokenStrList: [str] = self.text.split('\t')
        # for tokenStr in tokenStrList:
        #     token = HumdrumToken(tokenStr)
        #     token.ownerLine = self
        #     self._tokens.append(token)
        #     self._numTabsAfterToken.append(1)

        for m in re.finditer(r'([^\t]+)(\t*)', self.text):
            # m is a match object containing two groups: first the token, then any trailing tabs
            tokenStr = m.group(1)
            if tokenStr is None:
                break

            tabsStr = m.group(2)
            if tabsStr is None:
                numTabsAfterThisToken = 0
            else:
                numTabsAfterThisToken = len(tabsStr)

            token = HumdrumToken(tokenStr)
            token.ownerLine = self
            self._tokens.append(token)
            self._numTabsAfterToken.append(numTabsAfterThisToken)

        return len(self._tokens)
Ejemplo n.º 5
0
    def addToken(self, tok: Union[HumdrumToken, str], parti: int, staffi: int,
                 voicei: int):
        if isinstance(tok, str):
            tok = HumdrumToken(tok)

        if not 0 <= parti < len(self.parts):
            raise HumdrumInternalError(
                f'Error: part index {parti} is out of range(0, {len(self.parts)})'
            )

        if staffi < 0:
            raise HumdrumInternalError(f'Error: staff index {staffi} < 0')

        part: GridPart = self.parts[parti]

        # fill in enough staves to get you to staffi
        if staffi >= len(part.staves):
            for _ in range(len(part.staves), staffi + 1):
                part.staves.append(GridStaff())

        staff: GridStaff = part.staves[staffi]

        # fill in enough voices to get you to voicei
        if voicei >= len(staff.voices):
            for _ in range(len(staff.voices), voicei + 1):
                staff.voices.append(GridVoice())

        voice: GridVoice = staff.voices[voicei]

        # Ok, finally do what you came to do...
        voice.token = tok
Ejemplo n.º 6
0
 def appendToken(self,
                 token,
                 tabCount: int = 0):  # token can be HumdrumToken or str
     if isinstance(token, str):
         token = HumdrumToken(token)
     self._tokens.append(token)
     self._numTabsAfterToken.append(tabCount)
Ejemplo n.º 7
0
    def dataType(self):  # -> HumdrumToken
        if self._dataTypeTokenCached is not None:
            return self._dataTypeTokenCached

        from converter21.humdrum import HumdrumToken
        if self.ownerLine is None:
            return HumdrumToken('')

        tok = self.ownerLine.trackStart(self.track)
        if tok is None:
            return HumdrumToken('')

        # cache it
        self._dataTypeTokenCached = tok

        return tok
Ejemplo n.º 8
0
    def addToken(self, tok: t.Union[HumdrumToken, str], parti: int,
                 staffi: int, voicei: int) -> None:
        if isinstance(tok, str):
            tok = HumdrumToken(tok)

        if not 0 <= parti < len(self.parts):
            raise HumdrumInternalError(
                f'Error: part index {parti} is out of range(0, {len(self.parts)})'
            )

        if staffi < 0:
            raise HumdrumInternalError(f'Error: staff index {staffi} < 0')

        part: GridPart = self.parts[parti]

        # fill in enough staves to get you to staffi
        if staffi >= len(part.staves):
            for _ in range(len(part.staves), staffi + 1):
                part.staves.append(GridStaff())

        staff: GridStaff = part.staves[staffi]

        # fill in enough voices to get you to voicei
        if voicei >= len(staff.voices):
            for _ in range(len(staff.voices), voicei + 1):
                staff.voices.append(GridVoice())

        voice: t.Optional[GridVoice] = staff.voices[voicei]
        if t.TYPE_CHECKING:
            # because we just filled staff.voices[voicei] in with a GridVoice if necessary
            assert isinstance(voice, GridVoice)

        # Ok, finally do what you came to do...
        voice.token = tok
Ejemplo n.º 9
0
    def token(self, newToken: Union[HumdrumToken, str]):
        if isinstance(newToken, HumdrumToken) or newToken is None:
            self._token = newToken
        elif isinstance(newToken, str):
            self._token = HumdrumToken(newToken)
        else:
            raise HumdrumInternalError(f'invalid type of token: {newToken}')

        self._isTransfered = False
Ejemplo n.º 10
0
 def insertToken(self, index: int, token,
                 tabCount: int):  # token can be HumdrumToken or str
     if isinstance(token, HumdrumToken):
         self._tokens.insert(index, token)
         self._numTabsAfterToken.insert(index, tabCount)
         return
     if isinstance(token, str):
         self._tokens.insert(index, HumdrumToken(token))
         self._numTabsAfterToken.insert(index, tabCount)
Ejemplo n.º 11
0
    def __init__(
        self,
        token: t.Optional[t.Union[HumdrumToken, str]] = None,
        duration: HumNumIn = opFrac(0)
    ) -> None:
        if isinstance(token, str):
            token = HumdrumToken(token)
        self._token: t.Optional[HumdrumToken] = token

        self._nextDur = opFrac(duration)
        #         self._prevDur = opFrac(0) # appears to be unused (never set to anything but zero)
        self._isTransfered: bool = False
Ejemplo n.º 12
0
    def addDynamicsLayoutParameters(self, associatedSlice: GridSlice,
                                    partIndex: int, staffIndex: int,
                                    locomment: str):
        if len(self.slices) == 0:
            # something strange happened: expecting at least one item in measure.
            return  # associatedSlice is supposed to already be in the measure

        # find owning line (associatedSlice)
        foundIt: bool = False
        associatedSliceIdx: int = None
        for associatedSliceIdx in range(len(self.slices) - 1, -1,
                                        -1):  # loop in reverse index order
            gridSlice: GridSlice = self.slices[associatedSliceIdx]
            if gridSlice is associatedSlice:
                foundIt = True
                break
        if not foundIt:
            # cannot find owning line (a.k.a. associatedSlice is not in this GridMeasure)
            return

        # see if the previous slice is a layout slice we can use
        prevIdx: int = associatedSliceIdx - 1
        prevSlice: GridSlice = self.slices[prevIdx]
        if prevSlice.isLocalLayoutSlice:
            prevStaff: GridStaff = prevSlice.parts[partIndex].staves[
                staffIndex]
            if prevStaff.dynamics is None:
                prevStaff.dynamics = HumdrumToken(locomment)
                return

        # if we get here, we couldn't use the previous slice, so we need to insert
        # a new Layout slice to use, just before the associated slice.
        insertPoint: int = associatedSliceIdx
        newSlice: GridSlice = GridSlice(self, associatedSlice.timestamp,
                                        SliceType.Layouts)
        newSlice.initializeBySlice(associatedSlice)
        self.slices.insert(insertPoint, newSlice)

        newStaff: GridStaff = newSlice.parts[partIndex].staves[staffIndex]
        newStaff.dynamics = HumdrumToken(locomment)
Ejemplo n.º 13
0
    def copyStructure(self, fromLine: 'HumdrumLine', nullStr: str) -> None:
        for fromToken in fromLine.tokens():
            newToken: HumdrumToken = HumdrumToken(nullStr)
            newToken.ownerLine = self
            newToken.copyStructure(fromToken)
            self._tokens.append(newToken)

        self.createLineFromTokens()
        # pylint: disable=protected-access
        self._numTabsAfterToken = fromLine._numTabsAfterToken
        self._rhythmAnalyzed = fromLine._rhythmAnalyzed
        # pylint: enable=protected-access
        self.ownerFile = fromLine.ownerFile
Ejemplo n.º 14
0
    def _createRecipTokenFromDuration(duration: HumNum) -> HumdrumToken:
        duration /= 4  # convert to quarter note units

        if duration.numerator == 0:
            # if the GridSlice is at the end of a measure, the
            # time between the starttime/endtime of the GridSlice should
            # be subtracted from the endtime of the current GridMeasure.
            return HumdrumToken('g')

        if duration.numerator == 1:
            return HumdrumToken(str(duration.denominator))

        if duration.numerator % 3 == 0:
            dotdur: HumNum = (duration * 2) / 3
            if dotdur.numerator == 1:
                return HumdrumToken(str(dotdur.denominator) + '.')

        # try to fit to two dots here

        # try to fit to three dots here

        return HumdrumToken(
            str(duration.denominator) + '%' + str(duration.numerator))
Ejemplo n.º 15
0
    def transferSidesFromPart(line: HumdrumLine, part: GridPart, emptyStr: str,
                              maxhcount: int, maxfcount: int):
        sides: GridSide = part.sides
        hcount: int = sides.harmonyCount

        # FIGURED BASS
        if maxfcount > 0:
            figuredBass: HumdrumToken = sides.figuredBass
            if figuredBass is not None:
                line.appendToken(figuredBass)
            else:
                line.appendToken(HumdrumToken(emptyStr))

        # HARMONY
        for _ in range(0, hcount):
            harmony: HumdrumToken = sides.harmony
            if harmony is not None:
                line.appendToken(harmony)
            else:
                line.appendToken(HumdrumToken(emptyStr))

        for _ in range(hcount, maxhcount):
            line.appendToken(HumdrumToken(emptyStr))
Ejemplo n.º 16
0
    def __init__(self,
                 token: Union[HumdrumToken, str] = None,
                 duration: HumNum = HumNum(0)):
        self._token: HumdrumToken = None
        if isinstance(token, HumdrumToken) or token is None:
            self._token = token
        elif isinstance(token, str):
            self._token = HumdrumToken(token)
        else:
            raise HumdrumInternalError(f'invalid type of token: {token}')

        self._nextDur = duration
        #         self._prevDur = HumNum(0) # appears to be unused (never set to anything but zero)
        self._isTransfered: bool = False
Ejemplo n.º 17
0
    def setVerse(self, index: int, token: Union[HumdrumToken, str]):
        if isinstance(token, str):
            # make it into a proper token
            token = HumdrumToken(token)

        if index == self.verseCount:
            self._verses.append(token)
        elif index < self.verseCount:
            # Insert in a slot which might already have a verse token
            self._verses[index] = token
        else:
            # add more than one verse spot, and insert verse:
            for _ in range(self.verseCount,
                           index + 1):  # verseCount through index, inclusive
                self._verses.append(None)
            self._verses[index] = token
Ejemplo n.º 18
0
    def setNullTokenLayer(self, layerIndex: int, sliceType: SliceType,
                          nextDur: HumNum):
        if sliceType == SliceType.Invalid:
            return
        if sliceType == SliceType.GlobalLayouts:
            return
        if sliceType == SliceType.GlobalComments:
            return
        if sliceType == SliceType.ReferenceRecords:
            return

        nullStr: str = ''
        if sliceType < SliceType.Data_:
            nullStr = '.'
        elif sliceType <= SliceType.Measure_:
            nullStr = '='
        elif sliceType <= SliceType.Interpretation_:
            nullStr = '*'
        elif sliceType <= SliceType.Spined_:
            nullStr = '!'
        else:
            raise HumdrumInternalError(
                f'!!STRANGE ERROR: {self}, SLICE TYPE: {sliceType}')

        if layerIndex < len(self.voices):
            if (self.voices[layerIndex] is not None
                    and self.voices[layerIndex].token is not None):
                if self.voices[layerIndex].token.text == nullStr:
                    # there is already a null data token here, so don't
                    # replace it.
                    return
                raise HumdrumExportError(
                    'Warning, existing token: \'{self.voices[layerIndex].token.text}\' where a null token should be.'
                )

        token: HumdrumToken = HumdrumToken(nullStr)
        self.setTokenLayer(layerIndex, token, nextDur)
Ejemplo n.º 19
0
    def __init__(
            self,
            line: str = '',
            asGlobalToken: bool = False,
            ownerFile=None  # HumdrumFile
    ) -> None:
        from converter21.humdrum import HumdrumFile
        super().__init__()  # initialize the HumHash fields

        '''
            _text: the line's text string
        '''
        if len(line) > 0 and line[-1] == '\n':
            # strip off any trailing LF
            line = line[:-1]

        self._text: str = line

        '''
        // owner: This is the HumdrumFile which manages the given line.
        '''
        self._ownerFile: HumdrumFile = ownerFile

        '''
        // m_lineindex: Used to store the index number of the HumdrumLine in
        // the owning HumdrumFile object.
        // This variable is filled by HumdrumFileStructure::analyzeLines().
        '''
        self._lineIndex: int = -1

        '''
        // m_tokens: Used to store the individual tab-separated token fields
        // on a line.  These are prepared automatically after reading in
        // a full line of text (which is accessed throught the string parent
        // class).  If the full line is changed, the tokens are not updated
        // automatically -- use createTokensFromLine().  Likewise the full
        // text line is not updated if any tokens are changed -- use
        // createLineFromTokens() in that case.  The second case is more
        // useful: you can read in a HumdrumFile, tweak the tokens, then
        // reconstruct the full line and print out again.
        // This variable is filled by HumdrumFile::read().
        // The contents of this vector should be deleted when deconstructing
        // a HumdrumLine object.
        '''
        self._tokens: t.List[HumdrumToken] = []
        if asGlobalToken:
            self._tokens = [HumdrumToken(line)]

        '''
        // m_tabs: Used to store a count of the number of tabs between
        // each token on a line.  This is the number of tabs after the
        // token at the given index (so no tabs before the first token).
        '''
        self._numTabsAfterToken: t.List[int] = []
        if asGlobalToken:
            self._numTabsAfterToken = [0]

        '''
        // m_duration: This is the "duration" of a line.  The duration is
        // equal to the minimum time unit of all durational tokens on the
        // line.  This also includes null tokens when the duration of a
        // previous note in a previous spine is ending on the line, so it is
        // not just the minimum duration on the line.
        // This variable is filled by HumdrumFileStructure::analyzeRhythm().
        '''
        self._duration: HumNum = -1.0

        '''
        // m_durationFromStart: This is the cumulative duration of all lines
        // prior to this one in the owning HumdrumFile object.  For example,
        // the first notes in a score start at time 0, If the duration of the
        // first data line is 1 quarter note, then the durationFromStart for
        // the second line will be 1 quarter note.
        // This variable is filled by HumdrumFileStructure::analyzeRhythm().
        '''
        self._durationFromStart: HumNum = -1.0

        '''
        // m_durationFromBarline: This is the cumulative duration from the
        // last barline to the current data line.
        // This variable is filled by HumdrumFileStructure::analyzeMeter().
        '''
        self._durationFromBarline: HumNum = -1.0

        '''
        // m_durationToBarline: This is the duration from the start of the
        // current line to the next barline in the owning HumdrumFile object.
        // This variable is filled by HumdrumFileStructure::analyzeMeter().
        '''
        self._durationToBarline: HumNum = -1.0

        '''
        // m_linkedParameters: List of Humdrum tokens which are parameters
        // (mostly only layout parameters at the moment)
        '''
        self._linkedParameters: t.List[HumdrumToken] = []

        '''
        // m_rhythm_analyzed: True if duration information from HumdrumFile
        // has been added to line.
        '''
        self._rhythmAnalyzed: bool = False

        '''
            We are also a HumHash, and that was initialized via super() above.
            But we want our default HumHash prefix to be '!!', not ''
        '''
        self.prefix: str = '!!'
Ejemplo n.º 20
0
    def token(self, newToken: t.Optional[t.Union[HumdrumToken, str]]) -> None:
        if isinstance(newToken, str):
            newToken = HumdrumToken(newToken)
        self._token = newToken

        self._isTransfered = False
Ejemplo n.º 21
0
 def insertToken(self, index: int, token: t.Union[HumdrumToken, str], tabCount: int = 0) -> None:
     if isinstance(token, str):
         token = HumdrumToken(token)
     self._tokens.insert(index, token)
     self._numTabsAfterToken.insert(index, tabCount)
Ejemplo n.º 22
0
 def appendToken(self, token: t.Union[HumdrumToken, str], tabCount: int = 0) -> None:
     if isinstance(token, str):
         token = HumdrumToken(token)
     self._tokens.append(token)
     self._numTabsAfterToken.append(tabCount)
Ejemplo n.º 23
0
    def transferTokens(self, outFile: HumdrumFile, recip: bool):
        line: HumdrumLine = HumdrumLine()
        voice: GridVoice = None
        emptyStr: str = '.'

        if self.isMeasureSlice:
            if len(self.parts) > 0:
                if len(self.parts[0].staves[0].voices) > 0:
                    voice = self.parts[0].staves[0].voices[0]
                    if voice.token is not None:
                        emptyStr = voice.token.text
                    else:
                        emptyStr = '=YYYYYY'
                else:
                    emptyStr = '=YYYYYY'
        elif self.isInterpretationSlice:
            emptyStr = '*'
        elif self.isLocalLayoutSlice:
            emptyStr = '!'
        elif not self.hasSpines:
            emptyStr = '???'

        if recip:
            token: HumdrumToken = None

            if self.isNoteSlice:
                token = self._createRecipTokenFromDuration(self.duration)
            elif self.isClefSlice:
                token = HumdrumToken('*')
                emptyStr = '*'
            elif self.isMeasureSlice:
                if len(self.parts[0].staves[0]) > 0:
                    voice = self.parts[0].staves[0].voices[0]
                    token = HumdrumToken(voice.token.text)
                else:
                    token = HumdrumToken('=XXXXX')
                emptyStr = token.text
            elif self.isInterpretationSlice:
                token = HumdrumToken('*')
                emptyStr = '*'
            elif self.isGraceSlice:
                token = HumdrumToken('q')
                emptyStr = '.'
            elif self.hasSpines:
                token = HumdrumToken('55')
                emptyStr = '!'

            if token is not None:
                if self.hasSpines:
                    line.appendToken(token)
                else:
                    token = None

        # extract the Tokens from each part/staff
        for p in range(len(self.parts) - 1, -1, -1):
            part = self.parts[p]
            if not self.hasSpines and p != 0:
                continue
            for s in range(len(part.staves) - 1, -1, -1):
                staff = part.staves[s]
                if not self.hasSpines and s != 0:
                    continue
                if len(staff.voices) == 0:
                    # 888: fix this later.  For now if there are no notes
                    # 888: ... on the staff, add a null token.  Fix so that
                    # 888: ... all open voices are given null tokens.
                    line.appendToken(HumdrumToken(emptyStr))
                else:
                    for voice in staff.voices:  # NOT reversed (voices different from parts/staves)
                        if voice is not None and voice.token is not None:
                            line.appendToken(voice.token)
                        else:
                            line.appendToken(HumdrumToken(emptyStr))

                if not self.hasSpines:
                    # Don't add sides to non-spined lines
                    continue

                maxxcount: int = self.getXmlIdCount(p, s)
                maxdcount: int = self.getDynamicsCount(p, s)
                maxvcount: int = self.getVerseCount(p, s)
                self.transferSidesFromStaff(line, staff, emptyStr, maxxcount,
                                            maxdcount, maxvcount)

            if not self.hasSpines:
                # Don't add sides to non-spined lines
                continue

            maxhcount: int = self.getHarmonyCount(p)
            maxfcount: int = self.getFiguredBassCount(p)
            self.transferSidesFromPart(line, part, emptyStr, maxhcount,
                                       maxfcount)

        outFile.appendLine(line)