Music21 - How to keep the time signature when transposing?

74 Views Asked by At

I am trying to transpose to a common key (C major/A minor) like this:

def main():
    print("cwd=", os.getcwd())
    path="midi/bachjs"
    with os.scandir(path) as it:
        for entry in it:
            if entry.name.startswith("Minuet") and entry.name.endswith(".mid") and entry.is_file():
                filename=Path(entry.path)
                print(filename)
                piece=converter.parse(filename)
                key=piece.analyze('key')
                target=pitch.Pitch('C')
                if key.type == 'minor':
                    target=pitch.Pitch('A')
                if target.name != key.tonic.name:
                    move = interval.Interval(key.tonic, target)
                    newpiece=piece.transpose(move)
                    newkey=newpiece.analyze('key')
                    fp = newpiece.write('midi', fp=filename.with_suffix('').with_suffix('.in'+target.name+'.mid'))

if __name__ == "__main__":
    main()

Transposing BWV 114:

enter image description here

indeed shifts the initial D down to G etc., but the result is horrible:

enter image description here

How could I fix this? Thanks!

1

There are 1 best solutions below

0
Mike Slinn On

This is my first time using music21. Hopefully, this answer is helpful.

I noticed some problems with your code:

  • No imports were shown. Imports are significant.
  • Some variable names were the same as music21 module names. Try using more descriptive names.
  • You did not provide the MIDI file that your program worked with.

Below is a similar program. Instead of working from a local MIDI file, it obtained the MusicXML file (bach/bwv114.7.mxl) from the online corpus of MusicXML files provided by music21 at MIT. I am unsure if this is actually the same piece that you worked with - the notes do not correspond at all to the image of the score you show.

# See https://stackoverflow.com/q/75063300/553865

from music21 import *
import os
from pathlib import Path

def new_filename(corpus_name, pitch_name, major_minor, filetype):
    name = Path(corpus_name).stem
    if major_minor == 'minor':
      m = 'm'
    else:
      m = ''
    return f'{name}.in_{pitch_name}{m}.{filetype}'


paths = corpus.getComposer('bach')
score = corpus.parse('bach/bwv114.7.mxl')
key_guessed = score.analyze('key') # <music21.key.Key of g minor>

if key_guessed.type == 'minor':
    target_pitch = pitch.Pitch('A') # <music21.pitch.Pitch A>
else:
    target_pitch = pitch.Pitch('C') # <music21.pitch.Pitch C>
if target_pitch.name != key_guessed.tonic.name: # 'A' != 'G'
    interval_desired = interval.Interval(key_guessed.tonic, target_pitch)
    transposed_score = score.transpose(interval_desired)
    new_key = transposed_score.analyze('key')

    filename = new_filename(score.corpusFilepath, target_pitch.name, key_guessed.type, 'mid')
    transposed_score.write('midi', filename)

I used Guitar Pro to convert the MIDI file to PDF:

bwv114.7.in_Am