MikuAI/rvc/main.py
2024-03-31 19:52:44 +00:00

111 lines
4.4 KiB
Python

import gc
import os
import soundfile as sf
import sox
#from pedalboard import Pedalboard, Reverb, Compressor, HighpassFilter
#from pedalboard.io import AudioFile
from .rvc import Config, load_hubert, get_vc, rvc_infer
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
rvc_models_dir = os.path.join(BASE_DIR, 'rvc_models')
def get_rvc_model(voice_model):
rvc_model_filename, rvc_index_filename = None, None
model_dir = os.path.join(rvc_models_dir, voice_model)
for file in os.listdir(model_dir):
ext = os.path.splitext(file)[1]
if ext == '.pth':
rvc_model_filename = file
if ext == '.index':
rvc_index_filename = file
if rvc_model_filename is None:
error_msg = f'No model file exists in {model_dir}.'
raise NameError(error_msg)
return os.path.join(model_dir, rvc_model_filename), os.path.join(model_dir, rvc_index_filename) if rvc_index_filename else ''
def pitch_shift(audio_path, pitch_change):
output_path = f'{os.path.splitext(audio_path)[0]}_p{pitch_change}.wav'
if not os.path.exists(output_path):
y, sr = sf.read(audio_path)
tfm = sox.Transformer()
tfm.pitch(pitch_change)
y_shifted = tfm.build_array(input_array=y, sample_rate_in=sr)
sf.write(output_path, y_shifted, sr)
return output_path
def voice_change(voice_model, vocals_path, output_path, pitch_change, f0_method, index_rate, filter_radius, rms_mix_rate, protect, crepe_hop_length):
rvc_model_path, rvc_index_path = get_rvc_model(voice_model)
device = 'cuda:0'
config = Config(device, True)
hubert_model = load_hubert(device, config.is_half, os.path.join(rvc_models_dir, 'hubert_base.pt'))
cpt, version, net_g, tgt_sr, vc = get_vc(device, config.is_half, config, rvc_model_path)
# convert main vocals
try:
rvc_infer(rvc_index_path, index_rate, vocals_path, output_path, pitch_change, f0_method, cpt, version, net_g, filter_radius, tgt_sr, rms_mix_rate, protect, crepe_hop_length, vc, hubert_model)
except Exception as err:
print(err)
finally:
del hubert_model, cpt
gc.collect()
'''
def add_audio_effects(audio_path, reverb_rm_size, reverb_wet, reverb_dry, reverb_damping):
output_path = f'{os.path.splitext(audio_path)[0]}_mixed.wav'
# Initialize audio effects plugins
board = Pedalboard(
[
HighpassFilter(),
Compressor(ratio=4, threshold_db=-15),
Reverb(room_size=reverb_rm_size, dry_level=reverb_dry, wet_level=reverb_wet, damping=reverb_damping)
]
)
with AudioFile(audio_path) as f:
with AudioFile(output_path, 'w', f.samplerate, f.num_channels) as o:
# Read one second of audio at a time, until the file is empty:
while f.tell() < f.frames:
chunk = f.read(int(f.samplerate))
effected = board(chunk, f.samplerate, reset=False)
o.write(effected)
return output_path
'''
def song_cover_pipeline(song_input, pitch_change_oct, voice_model='miku',
main_gain=0, backup_gain=0, inst_gain=0, index_rate=0.5, filter_radius=3,
rms_mix_rate=0.25, f0_method='rmvpe', crepe_hop_length=128, protect=0.33, pitch_change_sem=0,
reverb_rm_size=0.15, reverb_wet=0.2, reverb_dry=0.8, reverb_damping=0.7, output_format='mp3'):
try:
orig_vocals_path = song_input.strip('\"')
pitch_change = pitch_change_oct * 12 + pitch_change_sem
ai_vocals_path = os.path.join(
os.path.dirname(song_input),
f'{os.path.splitext(os.path.basename(orig_vocals_path))[0]}_{voice_model}_p{pitch_change}_i{index_rate}_fr{filter_radius}_rms{rms_mix_rate}_pro{protect}_{f0_method}{"" if f0_method != "mangio-crepe" else f"_{crepe_hop_length}"}.wav'
)
print(f'Output file path will be: {ai_vocals_path}')
if not os.path.exists(ai_vocals_path):
print('[~] Converting voice using RVC...')
voice_change(voice_model, orig_vocals_path, ai_vocals_path, pitch_change, f0_method, index_rate, filter_radius, rms_mix_rate, protect, crepe_hop_length)
#display_progress('[~] Applying audio effects to Vocals...', 0.8, is_webui, progress)
#ai_vocals_mixed_path = add_audio_effects(ai_vocals_path, reverb_rm_size, reverb_wet, reverb_dry, reverb_damping)
return ai_vocals_path
except Exception as e:
print(e)