【python】【转调】用python程序实现简谱转调

一、任务

用python实现将指定旋律从某调转到某调的功能。

二、原理

将X调转到Y调,即将X升(X-Y)个半音
注:这里X-Y代表半音关系,对应下面的trans_map字典;
注:传入的音阶应可以表示大于一个八度的音域。这里采用的策略是,若音符前面有.(点)则表示第一个八度,若在音符后面有.则表示高一个八度。

三、代码

#trans_map:定义音名间的半音关系,每个半音之间的差为1
trans_map = {'C':0,'bD':1,'D':2,'bE':3,'E':4,'F':5,'bG':6,'G':7,'bA':8,'A':9,'bB':10,'B':11}
#C_scale:C大调半音阶
C_scale = ['1','#1','2','#2','3','4','#4','5','#5','6','#6','7']

#函数说明:需传入旋律,原调性,目标调性
def trans_tonality(Tune,Tune_Tonality,Aim_Tonality):
    tune = []                                                   #转调后的旋律
    minus = trans_map[Tune_Tonality]-trans_map[Aim_Tonality]        #半音关系
    at = C_scale[minus:]+C_scale[:minus]      #利用半音关系推出转调后的参考音阶
    for t in list(Tune.split(',')):                         #按照逗号分割音符
        position = [i.start() for i in re.finditer('\.', t)] #找到所有.的位置

        if position == []:                #如果音符旁没有.
            low_num = 0
            high_num = 0
        elif position[0]==0:              #如果音符前有.
            low_num = len(position)
            high_num = 0
        else:                             #如果音符后有.
            high_num = len(position)
            low_num = 0
        if minus>0:
            high_num += 1
            low_num -= 1
        t = t.translate(str.maketrans('','','.')) #.的信息已经统计好了,把它们删掉

        if len(t)==1:                     #没有升降号
            ori = int(t)
            if int(t)<4:                  #do re mi
                new_tune = at[int(t)*2-2]
            elif int(t)<8:                #fa sol la ti
                new_tune = at[int(t)*2-3]
            else:
                new_tune = 'Error'
        elif len(t)==2:                   #有升降号
            ori = int(t[1])               #记录原音名
            if 'b' in t:                  #如果是降号b,变成升号#,之后再统一处理;如b6变成#5
                t = '#'+str(int(t[1])-1)
            if int(t[1])<3:               # #do #re
                print(t[1])
                new_tune = str(at[int(t[1])*2-1])
            elif int(t[1])<7:             # #fa #sol #la
                new_tune = str(at[int(t[1])*2-2])
            else:
                new_tune = 'Error'
        else:
            new_tune = 'Error'

        try:                              #根据原来记录的.的信息恢复音高信息,即加上.
            if int(new_tune[-1]) > ori:
                if high_num > 0:
                    high_num -= 1
                else:
                    low_num += 1
            for i in range(low_num):
                new_tune = '.' + new_tune
            for i in range(high_num):
                new_tune = new_tune + '.'
            tune.append(new_tune)
        except:
            tune.append('Error')

    print(tune)

#函数说明:trans_tonality(Tune,Tune_Tonality,Aim_Tonality)旋律,原调性,目标调性
trans_tonality('1,1,5,5,6,6,5,4,4,3,3,2,2,1','C','D')
trans_tonality('1,1,5,5,6,6,5,4,4,3,3,2,2,1','D','C')
#返回值:
#['.#6', '.#6', '4', '4', '5', '5', '4', '#2', '#2', '2', '2', '1', '1', '.#6']
#['2', '2', '6', '6', '7', '7', '6', '5', '5', '#4', '#4', '3', '3', '2']

你可能感兴趣的:(Task)