--*--
(!)有更新版本:Python音乐制作-紧急修复版v1.2_Unconquerable&Llxy的博客-CSDN博客
--*--
外来库:Pysynth
PySynth — A Music Synthesizer for Pythonhttps://mdoege.github.io/PySynth/#d
文件资源:
音色有多种,取决于不同模块。这里不过多赘述。
上 代 码
文件(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-8910或Atari 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再~见~~~