Python根据乐谱生成音乐

--*--

(!)有更新版本:Python音乐制作-紧急修复版v1.2_Unconquerable&Llxy的博客-CSDN博客

--*--

外来库:Pysynth

PySynth — A Music Synthesizer for Pythonhttps://mdoege.github.io/PySynth/#d

文件资源:

Python第三方库:Pysynth-Python文档类资源-CSDN下载学习资源,解压后使用。更多下载资源、学习资料请访问CSDN下载频道.https://download.csdn.net/download/html_finder/86441665

音色有多种,取决于不同模块。这里不过多赘述。

上 代 码 

文件(1)melody.py

# coding:utf-8

"""

----------------------------------
*    author: Unconquerable       *
----------------------------------

a great tool to convert melody text to music.

"""

class sound(object):
    high=4

    def __init__(self,high=4):
        self.high=high
    def __del__(self):
        del self.high
    def __str__(self):
        return ""

    def upLoud(self,up=1):
        self.high+=up
    def downLoud(self,down=1):
        self.high-=down
    def absoluteLoud(self,abv=0):
        self.high+=abv
    absLoud=absoluteLoud
    def resetLoud(self,value=4):
        self.high=value
    init=resetLoud

    @property
    def toString(self):
        return self.__str__()
    real=toString

    def plus(self):
        ...

    def plus_(self,num):
        ...

    def nplus(self):
        ...


class C(sound):
    high = 4
    def __init__(self,high=4):
        super().__init__(high=high)
    def __str__(self):
        return "c"+str(self.high)

    def plus(self):
        return AddC(self.high)

    def plus_(self, num):
        if num == 0: return self
        if num < 0:
            return self.nplus().plus_(num + 1)
        if num > 0:
            return self.plus().plus_(num - 1)

    def nplus(self):
        return B(self.high-1)



class AddC(sound):
    high = 4
    def __init__(self,high):
        super().__init__(high)
    def __str__(self):
        return "c#"+str(self.high)
    def plus(self):
        return D(self.high)

    def plus_(self, num):
        if num == 0: return self
        if num < 0:
            return self.nplus().plus_(num + 1)
        if num > 0:
            return self.plus().plus_(num - 1)

    def nplus(self):
        return C(self.high)

class D(sound):
    high = 4
    def __init__(self,high=4):
        super().__init__(high=high)
    def __str__(self):
        return "d"+str(self.high)
    def plus(self):
        return AddD(self.high)

    def plus_(self, num):
        if num == 0: return self
        if num < 0:
            return self.nplus().plus_(num + 1)
        if num > 0:
            return self.plus().plus_(num - 1)

    def nplus(self):
        return AddC(self.high)

class AddD(sound):
    high = 4
    def __init__(self,high=4):
        super().__init__(high=high)
    def __str__(self):
        return "d#"+str(self.high)
    def plus(self):
        return E(self.high)

    def plus_(self, num):
        if num == 0: return self
        if num < 0:
            return self.nplus().plus_(num + 1)
        if num > 0:
            return self.plus().plus_(num - 1)

    def nplus(self):
        return D(self.high)

class E(sound):
    high = 4
    def __init__(self,high=4):
        super().__init__(high=high)
    def __str__(self):
        return "e"+str(self.high)
    def plus(self):
        return F(self.high)

    def plus_(self, num):
        if num == 0: return self
        if num < 0:
            return self.nplus().plus_(num + 1)
        if num > 0:
            return self.plus().plus_(num - 1)

    def nplus(self):
        return AddD(self.high)

class F(sound):
    high = 4
    def __init__(self,high=4):
        super().__init__(high=high)
    def __str__(self):
        return "f"+str(self.high)
    def plus(self):
        return AddF(self.high)

    def plus_(self, num):
        if num == 0: return self
        if num < 0:
            return self.nplus().plus_(num + 1)
        if num > 0:
            return self.plus().plus_(num - 1)

    def nplus(self):
        return E(self.high)

class AddF(sound):
    high = 4
    def __init__(self,high=4):
        super().__init__(high=high)
    def __str__(self):
        return "f#"+str(self.high)
    def plus(self):
        return G(self.high)

    def plus_(self, num):
        if num == 0: return self
        if num < 0:
            return self.nplus().plus_(num + 1)
        if num > 0:
            return self.plus().plus_(num - 1)

    def nplus(self):
        return F(self.high)

class G(sound):
    high = 4
    def __init__(self,high=4):
        super().__init__(high=high)
    def __str__(self):
        return "g"+str(self.high)
    def plus(self):
        return AddG(self.high)

    def plus_(self, num):
        if num == 0: return self
        if num < 0:
            return self.nplus().plus_(num + 1)
        if num > 0:
            return self.plus().plus_(num - 1)

    def nplus(self):
        return AddF(self.high)

class AddG(sound):
    high = 4
    def __init__(self,high=4):
        super().__init__(high=high)
    def __str__(self):
        return "g#"+str(self.high)
    def plus(self):
        return A(self.high)

    def plus_(self, num):
        if num == 0: return self
        if num < 0:
            return self.nplus().plus_(num + 1)
        if num > 0:
            return self.plus().plus_(num - 1)

    def nplus(self):
        return G(self.high)

class A(sound):
    high = 4
    def __init__(self,high=4):
        super().__init__(high=high)
    def __str__(self):
        return "a"+str(self.high)
    def plus(self):
        return AddA(self.high)

    def plus_(self, num):
        if num == 0: return self
        if num < 0:
            return self.nplus().plus_(num + 1)
        if num > 0:
            return self.plus().plus_(num - 1)

    def nplus(self):
        return AddG(self.high)

class AddA(sound):
    high = 4
    def __init__(self,high=4):
        super().__init__(high=high)
    def __str__(self):
        return "a#"+str(self.high)
    def plus(self):
        return B(self.high)

    def plus_(self, num):
        if num == 0: return self
        if num < 0:
            return self.nplus().plus_(num + 1)
        if num > 0:
            return self.plus().plus_(num - 1)

    def nplus(self):
        return A(self.high)

class B(sound):
    high = 4
    def __init__(self,high=4):
        super().__init__(high=high)
    def __str__(self):
        return "b"+str(self.high)
    def plus(self):
        return C(self.high+1)

    def plus_(self, num):
        if num == 0: return self
        if num < 0:
            return self.nplus().plus_(num + 1)
        if num > 0:
            return self.plus().plus_(num - 1)

    def nplus(self):
        return AddA(self.high)

class NULL(sound):
    def __str__(self):
        return "r"
class time(object):
    real = 0
    def __init__(self,time=4):
        self.real= 4/time

class note(object):
    sound_ = sound()
    time_ = time()

    def __init__(self,sd,t):
        self.soundSet(sd)
        self.timeSet(t)

    def soundSet(self,sd):
        if isinstance(sd,str):
            nd=sd[:-1].upper()
            dct={"C":C,"C#":AddC,"D":D,"D#":AddD,"E":E,"F":F,
                 "F#":AddF,"G":G,"G#":AddG,"A":A,"A#":AddA,"B":B,"R":NULL}
            self.sound_=dct[nd](int(sd[-1]))
        if isinstance(sd,sound):
            self.sound_=sd
        if isinstance(sd,tuple):
            nd = sd[:-1].upper()
            dct = {"C": C, "C#": AddC, "D": D, "D#": AddD, "E": E, "F": F,
                   "F#": AddF, "G": G, "G#": AddG, "A": A, "A#": AddA, "B": B, "R": NULL}
            self.sound_ = dct[nd](int(sd[-1]))

    def timeSet(self,t):
        if isinstance(t,(int,float)):
            self.time_=time(t)
        if isinstance(t,time):
            self.time_=t

    @property
    def out(self):
        return self.sound_.toString,self.time_.real
class wav:
    melody=C(4)
    sound=[]
    staticTime=1
    def __init__(self,text=None,split=' '):
        if text:
            self.load(text=text,split=split)
    def __del__(self):
        pass

    @property
    def getMelody(self):
        return self.melody

    @property
    def getSound(self):
        return self.sound

    @property
    def getTime(self):
        return self.staticTime

    def setTime(self,time):
        self.staticTime=time

    def setMelody(self,melody):
        self.melody=melody
    def loadOneNote(self,n):
        if isinstance(n,note):
            self.sound.append(n.out)
        if isinstance(n,str):
            n=n.strip()
            if n[0]=="0":
                t=self.staticTime
                for i in n[1:]:
                    if i == "-":  # 延音符号
                        t += self.staticTime
                    if i == "_":  # 半音符号
                        t /= 2
                    # (!)不要让延音符号和半音符号同时出现
                    if i == ".":  # 附点音符
                        t += t / 2

                self.sound.append(("r",4/t))
                return
            #简谱
            t=self.staticTime
            dct={
                1:0,
                2:2,
                3:4,
                4:5,
                5:7,
                6:9,
                7:11
            }
            l=self.melody.plus_(dct[int(n[0])])
            for i in n[1:]:
                if i=="#":#升音符号
                    l.plus()
                if i=="&":#降音符号
                    l.nplus()
                if i=="-":#延音符号
                    t+=self.staticTime
                if i=="_":#半音符号
                    t/=2
                # (!)不要让延音符号和半音符号同时出现
                if i==".":#附点音符
                    t+=t/2
                if i=="+":#升音
                    l.upLoud(1)
                if i=="!":#降音
                    l.downLoud(1)

            mixed=note(l,t).out
            self.sound.append(mixed)
    def load(self,text,split=''):
        if split!='':
            for i in text.split(split):
                self.loadOneNote(i)
        else:
            tp=""
            for i in text:
                if i.isnumeric():
                    if tp.strip() != "":
                        self.loadOneNote(tp.strip())
                    tp=""
                tp+=i

    def make_wav(self,module="pysynth",bpm=120,transpose=0,pause=.05,boost=1.1,
                 repeat=0,fn="out.wav", silent=False):
        __import__(module.lower()).make_wav(song=self.sound,bpm=bpm,transpose=transpose,
                                    pause=pause,boost=boost,repeat=repeat,
                                    fn=fn, silent=silent)


文件:2(可有可无,可以规定调用的规范)melody.pyi

# coding:utf-8

"""

----------------------------------
*    author: Unconquerable       *
----------------------------------

a great tool to convert melody text to music.

"""


from typing import Union

class sound(object):
    high:int

    def __init__(self,high:int=4): ...
    def __del__(self): ...
    def __str__(self) -> str: ...

    def upLoud(self,up:int) -> None: ...
    def downLoud(self,down:int) -> None: ...
    def absoluteLoud(self,abv:int) -> None: ...
    absLoud=absoluteLoud
    def resetLoud(self,value:int) -> None: ...
    init=resetLoud
    @property
    def toString(self) -> str : ...
    real=toString

    def plus(self) -> sound : ...
    def plus_(self,num:int) -> sound : ...
    def nplus(self) -> sound: ...

class C(sound):
    high:int

    def __init__(self,high:int=4):
        super(C,self).__init__(high=high)
        ...
    def __str__(self) -> str: ...

    def plus(self) -> sound : ...
    def plus_(self,num:int) -> sound : ...
    def nplus(self) -> sound: ...

class AddC(sound):
    high:int

    def __init__(self,high:int=4):
        super(AddC,self).__init__(high=high)
        ...
    def __str__(self) -> str: ...

    def plus(self) -> sound : ...
    def plus_(self,num:int) -> sound : ...
    def nplus(self) -> sound: ...

class D(sound):
    high:int

    def __init__(self,high:int=4):
        super(D,self).__init__(high=high)
        ...
    def __str__(self) -> str: ...

    def plus(self) -> sound : ...
    def plus_(self,num:int) -> sound : ...
    def nplus(self) -> sound: ...

class AddD(sound):
    high:int

    def __init__(self,high:int=4):
        super(AddD,self).__init__(high=high)
        ...
    def __str__(self) -> str: ...

    def plus(self) -> sound : ...
    def plus_(self,num:int) -> sound : ...
    def nplus(self) -> sound: ...

class E(sound):
    high:int

    def __init__(self,high:int=4):
        super(E,self).__init__(high=high)
        ...
    def __str__(self) -> str: ...

    def plus(self) -> sound : ...
    def plus_(self,num:int) -> sound : ...
    def nplus(self) -> sound: ...

class F(sound):
    high:int

    def __init__(self,high:int=4):
        super(F,self).__init__(high=high)
        ...
    def __str__(self) -> str: ...

    def plus(self) -> sound : ...
    def plus_(self,num:int) -> sound : ...
    def nplus(self) -> sound: ...

class AddF(sound):
    high:int

    def __init__(self,high:int=4):
        super(AddF,self).__init__(high=high)
        ...
    def __str__(self) -> str: ...

    def plus(self) -> sound : ...
    def plus_(self,num:int) -> sound : ...
    def nplus(self) -> sound: ...

class G(sound):
    high:int

    def __init__(self,high:int=4):
        super(G,self).__init__(high=high)
        ...
    def __str__(self) -> str: ...

    def plus(self) -> sound : ...
    def plus_(self,num:int) -> sound : ...
    def nplus(self) -> sound: ...

class AddG(sound):
    high:int

    def __init__(self,high:int=4):
        super(AddG,self).__init__(high=high)
        ...
    def __str__(self) -> str: ...

    def plus(self) -> sound : ...
    def plus_(self,num:int) -> sound : ...
    def nplus(self) -> sound: ...

class A(sound):
    high:int

    def __init__(self,high:int=4):
        super(A,self).__init__(high=high)
        ...
    def __str__(self) -> str: ...

    def plus(self) -> sound : ...
    def plus_(self,num:int) -> sound : ...
    def nplus(self) -> sound: ...

class AddA(sound):
    high:int

    def __init__(self,high:int=4):
        super(AddA,self).__init__(high=high)
        ...
    def __str__(self) -> str: ...

    def plus(self) -> sound : ...
    def plus_(self,num:int) -> sound : ...
    def nplus(self) -> sound: ...

class B(sound):
    high:int

    def __init__(self,high:int=4):
        super(B,self).__init__(high=high)
        ...
    def __str__(self) -> str: ...

    def plus(self) -> sound : ...
    def plus_(self,num:int) -> sound : ...
    def nplus(self) -> sound: ...

class NULL(sound):
    def __str__(self) -> str: ...

class time(object):
    real : int
    def __init__(self,time:int=4): ...

class note(object):
    sound_ : sound
    time_ : time

    def __init__(self,sd:Union[sound,str,tuple],t:Union[time,int,float]): ...

    def soundSet(self,sd:Union[sound,str,tuple]) -> None: ...

    def timeSet(self,t:Union[time,int,float]) -> None: ...

    @property
    def out(self) -> tuple[str,int]: ...

class wav:
    melody:sound
    sound:list
    staticTime:Union[int,float]

    def __init__(self,text:Union[str,None]=None,split:str=' ') : ...
    def __del__(self) :  ...

    @property
    def getMelody(self) -> str: ...

    @property
    def getSound(self) -> list: ...

    @property
    def getTime(self) -> Union[int,float]:...

    def setTime(self,time:Union[int,float]) -> None: ...
    def setMelody(self,melody:sound) -> None: ...
    def loadOneNote(self,n:str) -> None: ...
    def load(self,text:str,split:str=' ') -> None: ...

    def make_wav(self,module:str="pysynth",bpm:Union[int,float]=120,transpose:int=0,pause:float=.05,
                 boost:float=1.1,repeat:int=0,fn:str="out.wav", silent:bool=False) -> None: ...

调用(1.py,同目录,父目录名称为MELODY。):

第三行import语句根据情况自行更改。

open里面的文件名自定。

# coding=utf-8

from MELODY.melody import *


a=wav()

text=open(r".\1.txt").read()
text=text.split("-*-")

a.setMelody(note(text[1].strip(),1).sound_)
a.setTime(int(text[2].strip()))

a.load(
    str(text[3]).strip()
)
res=text[0].strip().split("|")

a.make_wav(module=res[0],bpm=eval(res[1]),repeat=eval(res[2]),fn=res[3])

1.txt:

格式为:

字符串,引用模块名|整数|整数|存储文件名
-*-
调式,例如:1=C则填写c,1=降B则填写a#(即升a)
-*-
节拍。例如,默认为每个音四分音符,即1 。
-*-
(乐谱部分)

注意:上面的部分基本不用更改。接下来是我写的一个模板。

pysynth|120|0|file.wav
-*-
c
-*-
1
-*-

接下来要进行介绍。

第一行,以"|"分割。

"pysynth"表示使用默认音色。音色列表见下:

PySynth_A

这种加法单声道合成器非常简单,听起来有点像长笛或风琴,结合了钢琴般的音符音量衰减。PySynth A 只需要 Python 本身。它应该在所有 Python 支持的平台上运行,例如 Windows、Unix 和 Mac。

PySynth_B

一个加法合成器模块,它试图用更多的谐波创建更像钢琴的声音。这个版本是复调的,因为它不会在下一个音符响起时切断前一个音符。

PySynth_C

PySynth C 是一种基于减法合成的简单弓弦音色。它使用锯齿波振荡器和低通滤波器,类似于 1970 年代的模拟合成器(或amsynth中的弦乐声音,或来自MOS Technology SID的声音)。与 PySynth A 一样,它只需要 Python 本身即可运行。

PySynth_D

PySynth D 使用与 PySynth C 类似的减法合成,但它基于方波。这种合成器主音类型的声音让人联想到木管乐器。方波也用于 1970 年代/1980 年代的计算机声音芯片,例如General Instrument AY-3-8910Atari POKEY。只需要 Python 本身。

PySynth_E

该模块基于 PySynth B,基于相位调制创建简单的电子钢琴声音,这是进行 FM 合成的常用方法,例如在 1980 年代 Yamaha 合成器上。这种声音当然是受到Yamaha DX7上的 Rhodes 钢琴的启发。

PySynth_P

PySynth P 使用与 PySynth C 和 D 类似的减法合成,但基于具有指数体积包络的白噪声。它会产生未经调音的打击乐声音。这种类型的声音在 1980 年代通常用于打击乐和游戏音效。只需要 Python 本身。

PySynth_S

该模块使用Karplus-Strong 算法(想想吉他或大键琴)模拟单个弹拨。由于这种合成的性质,特别是较高频率的音符可能会与 PySynth S 稍微不协调,这与谐波精确的其他变体相反。这可以通过更高的采样率来解决,但这也会使其对 Python 来说有点慢。

PySynth_beeper

这个贡献的合成器属于nokiacomposer2wav.py并且应该重新创建老式诺基亚功能手机的铃声。

PySynth_samp

此合成器使用 48 kHz、24 位Salamander 钢琴样本。请在第 50 行设置 Salamander WAV 的路径(包括尾部斜杠)。

第二个值120表示了一分钟内演奏多少个四分音符。

第三个值是重复次数,默认为0,即不重复。

第四个值是文件存储路径。

第三行,一个值,表示调式。可选的有:

c c# d d# e f f# g g# a a# b

第五行,一个值,表示一个数字算作几个四分音符。如果没有特殊需要,填1就可以

乐谱部分。

简谱表示

升音用#

降音用&

半音用_

延音用-

附点用.

高八度用+

降八度用!

(全部用英文符)

接下来会逐渐(断断续续)发布一些相关的音乐材料(txt文件,用刚才的1.py解释一下就可以导出为wav文件了)

OK再~见~~~

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Unconquerable p

给点吧~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值