Skip to content

Commit 9a3391c

Browse files
2 parents 1824d99 + a1ea911 commit 9a3391c

7 files changed

Lines changed: 206 additions & 2 deletions

File tree

.github/workflows/main.yml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
on:
2+
workflow_dispatch:
3+
inputs:
4+
version:
5+
description: '版本号'
6+
default: '0.0.0'
7+
required: true
8+
type: string
9+
10+
jobs:
11+
pack-windows:
12+
runs-on: ${{ matrix.os }}
13+
14+
strategy:
15+
matrix:
16+
os: [ 'windows-latest' ]
17+
18+
steps:
19+
- uses: actions/checkout@v1
20+
21+
- name: Download Winpython
22+
uses: carlosperate/download-file-action@v1.0.3
23+
with:
24+
file-url: https://github.com/winpython/winpython/releases/download/4.3.20210620/Winpython64-3.8.10.0dot.exe
25+
file-name: Winpython64-3.8.10.0dot.exe
26+
location: ${{ github.workspace }}
27+
28+
- name: Extract Winpython
29+
run: 7z x -o"${{ github.workspace }}" "${{ github.workspace }}/Winpython64-3.8.10.0dot.exe"
30+
31+
- name: Install python packages
32+
run: .\build.bat
33+
34+
- name: remove Winpython installer
35+
run: del "${{ github.workspace }}/Winpython64-3.8.10.0dot.exe"
36+
37+
- name: pack
38+
run: 7z a .\diffsinger-server.zip .\*
39+
40+
- name: upload
41+
uses: actions/upload-artifact@v1.0.0
42+
with:
43+
name: diffsinger-server-cpu-${{ inputs.version }}.zip
44+
path: ${{ github.workspace }}\diffsinger-server.zip

.gitignore

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,8 @@ local_tools/
88
*.wav
99
infer_out/
1010
config.yaml
11-
*.onnx
11+
*.onnx
12+
13+
.vscode
14+
WPy64-38100
15+
Winpython64-3.8.10.0dot.exe

build.bat

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
WPy64-38100\python-3.8.10.amd64\python -m pip install "https://download.pytorch.org/whl/cpu/torch-1.6.0%%2Bcpu-cp38-cp38-win_amd64.whl"
2+
WPy64-38100\python-3.8.10.amd64\python -m pip install https://download.pytorch.org/whl/torchaudio-0.6.0-cp38-none-win_amd64.whl
3+
WPy64-38100\python-3.8.10.amd64\python -m pip install "https://download.pytorch.org/whl/cpu/torchvision-0.7.0%%2Bcpu-cp38-cp38-win_amd64.whl"
4+
WPy64-38100\python-3.8.10.amd64\python -m pip install -r requirements_2080.txt
5+
WPy64-38100\python-3.8.10.amd64\python -m pip install -r requirements_server.txt

requirements_server.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pyzmq==23.2.0

run.bat

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
WPy64-38100\python-3.8.10.amd64\python.exe server.py

server.py

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
# coding=utf8
2+
print('Starting diffsinger server...')
3+
import json
4+
import os
5+
import sys
6+
import traceback
7+
import zmq
8+
9+
from inference.svs.ds_e2e import DiffSingerE2EInfer
10+
11+
notedict={
12+
0:"C",
13+
1:"C#",
14+
2:"D",
15+
3:"D#",
16+
4:"E",
17+
5:"F",
18+
6:"F#",
19+
7:"G",
20+
8:"G#",
21+
9:"A",
22+
10:"A#",
23+
11:"B"
24+
}
25+
26+
def poll_socket(socket, timetick = 100):
27+
poller = zmq.Poller()
28+
poller.register(socket, zmq.POLLIN)
29+
# wait up to 100msec
30+
try:
31+
while True:
32+
obj = dict(poller.poll(timetick))
33+
if socket in obj and obj[socket] == zmq.POLLIN:
34+
yield socket.recv()
35+
except KeyboardInterrupt:
36+
pass
37+
# Escape while loop if there's a keyboard interrupt.
38+
39+
def readblocks(ustfile):
40+
#迭代器,从ust文件中逐个读取块,以字典形式返回
41+
current_block_data=dict()
42+
for line in ustfile.readlines():
43+
if(line.startswith("[")):#块的开始
44+
#先返回上一个
45+
if(len(current_block_data)>=1):
46+
yield current_block_data
47+
#然后开新块
48+
current_block_data={"name":line.strip("[#]\n")}
49+
pass
50+
else:
51+
(key,value)=line.strip("\n").split("=")
52+
current_block_data[key]=value
53+
pass
54+
if(len(current_block_data)>=1):#返回最后一个
55+
yield current_block_data
56+
57+
def acoustic(ustpath:str):
58+
#解析ust文件为diffsinger所需格式
59+
#参考:main.py
60+
wavpath=ustpath[:-4]+".wav"
61+
62+
tempo=120
63+
project=""
64+
voiceDir=""
65+
cacheDir=""
66+
67+
ph_seq=[]
68+
note_seq=[]
69+
ph_dur=[]
70+
is_slur_seq=[]
71+
72+
with open(ustpath) as ustfile:
73+
for block in readblocks(ustfile):
74+
if(block["name"]=="SETTING"):#音轨信息块
75+
tempo=float(block["Tempo"])
76+
project=block["Project"]
77+
voiceDir=block["VoiceDir"]
78+
cacheDir=block["CacheDir"]
79+
elif(block["name"].isdigit()):#音符
80+
lyric=block["Lyric"]
81+
notenum=int(block["NoteNum"])
82+
length=int(block["Length"])
83+
if(lyric=="-"):#;连音符
84+
ph_seq.append(ph_seq[-1])
85+
note_seq.append(notedict[notenum%12]+str(notenum//12-1))
86+
ph_dur.append(str(length/(tempo*8)))
87+
is_slur_seq.append("1")
88+
elif(lyric!="R"):
89+
ph_seq.append(lyric)
90+
note_seq.append(notedict[notenum%12]+str(notenum//12-1))
91+
ph_dur.append(str(length/(tempo*8)))
92+
is_slur_seq.append("0")
93+
ph_seq=" ".join(ph_seq)
94+
print("Phonemes:",ph_seq)
95+
inp={
96+
"text":"",
97+
"ph_seq":ph_seq,
98+
"note_seq":" ".join(note_seq),
99+
"ph_dur":" ".join(ph_dur),
100+
"note_dur_seq":" ".join(ph_dur),
101+
"is_slur_seq":" ".join(is_slur_seq),
102+
'input_type': 'phoneme'
103+
}
104+
#合成
105+
DiffSingerE2EInfer.example_run(inp, target=wavpath)
106+
return {
107+
'path_wav': wavpath,
108+
}
109+
110+
#为了方便调试,把argv配置放外面
111+
root_dir = os.path.dirname(__file__)
112+
sys.argv = [
113+
f'{root_dir}/inference/svs/ds_e2e.py',
114+
'--config',
115+
f'{root_dir}/usr/configs/midi/e2e/opencpop/ds100_adj_rel.yaml',
116+
'--exp_name',
117+
'0228_opencpop_ds100_rel']
118+
119+
def main():
120+
context = zmq.Context()
121+
socket = context.socket(zmq.REP)
122+
socket.bind('tcp://*:38442')
123+
print('Started diffsinger server')
124+
125+
for message in poll_socket(socket):
126+
request = json.loads(message)
127+
print("="*40)
128+
print('Received request: %s' % request)
129+
response = {}
130+
try:
131+
#if request[0] == 'timing':
132+
# response['result'] = timing(request[1])
133+
if request[0] == 'acoustic':
134+
response['result'] = acoustic(request[1])
135+
else:
136+
raise NotImplementedError('unexpected command %s' % request[0])
137+
except Exception as e:
138+
response['error'] = str(e)
139+
traceback.print_exc()
140+
141+
print('Sending response: %s' % response)
142+
socket.send_string(json.dumps(response))
143+
144+
if(__name__=="__main__"):
145+
main()

utils/hparams.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,11 @@ def set_hparams(config='', exp_name='', hparams_str='', print_hparams=True, glob
4545
loaded_config = set()
4646

4747
def load_config(config_fn): # deep first
48-
with open(config_fn, encoding='utf-8') as f:
48+
if(config_fn.startswith("/")):
49+
config_fn_path=os.path.abspath(config_fn[1:])
50+
else:
51+
config_fn_path=config_fn
52+
with open(config_fn_path, encoding='utf-8') as f:
4953
hparams_ = yaml.safe_load(f)
5054
loaded_config.add(config_fn)
5155
if 'base_config' in hparams_:

0 commit comments

Comments
 (0)