示例#1
0
    def insert_custos(self, pname, oct, before_id, ulx, uly, lrx, lry):
        '''
        Insert a custos. Also add a bounding box
        for this element.
        '''

        # create custos
        custos = MeiElement("custos")
        if pname and oct:
            custos.addAttribute("pname", pname)
            custos.addAttribute("oct", oct)

        # insert the custos
        if before_id is None:
            # get last layer
            layers = self.mei.getElementsByName("layer")
            if len(layers):
                layers[-1].addChild(custos)
        else:
            before = self.mei.getElementById(str(before_id))
            parent = before.getParent()

            if parent and before:
                parent.addChildBefore(before, custos)

        # update the bounding box
        self.update_or_add_zone(custos, ulx, uly, lrx, lry)

        result = {"id": custos.getId()}
        return result
示例#2
0
    def insert_custos(self, pname, oct, before_id, ulx, uly, lrx, lry):
        '''
        Insert a custos. Also add a bounding box
        for this element.
        '''

        # create custos
        custos = MeiElement("custos")
        if pname and oct:
            custos.addAttribute("pname", pname)
            custos.addAttribute("oct", oct)

        # insert the custos
        before = self.mei.getElementById(before_id)

        # get layer element
        parent = before.getParent()

        if parent and before:
            parent.addChildBefore(before, custos)

        # update the bounding box
        self.update_or_add_zone(custos, ulx, uly, lrx, lry)

        result = {"id": custos.getId()}
        return result
示例#3
0
    def insert_clef(self, line, shape, pitch_info, before_id, ulx, uly, lrx, lry):
        '''
        Insert a doh or fah clef, with a given bounding box.
        Must also update pitched elements on the staff that
        affected by this clef being inserted.
        '''

        clef = MeiElement("clef")
        clef.addAttribute("shape", shape)
        clef.addAttribute("line", line)

        # perform clef insertion
        if before_id is None:
            # get last layer
            layers = self.mei.getElementsByName("layer")
            if len(layers):
                layers[-1].addChild(clef)
        else:
            before = self.mei.getElementById(str(before_id))
            parent = before.getParent()

            if parent and before:
                parent.addChildBefore(before, clef)

        self.update_or_add_zone(clef, ulx, uly, lrx, lry)
        if pitch_info:
            self.update_pitched_elements(pitch_info)

        result = {"id": clef.getId()}
        return result
示例#4
0
    def insert_custos(self, pname, oct, before_id, ulx, uly, lrx, lry):
        '''
        Insert a custos. Also add a bounding box
        for this element.
        '''

        # create custos
        custos = MeiElement("custos")
        if pname and oct:
            custos.addAttribute("pname", pname)
            custos.addAttribute("oct", oct)

        # insert the custos
        if before_id is None:
            # get last layer
            layers = self.mei.getElementsByName("layer")
            if len(layers):
                layers[-1].addChild(custos)
        else:
            before = self.mei.getElementById(str(before_id))
            parent = before.getParent()

            if parent and before:
                parent.addChildBefore(before, custos)

        # update the bounding box
        self.update_or_add_zone(custos, ulx, uly, lrx, lry)

        result = {"id": custos.getId()}
        return result
示例#5
0
文件: api.py 项目: sequoiar/Neon.js
    def insert_puncta(self, nid, bboxes):
        '''
        Insert a punctum for each note in the reference neume
        before the reference neume in the MEI document.
        '''
        ref_neume = self.mei.getElementById(nid)
        parent = ref_neume.getParent()

        # get underlying notes
        notes = ref_neume.getDescendantsByName("note")
        nids = []
        for n, bb in zip(notes, bboxes):
            punctum = MeiElement("neume")
            punctum.addAttribute("name", "punctum")
            nc = MeiElement("nc")
            nc.addChild(n)
            punctum.addChild(nc)

            # add generated punctum id to return to client
            nids.append(punctum.getId())

            # add facs data for the punctum
            zone = self.get_new_zone(bb["ulx"], bb["uly"], bb["lrx"], bb["lry"])
            self.add_zone(punctum, zone)

            # insert the punctum before the reference neume
            parent.addChildBefore(ref_neume, punctum)

        return nids
示例#6
0
    def insert_clef(self, line, shape, pitch_info, before_id, ulx, uly, lrx,
                    lry):
        '''
        Insert a doh or fah clef, with a given bounding box.
        Must also update pitched elements on the staff that
        affected by this clef being inserted.
        '''

        clef = MeiElement("clef")
        clef.addAttribute("shape", shape)
        clef.addAttribute("line", line)

        # perform clef insertion
        if before_id is None:
            # get last layer
            layers = self.mei.getElementsByName("layer")
            if len(layers):
                layers[-1].addChild(clef)
        else:
            before = self.mei.getElementById(str(before_id))
            parent = before.getParent()

            if parent and before:
                parent.addChildBefore(before, clef)

        self.update_or_add_zone(clef, ulx, uly, lrx, lry)
        if pitch_info:
            self.update_pitched_elements(pitch_info)

        result = {"id": clef.getId()}
        return result
示例#7
0
文件: api.py 项目: sequoiar/Neon.js
    def insert_puncta(self, nid, bboxes):
        '''
        Insert a punctum for each note in the reference neume
        before the reference neume in the MEI document.
        '''
        ref_neume = self.mei.getElementById(nid)
        parent = ref_neume.getParent()

        # get underlying notes
        notes = ref_neume.getDescendantsByName("note")
        nids = []
        for n, bb in zip(notes, bboxes):
            punctum = MeiElement("neume")
            punctum.addAttribute("name", "punctum")
            nc = MeiElement("nc")
            nc.addChild(n)
            punctum.addChild(nc)

            # add generated punctum id to return to client
            nids.append(punctum.getId())

            # add facs data for the punctum
            zone = self.get_new_zone(bb["ulx"], bb["uly"], bb["lrx"],
                                     bb["lry"])
            self.add_zone(punctum, zone)

            # insert the punctum before the reference neume
            parent.addChildBefore(ref_neume, punctum)

        return nids
示例#8
0
    def insert_custos(self, pname, oct, before_id, ulx, uly, lrx, lry):
        '''
        Insert a custos. Also add a bounding box
        for this element.
        '''

        # create custos
        custos = MeiElement("custos")
        custos.addAttribute("pname", pname)
        custos.addAttribute("oct", oct)

        # insert the custos
        before = self.mei.getElementById(before_id)

        # get layer element
        parent = before.getParent()

        if parent and before:
            parent.addChildBefore(before, custos)

        # update the bounding box
        self.update_or_add_zone(custos, ulx, uly, lrx, lry)

        result = {"id": custos.getId()}
        return result
示例#9
0
文件: api.py 项目: sequoiar/Neon.js
    def add_zone(self, custos, ulx, uly, lrx, lry):
        zone = MeiElement("zone")
        
        zone.addAttribute("ulx", ulx)
        zone.addAttribute("uly", uly)
        zone.addAttribute("lrx", lrx)
        zone.addAttribute("lry", lry)

        custos.addAttribute("facs", zone.getId())
        surfaces = self.mei.getElementsByName("surface")
        if len(surfaces):
            surfaces[0].addChild(zone)
示例#10
0
文件: api.py 项目: sequoiar/Neon.js
    def add_zone(self, custos, ulx, uly, lrx, lry):
        zone = MeiElement("zone")

        zone.addAttribute("ulx", ulx)
        zone.addAttribute("uly", uly)
        zone.addAttribute("lrx", lrx)
        zone.addAttribute("lry", lry)

        custos.addAttribute("facs", zone.getId())
        surfaces = self.mei.getElementsByName("surface")
        if len(surfaces):
            surfaces[0].addChild(zone)
示例#11
0
文件: api.py 项目: sequoiar/Neon.js
    def update_or_add_zone(self, clef, ulx, uly, lrx, lry):
        facsid = clef.getAttribute("facs").value
        if facsid:
            zone = self.mei.getElementById(facsid)
        else:
            zone = MeiElement("zone")
            clef.addAttribute("facs", zone.getId())
            surfaces = self.mei.getElementsByName("surface")
            if len(surfaces):
                surfaces[0].addChild(zone)

        zone.addAttribute("ulx", ulx)
        zone.addAttribute("uly", uly)
        zone.addAttribute("lrx", lrx)
        zone.addAttribute("lry", lry)
示例#12
0
文件: api.py 项目: sequoiar/Neon.js
    def update_zone(self, division, ulx, uly, lrx, lry):
        facs_id = division.getAttribute("facs").getValue()
        if facs_id:
            zone = self.mei.getElementById(facs_id)
        else:
            zone = MeiElement("zone")
            division.addAttribute("facs", zone.getId())
            surfaces = self.mei.getElementsByName("surface")
            if len(surfaces):
                surfaces[0].addChild(zone)

        zone.addAttribute("ulx", ulx)
        zone.addAttribute("uly", uly)
        zone.addAttribute("lrx", lrx)
        zone.addAttribute("lry", lry)
示例#13
0
文件: api.py 项目: sequoiar/Neon.js
    def update_or_add_zone(self, clef, ulx, uly, lrx, lry):
        facsid = clef.getAttribute("facs").value
        if facsid:
            zone = self.mei.getElementById(facsid)
        else:
            zone = MeiElement("zone")
            clef.addAttribute("facs", zone.getId())
            surfaces = self.mei.getElementsByName("surface")
            if len(surfaces):
                surfaces[0].addChild(zone)

        zone.addAttribute("ulx", ulx)
        zone.addAttribute("uly", uly)
        zone.addAttribute("lrx", lrx)
        zone.addAttribute("lry", lry)
示例#14
0
文件: api.py 项目: sequoiar/Neon.js
    def update_zone(self, division, ulx, uly, lrx, lry):
        facs_id = division.getAttribute("facs").getValue()
        if facs_id:
            zone = self.mei.getElementById(facs_id)
        else:
            zone = MeiElement("zone")
            division.addAttribute("facs", zone.getId())
            surfaces = self.mei.getElementsByName("surface")
            if len(surfaces):
                surfaces[0].addChild(zone)

        zone.addAttribute("ulx", ulx)
        zone.addAttribute("uly", uly)
        zone.addAttribute("lrx", lrx)
        zone.addAttribute("lry", lry)
示例#15
0
    def insert_punctum(self, before_id, pname, oct, dot_form, ulx, uly, lrx, lry):
        '''
        Insert a punctum before the given element. There is one case where
        there is no element to insert before, when there is no subsequent staff.
        In this case, the element is inserted at the end of the last system.
        Also sets the bounding box information of the new punctum.
        '''

        # create the punctum
        punctum = MeiElement("neume")
        punctum.addAttribute("name", "punctum")
        nc = MeiElement("nc")
        note = MeiElement("note")
        if pname and oct:
            note.addAttribute("pname", pname)
            note.addAttribute("oct", oct)

        # add ornamentation
        if dot_form is not None:
            dot = MeiElement("dot")
            dot.addAttribute("form", str(dot_form))
            note.addChild(dot)

        punctum.addChild(nc)
        nc.addChild(note)

        # create bounding box
        self.update_or_add_zone(punctum, ulx, uly, lrx, lry)

        # perform the insertion
        if before_id is None:
            # get last layer
            layers = self.mei.getElementsByName("layer")
            if len(layers):
                layers[-1].addChild(punctum)
        else:
            before = self.mei.getElementById(before_id)

            # get layer element
            parent = before.getParent()

            if parent and before:
                parent.addChildBefore(before, punctum)

        # get the generated ID for the client
        result = {"id": punctum.getId()}
        return result
示例#16
0
    def insert_punctum(self, before_id, pname, oct, dot_form, ulx, uly, lrx,
                       lry):
        '''
        Insert a punctum before the given element. There is one case where
        there is no element to insert before, when there is no subsequent staff.
        In this case, the element is inserted at the end of the last system.
        Also sets the bounding box information of the new punctum.
        '''

        # create the punctum
        punctum = MeiElement("neume")
        punctum.addAttribute("name", "punctum")
        nc = MeiElement("nc")
        note = MeiElement("note")
        note.addAttribute("pname", pname)
        note.addAttribute("oct", oct)

        # add ornamentation
        if dot_form is not None:
            dot = MeiElement("dot")
            dot.addAttribute("form", str(dot_form))
            note.addChild(dot)

        punctum.addChild(nc)
        nc.addChild(note)

        # create bounding box
        self.update_or_add_zone(punctum, ulx, uly, lrx, lry)

        # perform the insertion
        if before_id is None:
            # get last layer
            layers = self.mei.getElementsByName("layer")
            if len(layers):
                layers[-1].addChild(punctum)
        else:
            before = self.mei.getElementById(before_id)

            # get layer element
            parent = before.getParent()

            if parent and before:
                parent.addChildBefore(before, punctum)

        # get the generated ID for the client
        result = {"id": punctum.getId()}
        return result
示例#17
0
    def insert_system(self, page_id, ulx, uly, lrx, lry):
        '''
        Insert a system and its bounding box.
        '''

        # create system
        system = MeiElement("system")

        # add system to page
        page = self.mei.getElementById(page_id)
        page.addChild(system)

        # update system bounding box
        self.update_or_add_zone(system, ulx, uly, lrx, lry)

        result = {"id": system.getId()}
        return result
示例#18
0
    def insert_system(self, page_id, ulx, uly, lrx, lry):
        '''
        Insert a system and its bounding box.
        '''

        # create system
        system = MeiElement("system")

        # add system to page
        page = self.mei.getElementById(page_id)
        page.addChild(system)

        # update system bounding box
        self.update_or_add_zone(system, ulx, uly, lrx, lry)

        result = {"id": system.getId()}
        return result
示例#19
0
    def ungroup(self, ids, bboxes):
        '''
        Ungroup a neume with the provided ids into puncta.
        Create bounding box information for each punctum.
        '''

        newids = []
        for id, bbox in zip(ids, bboxes):
            ref_neume = self.mei.getElementById(id)
            parent = ref_neume.getParent()

            # get underlying notes
            notes = ref_neume.getDescendantsByName("note")
            nids = []
            for n, bb in zip(notes, bbox):
                punctum = MeiElement("neume")
                punctum.addAttribute("name", "punctum")
                nc = MeiElement("nc")
                nc.addChild(n)
                punctum.addChild(nc)

                # add generated punctum id to return to client
                nids.append(punctum.getId())

                # add facs data for the punctum
                self.update_or_add_zone(punctum, str(bb["ulx"]),
                                        str(bb["uly"]), str(bb["lrx"]),
                                        str(bb["lry"]))

                # insert the punctum before the reference neume
                parent.addChildBefore(ref_neume, punctum)

            newids.append(nids)

            # delete the old neume
            neume = self.mei.getElementById(id)
            if neume:
                # remove bounding box information
                self.remove_zone(neume)

                # now remove the neume
                neume.getParent().removeChild(neume)

        result = {"nids": newids}
        return result
示例#20
0
def generate_zone(surface, bb):
    '''
    Given a bounding box, generates a zone element, adds it to the given @surface,
    and returns its ID.
    '''
    el = MeiElement('zone')
    surface.addChild(el)

    # could be cleaner, but necessary so that we don't add extra attributes from @bb
    attribs = {
        'ulx': bb['ulx'],
        'uly': bb['uly'],
        'lrx': bb['lrx'],
        'lry': bb['lry'],
    }

    el = add_attributes_to_element(el, attribs)
    return el.getId()
示例#21
0
    def ungroup(self, ids, bboxes):
        '''
        Ungroup a neume with the provided ids into puncta.
        Create bounding box information for each punctum.
        '''

        newids = []
        for id, bbox in zip(ids, bboxes):
            ref_neume = self.mei.getElementById(id)
            parent = ref_neume.getParent()

            # get underlying notes
            notes = ref_neume.getDescendantsByName("note")
            nids = []
            for n, bb in zip(notes, bbox):
                punctum = MeiElement("neume")
                punctum.addAttribute("name", "punctum")
                nc = MeiElement("nc")
                nc.addChild(n)
                punctum.addChild(nc)

                # add generated punctum id to return to client
                nids.append(punctum.getId())

                # add facs data for the punctum
                self.update_or_add_zone(punctum, str(bb["ulx"]), str(bb["uly"]), str(bb["lrx"]), str(bb["lry"]))

                # insert the punctum before the reference neume
                parent.addChildBefore(ref_neume, punctum)

            newids.append(nids)

            # delete the old neume
            neume = self.mei.getElementById(id)
            if neume:
                # remove bounding box information
                self.remove_zone(neume)

                # now remove the neume
                neume.getParent().removeChild(neume)
        
        result = {"nids": newids}
        return result
示例#22
0
    def update_or_add_zone(self, element, ulx, uly, lrx, lry):
        '''
        Update the bounding box information attached to an element
        '''

        facsid = element.getAttribute("facs")
        if facsid:
            zone = self.mei.getElementById(facsid.getValue())
        else:
            zone = MeiElement("zone")
            element.addAttribute("facs", zone.getId())
            surfaces = self.mei.getElementsByName("surface")
            if len(surfaces):
                surfaces[0].addChild(zone)

        zone.addAttribute("ulx", ulx)
        zone.addAttribute("uly", uly)
        zone.addAttribute("lrx", lrx)
        zone.addAttribute("lry", lry)
示例#23
0
    def update_or_add_zone(self, element, ulx, uly, lrx, lry):
        '''
        Update the bounding box information attached to an element
        '''

        facsid = element.getAttribute("facs")
        if facsid:
            zone = self.mei.getElementById(facsid.getValue())
        else:
            zone = MeiElement("zone")
            element.addAttribute("facs", zone.getId())
            surfaces = self.mei.getElementsByName("surface")
            if len(surfaces):
                surfaces[0].addChild(zone)

        zone.addAttribute("ulx", ulx)
        zone.addAttribute("uly", uly)
        zone.addAttribute("lrx", lrx)
        zone.addAttribute("lry", lry)
示例#24
0
    def insert_system_break(self, system_id, order_number, next_sb_id):
        '''
        Insert a system break before the associated system break,
        associate it with a system ID, and give it an order number.
        '''

        # create system
        sb = MeiElement("sb")
        sb.addAttribute("n", str(order_number))
        sb.addAttribute("systemref", str(system_id))

        # Perform insertion.  If we have no next reference, just add to last layer.
        if next_sb_id is None:
            layers = self.mei.getElementsByName("layer")
            if len(layers):
                layers[-1].addChild(sb)
        else:
            next_sb = self.mei.getElementById(str(next_sb_id))
            parent = next_sb.getParent()
            if parent and next_sb:
                parent.addChildBefore(next_sb, sb)

        result = {"id": sb.getId()}
        return result
示例#25
0
    def insert_system_break(self, system_id, order_number, next_sb_id):
        '''
        Insert a system break before the associated system break,
        associate it with a system ID, and give it an order number.
        '''

        # create system
        sb = MeiElement("sb")
        sb.addAttribute("n", str(order_number))
        sb.addAttribute("systemref", str(system_id))

        # Perform insertion.  If we have no next reference, just add to last layer.
        if next_sb_id is None:
            layers = self.mei.getElementsByName("layer")
            if len(layers):
                layers[-1].addChild(sb)
        else:
            next_sb = self.mei.getElementById(str(next_sb_id))
            parent = next_sb.getParent()
            if parent and next_sb:
                parent.addChildBefore(next_sb, sb)

        result = {"id": sb.getId()}
        return result
示例#26
0
    def insert_division(self, before_id, type, ulx, uly, lrx, lry):
        '''
        Insert a division before the given element. There is one case
        where there is no element to insert before, when there is no
        subsequent staff. In this case, the element is inserted at the end
        of the last system. Also sets the bounding box information of the new
        division.
        '''

        division = MeiElement("division")
        division.addAttribute("form", type)
        self.update_or_add_zone(division, ulx, uly, lrx, lry)

        before = self.mei.getElementById(before_id)

        # get layer element
        layer = before.getParent()

        if layer and before:
            layer.addChildBefore(before, division)

            if type == "final":
                # if final division, close layer and staff
                staff = layer.getParent()
                section_parent = staff.getParent()

                # create new staff and layer
                new_staff = MeiElement("staff")
                new_layer = MeiElement("layer")
                new_layer.addAttribute("n", "1")

                # get elements after "before element" to move
                element_peers = before.getPeers()
                e_ind = list(element_peers).index(before)
                for e in element_peers[e_ind:]:
                    # add element to the new staff/layer
                    new_layer.addChild(e)
                    # remove element from the current staff/layer
                    layer.removeChild(e)

                new_staff.addChild(new_layer)

                # insert new staff into the document
                staves = section_parent.getChildrenByName("staff")
                s_ind = list(staves).index(staff)
                if s_ind + 1 < len(staves):
                    # there are staff elements after the new staff to insert
                    before_staff = staves[s_ind + 1]

                    # update staff numbers staves
                    for i, s in enumerate(staves[s_ind + 1:]):
                        s.addAttribute("n", str(s_ind + i + 3))

                    section_parent.addChildBefore(before_staff, new_staff)
                else:
                    section_parent.addChild(new_staff)

                new_staff.addAttribute("n", str(s_ind + 2))

                # insert and update staff definitions
                staff_group = self.mei.getElementsByName("staffGrp")
                if len(staff_group):
                    staff_defs = staff_group[0].getChildrenByName("staffDef")
                    if len(staff_defs) == len(staves):
                        staff_def = MeiElement("staffDef")
                        staff_def.addAttribute("n", str(s_ind + 2))
                        if s_ind + 1 < len(staff_defs):
                            before_staff_def = staff_defs[s_ind + 1]

                            # update staff number for all following staff defs
                            for i, sd in enumerate(staff_defs[s_ind + 1:]):
                                sd.addAttribute("n", str(s_ind + i + 3))

                            staff_group[0].addChildBefore(
                                before_staff_def, staff_def)
                        else:
                            staff_group[0].addChild(staff_def)

        result = {"id": division.getId()}
        return result
示例#27
0
    def _create_header(self, rodan_version='0.1'):
        '''
        Create a meiHead element
        '''

        mei_head = MeiElement('meiHead')
        today = datetime.date.today().isoformat()

        app_name = 'RODAN/barlineFinder'

        # file description
        file_desc = MeiElement('fileDesc')

        title_stmt = MeiElement('titleStmt')
        title = MeiElement('title')
        resp_stmt = MeiElement('respStmt')
        corp_name = MeiElement('corpName')
        corp_name.setValue('Distributed Digital Music Archives and Libraries Lab (DDMAL)')
        title_stmt.addChild(title)
        title_stmt.addChild(resp_stmt)
        resp_stmt.addChild(corp_name)
        
        pub_stmt = MeiElement('pubStmt')
        resp_stmt = MeiElement('respStmt')
        corp_name = MeiElement('corpName')
        corp_name.setValue('Distributed Digital Music Archives and Libraries Lab (DDMAL)')
        pub_stmt.addChild(resp_stmt)
        resp_stmt.addChild(corp_name)

        mei_head.addChild(file_desc)
        file_desc.addChild(title_stmt)
        file_desc.addChild(pub_stmt)

        # encoding description
        encoding_desc = MeiElement('encodingDesc')
        app_info = MeiElement('appInfo')
        application = MeiElement('application')
        application.addAttribute('version', rodan_version)
        name = MeiElement('name')
        name.setValue(app_name)
        ptr = MeiElement('ptr')
        ptr.addAttribute('target', 'https://github.com/DDMAL/barlineFinder')

        mei_head.addChild(encoding_desc)
        encoding_desc.addChild(app_info)
        app_info.addChild(application)
        application.addChild(name)
        application.addChild(ptr)

        # revision description
        revision_desc = MeiElement('revisionDesc')
        change = MeiElement('change')
        change.addAttribute('n', '1')
        resp_stmt = MeiElement('respStmt')
        corp_name = MeiElement('corpName')
        corp_name.setValue('Distributed Digital Music Archives and Libraries Lab (DDMAL)')
        change_desc = MeiElement('changeDesc')
        ref = MeiElement('ref')
        ref.addAttribute('target', '#'+application.getId())
        ref.setValue(app_name)
        ref.setTail('.')
        p = MeiElement('p')
        p.addChild(ref)
        p.setValue('Encoded using ')
        date = MeiElement('date')
        date.setValue(today)
        
        mei_head.addChild(revision_desc)
        revision_desc.addChild(change)
        change.addChild(resp_stmt)
        resp_stmt.addChild(corp_name)
        change.addChild(change_desc)
        change_desc.addChild(p)
        change.addChild(date)

        return mei_head
示例#28
0
    def neumify(self, ids, type_id, head_shapes, ulx, uly, lrx, lry):
        '''
        Neumify a group of neumes (with provided ids)
        and give it the given neume name. Also update
        bounding box information.
        '''
        # get neume name and variant from type id
        type_split = type_id.split(".")
        if type_split[-1].isdigit():
            type_split.pop()
        if len(type_split) == 1:
            attrs = [MeiAttribute("name", type_split[0])]
        else:
            variant = " ".join(type_split[1:])
            attrs = [
                MeiAttribute("name", type_split[0]),
                MeiAttribute("variant", variant)
            ]

        new_neume = MeiElement("neume")
        new_neume.setAttributes(attrs)
        ncs = []
        cur_nc = None

        iNote = 0
        for id in ids:
            ref_neume = self.mei.getElementById(str(id))
            if ref_neume:
                # get underlying notes
                notes = ref_neume.getDescendantsByName("note")
                for n in notes:
                    head = str(head_shapes[iNote])
                    # check if a new nc must be opened
                    if head == 'punctum' and cur_nc != 'punctum':
                        ncs.append(MeiElement("nc"))
                        cur_nc = head
                    elif head == 'punctum_inclinatum' and cur_nc != 'punctum_inclinatum':
                        new_nc = MeiElement("nc")
                        new_nc.addAttribute("inclinatum", "true")
                        ncs.append(new_nc)
                        cur_nc = head
                    elif head == 'punctum_inclinatum_parvum' and cur_nc != 'punctum_inclinatum_parvum':
                        new_nc = MeiElement("nc")
                        new_nc.addAttribute("inclinatum", "true")
                        new_nc.addAttribute("deminutus", "true")
                        ncs.append(new_nc)
                        cur_nc = head
                    elif head == 'quilisma' and cur_nc != 'quilisma':
                        new_nc = MeiElement("nc")
                        new_nc.addAttribute("quilisma", "true")
                        ncs.append(new_nc)
                        cur_nc = head
                    elif cur_nc is None:
                        ncs.append(MeiElement("nc"))
                        cur_nc = 'punctum'

                    ncs[-1].addChild(n)
                    iNote += 1

        new_neume.setChildren(ncs)

        # insert the new neume
        before = self.mei.getElementById(ids[0])
        parent = before.getParent()

        if before and parent:
            parent.addChildBefore(before, new_neume)

        # remove the old neumes from the mei document
        for id in ids:
            neume = self.mei.getElementById(str(id))
            if neume:
                # remove facs data
                facs = neume.getAttribute("facs")
                if facs:
                    facsid = facs.value
                    # Remove the zone if it exists
                    zone = self.mei.getElementById(str(facsid))
                    if zone and zone.name == "zone":
                        zone.parent.removeChild(zone)

                # now remove the neume
                neume.parent.removeChild(neume)

        # update bounding box data
        self.update_or_add_zone(new_neume, ulx, uly, lrx, lry)

        result = {"id": new_neume.getId()}
        return result
示例#29
0
    def write_mei(self, notes, audio_path, output_path=None):
        from pymei import MeiDocument, MeiElement, XmlExport
        
        # combine features with the same timestamps
        note_events = []
        for n in notes:
            ts = n.timestamp.toSeconds()
            note_num = int(n.values[0]) + 1          # it looks like everything is transposed a semitone down ... transposing up
            # if the last timestamp is equal to this timestamp, combine into a chord
            if len(note_events) > 0 and note_events[-1][0] == ts:
                note_events[-1][1].append(note_num)
            else:
                note_events.append([ts, [note_num]])

        # sort by timestamp in ascending order
        note_events = sorted(note_events, key=lambda n: n[0])

        # begin constructing mei document
        meidoc = MeiDocument()
        mei = MeiElement('mei')
        meidoc.setRootElement(mei)

        music = MeiElement('music')
        timeline = MeiElement('timeline')
        timeline.addAttribute('avref', str(audio_path))
        body = MeiElement('body')
        mdiv = MeiElement('mdiv')
        score = MeiElement('score')
        score_def = MeiElement('scoreDef')

        # assume 4/4 time signature
        meter_count = 4
        meter_unit = 4
        score_def.addAttribute('meter.count', str(meter_count))
        score_def.addAttribute('meter.unit', str(meter_unit))
        
        staff_def = MeiElement('staffDef')
        staff_def.addAttribute('n', '1')
        staff_def.addAttribute('label.full', 'Electric Guitar')
        staff_def.addAttribute('clef.shape', 'TAB')

        instr_def = MeiElement('instrDef')
        instr_def.addAttribute('n', 'Electric_Guitar')
        instr_def.addAttribute('midi.channel', '1')
        instr_def.addAttribute('midi.instrnum', '28')

        mei.addChild(music)
        music.addChild(timeline)
        music.addChild(body)
        body.addChild(mdiv)
        mdiv.addChild(score)
        score.addChild(score_def)
        score_def.addChild(staff_def)
        staff_def.addChild(instr_def)

        section = MeiElement('section')
        score.addChild(section)
        # another score def
        score_def = MeiElement('scoreDef')
        score_def.addAttribute('meter.count', str(meter_count))
        score_def.addAttribute('meter.unit', str(meter_unit))
        section.addChild(score_def)
        
        # start writing pitches to file
        note_container = None
        for i, note_event in enumerate(note_events):
            if i % meter_count == 0:
                measure = MeiElement('measure')
                measure.addAttribute('n', str(int(i/meter_count + 1)))
                staff = MeiElement('staff')
                staff.addAttribute('n', '1')
                layer = MeiElement('layer')
                layer.addAttribute('n', '1')
                section.addChild(measure)
                measure.addChild(staff)
                staff.addChild(layer)
                note_container = layer

            ts = note_event[0]
            when = MeiElement('when')
            if i == 0:
                timeline.addAttribute('origin', when.getId())
            when.addAttribute('absolute', str(ts))
            timeline.addChild(when)

            notes = note_event[1]
            if len(notes) > 1:
                chord = MeiElement('chord')
                chord.addAttribute('when', when.getId())
                for n in notes:
                    note = MeiElement('note')
                    note_info = PolyTrans.midi_map[n]
                    pname = note_info[0]
                    oct = note_info[1]
                    note.addAttribute('pname', pname[0])
                    note.addAttribute('oct', str(oct))
                    if len(pname) > 1 and pname[-1] == '#':
                        # there is an accidental
                        note.addAttribute('accid.ges', 's')
                    note.addAttribute('dur', str(meter_unit))
                    chord.addChild(note)
                note_container.addChild(chord)
            else:
                n = notes[0]
                note = MeiElement('note')
                note.addAttribute('when', when.getId())
                note_info = PolyTrans.midi_map[n]
                pname = note_info[0]
                oct = note_info[1]
                note.addAttribute('pname', pname[0])
                note.addAttribute('oct', str(oct))
                if len(pname) > 1 and pname[-1] == '#':
                    # there is an accidental
                    note.addAttribute('accid.ges', 's')
                note.addAttribute('dur', str(meter_unit))
                note_container.addChild(note)

        if output_path is not None:
            XmlExport.meiDocumentToFile(meidoc, output_path)
        else:
            return XmlExport.meiDocumentToText(meidoc)
示例#30
0
    def neumify(self, ids, type_id, liquescence, head_shapes, ulx, uly, lrx, lry):
        '''
        Neumify a group of neumes (with provided ids)
        and give it the given neume name. Also update
        bounding box information.
        '''
        
        # get neume name and variant from type id
        type_split = type_id.split(".")
        if type_split[-1].isdigit():
             type_split.pop()

        if len(type_split) == 1:
            attrs = [MeiAttribute("name", type_split[0])]
        else:
            variant = " ".join(type_split[1:])
            attrs = [MeiAttribute("name", type_split[0]), MeiAttribute("variant", variant)]

        '''
        # need to determine how to encode these different types of liquescence in the MEI document
        if liquescence:
            if liquescence == "alt":
                attrs.append(MeiAttribute("variant", "liquescence"))
            elif liquescence == "aug":
                attrs.append(MeiAttribute("variant", "liquescence_aug"))
            elif liquescence == "dim":
                attrs.append(MeiAttribute("variant", "liquescence_dim"))
        '''

        new_neume = MeiElement("neume")
        new_neume.setAttributes(attrs)
        ncs = []
        cur_nc = None

        iNote = 0
        for id in ids:
            ref_neume = self.mei.getElementById(str(id))
            if ref_neume:
                # get underlying notes
                notes = ref_neume.getDescendantsByName("note")
                for n in notes:
                    head = str(head_shapes[iNote])
                    # check if a new nc must be opened
                    if head == 'punctum' and cur_nc != 'punctum':
                        ncs.append(MeiElement("nc"))
                        cur_nc = head
                    elif head == 'punctum_inclinatum' and cur_nc != 'punctum_inclinatum':
                        new_nc = MeiElement("nc")
                        new_nc.addAttribute("inclinatum", "true")
                        ncs.append(new_nc)
                        cur_nc = head
                    elif head == 'punctum_inclinatum_parvum' and cur_nc != 'punctum_inclinatum_parvum':
                        new_nc = MeiElement("nc")
                        new_nc.addAttribute("inclinatum", "true")
                        new_nc.addAttribute("deminutus", "true")
                        ncs.append(new_nc)
                        cur_nc = head 
                    elif head == 'quilisma' and cur_nc != 'quilisma':
                        new_nc = MeiElement("nc")
                        new_nc.addAttribute("quilisma", "true")
                        ncs.append(new_nc)
                        cur_nc = head
                    elif cur_nc is None:
                        ncs.append(MeiElement("nc"))
                        cur_nc = 'punctum'

                    ncs[-1].addChild(n)
                    iNote += 1

        new_neume.setChildren(ncs)

        # insert the new neume
        before = self.mei.getElementById(ids[0])
        parent = before.getParent()

        if before and parent:
            parent.addChildBefore(before, new_neume)

        # remove the old neumes from the mei document
        for id in ids:
            neume = self.mei.getElementById(str(id))
            if neume:
                # remove facs data
                facs = neume.getAttribute("facs")
                if facs:
                    facsid = facs.value
                    # Remove the zone if it exists
                    zone = self.mei.getElementById(str(facsid))
                    if zone and zone.name == "zone":
                        zone.parent.removeChild(zone)

                # now remove the neume
                neume.parent.removeChild(neume)

        # update bounding box data
        self.update_or_add_zone(new_neume, ulx, uly, lrx, lry)

        result = {"id": new_neume.getId()}
        return result
示例#31
0
文件: meicreate.py 项目: agpar/Rodan
    def _create_header(self, rodan_version='0.1'):
        '''
        Create a meiHead element
        '''

        mei_head = MeiElement('meiHead')
        today = datetime.date.today().isoformat()

        app_name = 'RODAN/barlineFinder'

        # file description
        file_desc = MeiElement('fileDesc')

        title_stmt = MeiElement('titleStmt')
        title = MeiElement('title')
        resp_stmt = MeiElement('respStmt')
        corp_name = MeiElement('corpName')
        corp_name.setValue('Distributed Digital Music Archives and Libraries Lab (DDMAL)')
        title_stmt.addChild(title)
        title_stmt.addChild(resp_stmt)
        resp_stmt.addChild(corp_name)

        pub_stmt = MeiElement('pubStmt')
        resp_stmt = MeiElement('respStmt')
        corp_name = MeiElement('corpName')
        corp_name.setValue('Distributed Digital Music Archives and Libraries Lab (DDMAL)')
        pub_stmt.addChild(resp_stmt)
        resp_stmt.addChild(corp_name)

        mei_head.addChild(file_desc)
        file_desc.addChild(title_stmt)
        file_desc.addChild(pub_stmt)

        # encoding description
        encoding_desc = MeiElement('encodingDesc')
        app_info = MeiElement('appInfo')
        application = MeiElement('application')
        application.addAttribute('version', rodan_version)
        name = MeiElement('name')
        name.setValue(app_name)
        ptr = MeiElement('ptr')
        ptr.addAttribute('target', 'https://github.com/DDMAL/barlineFinder')

        mei_head.addChild(encoding_desc)
        encoding_desc.addChild(app_info)
        app_info.addChild(application)
        application.addChild(name)
        application.addChild(ptr)

        # revision description
        revision_desc = MeiElement('revisionDesc')
        change = MeiElement('change')
        change.addAttribute('n', '1')
        resp_stmt = MeiElement('respStmt')
        corp_name = MeiElement('corpName')
        corp_name.setValue('Distributed Digital Music Archives and Libraries Lab (DDMAL)')
        change_desc = MeiElement('changeDesc')
        ref = MeiElement('ref')
        ref.addAttribute('target', '#' + application.getId())
        ref.setValue(app_name)
        ref.setTail('.')
        p = MeiElement('p')
        p.addChild(ref)
        p.setValue('Encoded using ')
        date = MeiElement('date')
        date.setValue(today)

        mei_head.addChild(revision_desc)
        revision_desc.addChild(change)
        change.addChild(resp_stmt)
        resp_stmt.addChild(corp_name)
        change.addChild(change_desc)
        change_desc.addChild(p)
        change.addChild(date)

        return mei_head
示例#32
0
    def insert_division(self, before_id, type, ulx, uly, lrx, lry):
        '''
        Insert a division before the given element. There is one case
        where there is no element to insert before, when there is no
        subsequent staff. In this case, the element is inserted at the end
        of the last system. Also sets the bounding box information of the new
        division.
        '''

        division = MeiElement("division")
        division.addAttribute("form", type)
        self.update_or_add_zone(division, ulx, uly, lrx, lry)

        before = self.mei.getElementById(before_id)

        # get layer element
        layer = before.getParent()

        if layer and before:
            layer.addChildBefore(before, division)

            if type == "final":
                # if final division, close layer and staff
                staff = layer.getParent()
                section_parent = staff.getParent()

                # create new staff and layer
                new_staff = MeiElement("staff")
                new_layer = MeiElement("layer")
                new_layer.addAttribute("n", "1")
                
                # get elements after "before element" to move
                element_peers = before.getPeers()
                e_ind = list(element_peers).index(before)
                for e in element_peers[e_ind:]:
                    # add element to the new staff/layer
                    new_layer.addChild(e)
                    # remove element from the current staff/layer
                    layer.removeChild(e)

                new_staff.addChild(new_layer)

                # insert new staff into the document
                staves = section_parent.getChildrenByName("staff")
                s_ind = list(staves).index(staff)
                if s_ind+1 < len(staves):
                    # there are staff elements after the new staff to insert
                    before_staff = staves[s_ind+1]

                    # update staff numbers staves
                    for i, s in enumerate(staves[s_ind+1:]):
                        s.addAttribute("n", str(s_ind+i+3))

                    section_parent.addChildBefore(before_staff, new_staff)
                else:
                    section_parent.addChild(new_staff)

                new_staff.addAttribute("n", str(s_ind+2))
                
                # insert and update staff definitions
                staff_group = self.mei.getElementsByName("staffGrp")
                if len(staff_group):
                    staff_defs = staff_group[0].getChildrenByName("staffDef")
                    if len(staff_defs) == len(staves):
                        staff_def = MeiElement("staffDef")
                        staff_def.addAttribute("n", str(s_ind+2))
                        if s_ind+1 < len(staff_defs):
                            before_staff_def = staff_defs[s_ind+1]

                            # update staff number for all following staff defs
                            for i, sd in enumerate(staff_defs[s_ind+1:]):
                                sd.addAttribute("n", str(s_ind+i+3))

                            staff_group[0].addChildBefore(before_staff_def, staff_def)
                        else:
                            staff_group[0].addChild(staff_def)

        result = {"id": division.getId()}
        return result