Source code for music21.converter.qmConverter
# ------------------------------------------------------------------------------
# Name: converter/qmConverter.py
# Purpose: Example of subclassing SubConverter to parse a new format
#
# Authors: Michael Scott Asato Cuthbert
#
# Copyright: Copyright © 2015 Michael Scott Asato Cuthbert
# License: BSD, see license.txt
# ------------------------------------------------------------------------------
'''
This is an example of how converter.subConverters.SubConverter
can be subclassed in order to parse and write an unsupported format
in this case, the format, .qm, consists of a line of letters separated
by spaces:
C E G D F
and turns each of them into a quarter note in octave 4 in 4/4.
Consult the code to see how it works. To use, call
`converter.registerSubConverter(converter.qmConverter.QMConverter)`
then `myStream = converter.parse('quarterMusic: C E G D F')`
'''
from __future__ import annotations
from music21 import converter
from music21 import environment
from music21 import meter
from music21 import note
from music21 import stream
environLocal = environment.Environment('converter.qmConverter')
[docs]
class QMConverter(converter.subConverters.SubConverter):
registerFormats = ('qm', 'quarterMusic')
registerInputExtensions = ('qm',)
registerOutputExtensions = ('qm',)
[docs]
def parseData(self, strData, number=None):
'''
Parse the data. The number attribute is not used.
>>> from music21.converter.qmConverter import QMConverter
>>> qmc = QMConverter()
>>> qmc.parseData('C D E G C')
>>> q_stream = qmc.stream
>>> q_stream.show('text')
{0.0} <music21.stream.Measure 1 offset=0.0>
{0.0} <music21.clef.TrebleClef>
{0.0} <music21.meter.TimeSignature 4/4>
{0.0} <music21.note.Note C>
{1.0} <music21.note.Note D>
{2.0} <music21.note.Note E>
{3.0} <music21.note.Note G>
{4.0} <music21.stream.Measure 2 offset=4.0>
{0.0} <music21.note.Note C>
{1.0} <music21.bar.Barline type=final>
'''
strDataList = strData.split()
s = stream.Part()
m = meter.TimeSignature('4/4')
s.insert(0, m)
for beat in strDataList:
nObj = note.Note(beat)
nObj.duration.quarterLength = 1
s.append(nObj)
self.stream = s.makeMeasures()
[docs]
def parseFile(self, filePath, number=None, **keywords):
'''
parse a file from disk. If QMConverter is registered, then any
file ending in .qm will automatically be parsed.
>>> import os
>>> parserPath = common.getSourceFilePath() / 'converter'
>>> testPath = parserPath / 'quarterMusicTestIn.qm'
>>> from music21.converter.qmConverter import QMConverter
>>> qmc = QMConverter()
>>> qmc.parseFile(testPath)
>>> s = qmc.stream
>>> s.show('text')
{0.0} <music21.stream.Measure 1 offset=0.0>
{0.0} <music21.clef.TrebleClef>
{0.0} <music21.meter.TimeSignature 4/4>
{0.0} <music21.note.Note C>
{1.0} <music21.note.Note E>
{2.0} <music21.note.Note G>
{3.0} <music21.note.Note F>
{4.0} <music21.stream.Measure 2 offset=4.0>
{0.0} <music21.note.Note E>
{1.0} <music21.note.Note D>
{2.0} <music21.note.Note C>
{3.0} <music21.bar.Barline type=final>
'''
with open(filePath, 'r', encoding='utf-8') as f:
self.parseData(f.read())
[docs]
def write(self, obj, fmt, fp=None, subformats=(), **keywords): # pragma: no cover
music = ''
if fp is None:
fp = environLocal.getTempFile('.qm')
for n in obj.flatten().notes:
music = music + n.name + ' '
music += '\n'
with open(fp, 'w', encoding='utf-8') as f:
f.write(music)
return fp
if __name__ == '__main__':
import music21
music21.mainTest()
# from music21 import common
#
# converter.registerSubConverter(QMConverter)
#
# print('\nFILE')
# print('+++++++++++++++++++++++++')
#
# parserPath = common.getSourceFilePath() / 'converter'
# testPath = parserPath / 'quarterMusicTestIn.qm'
#
# a = converter.parse(testPath)
#
# a.show('text')
#
#
# print('\nIn-Line')
# print('+++++++++++++++++++++++++')
#
# b = converter.parse('quarterMusic: G C G')
# b.show('text')
# print( b.write('qm') )