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 ()
0 commit comments