Spaces:
Runtime error
Runtime error
"""Module which defines the code for the "Multi-step generation" tab.""" | |
from typing import TYPE_CHECKING, Any | |
from collections.abc import Sequence | |
from functools import partial | |
import gradio as gr | |
from ultimate_rvc.core.generate.song_cover import ( | |
convert, | |
mix_song, | |
pitch_shift, | |
postprocess, | |
retrieve_song, | |
separate_audio, | |
) | |
from ultimate_rvc.typing_extra import ( | |
AudioExt, | |
F0Method, | |
SampleRate, | |
SegmentSize, | |
SeparationModel, | |
) | |
from ultimate_rvc.web.common import ( | |
PROGRESS_BAR, | |
exception_harness, | |
toggle_visible_component, | |
update_cached_songs, | |
update_output_audio, | |
update_song_cover_name, | |
update_value, | |
) | |
from ultimate_rvc.web.typing_extra import ConcurrencyId, SourceType | |
if TYPE_CHECKING: | |
from ultimate_rvc.web.typing_extra import UpdateAudioKwArgs | |
def _update_audio( | |
num_components: int, | |
output_indices: Sequence[int], | |
track: str | None, | |
disallow_none: bool = True, | |
) -> gr.Audio | tuple[gr.Audio, ...]: | |
""" | |
Update the value of a subset of `Audio` components to the given | |
audio track. | |
Parameters | |
---------- | |
num_components : int | |
The total number of `Audio` components under consideration. | |
output_indices : Sequence[int] | |
Indices of `Audio` components to update the value for. | |
track : str | |
Path pointing to an audio track to update the value of the | |
indexed `Audio` components with. | |
disallow_none : bool, default=True | |
Whether to disallow the value of the indexed components to be | |
`None`. | |
Returns | |
------- | |
gr.Audio | tuple[gr.Audio, ...] | |
Each `Audio` component under consideration with the value of the | |
indexed components updated to the given audio track. | |
""" | |
update_args_list: list[UpdateAudioKwArgs] = [{} for _ in range(num_components)] | |
for index in output_indices: | |
if track or not disallow_none: | |
update_args_list[index]["value"] = track | |
match update_args_list: | |
case [update_args]: | |
return gr.Audio(**update_args) | |
case _: | |
return tuple(gr.Audio(**update_args) for update_args in update_args_list) | |
def _pair_audio_tracks_and_gain( | |
audio_components: Sequence[gr.Audio], | |
gain_components: Sequence[gr.Slider], | |
data: dict[gr.Audio | gr.Slider, Any], | |
) -> list[tuple[str, int]]: | |
""" | |
Pair audio tracks and gain levels stored in separate gradio | |
components. | |
This function is meant to first be partially applied to the sequence | |
of audio components and the sequence of slider components containing | |
the values that should be combined. The resulting function can then | |
be called by an event listener whose inputs is a set containing | |
those audio and slider components. The `data` parameter in that case | |
will contain a mapping from each of those components to the value | |
that the component stores. | |
Parameters | |
---------- | |
audio_components : Sequence[gr.Audio] | |
Audio components to pair with gain levels. | |
gain_components : Sequence[gr.Slider] | |
Gain level components to pair with audio tracks. | |
data : dict[gr.Audio | gr.Slider, Any] | |
Data from the audio and gain components. | |
Returns | |
------- | |
list[tuple[str, int]] | |
Paired audio tracks and gain levels. | |
Raises | |
------ | |
ValueError | |
If the number of audio tracks and gain levels are not the same. | |
""" | |
audio_tracks = [data[component] for component in audio_components] | |
gain_levels = [data[component] for component in gain_components] | |
if len(audio_tracks) != len(gain_levels): | |
err_msg = "Number of audio tracks and gain levels must be the same." | |
raise ValueError(err_msg) | |
return [ | |
(audio_track, gain_level) | |
for audio_track, gain_level in zip(audio_tracks, gain_levels, strict=True) | |
if audio_track | |
] | |
def render( | |
song_dirs: Sequence[gr.Dropdown], | |
cached_song_1click: gr.Dropdown, | |
cached_song_multi: gr.Dropdown, | |
model_multi: gr.Dropdown, | |
intermediate_audio: gr.Dropdown, | |
output_audio: gr.Dropdown, | |
) -> None: | |
""" | |
Render "Multi-step generation" tab. | |
Parameters | |
---------- | |
song_dirs : Sequence[gr.Dropdown] | |
Dropdowns for selecting song directories in the | |
"Multi-step generation" tab. | |
cached_song_1click : gr.Dropdown | |
Dropdown for selecting a cached song in the | |
"One-click generation" tab. | |
cached_song_multi : gr.Dropdown | |
Dropdown for selecting a cached song in the | |
"Multi-step generation" tab. | |
model_multi : gr.Dropdown | |
Dropdown for selecting a voice model in the | |
"Multi-step generation" tab. | |
intermediate_audio : gr.Dropdown | |
Dropdown for selecting intermediate audio files to delete in the | |
"Delete audio" tab. | |
output_audio : gr.Dropdown | |
Dropdown for selecting output audio files to delete in the | |
"Delete audio" tab. | |
""" | |
with gr.Tab("Multi-step generation"): | |
( | |
separate_audio_dir, | |
convert_vocals_dir, | |
postprocess_vocals_dir, | |
pitch_shift_background_dir, | |
mix_dir, | |
) = song_dirs | |
current_song_dir = gr.State(None) | |
input_tracks = [ | |
gr.Audio(label=label, type="filepath", render=False) | |
for label in [ | |
"Audio", | |
"Vocals", | |
"Vocals", | |
"Instrumentals", | |
"Backup vocals", | |
"Main vocals", | |
"Instrumentals", | |
"Backup vocals", | |
] | |
] | |
( | |
audio_track_input, | |
vocals_track_input, | |
converted_vocals_track_input, | |
instrumentals_track_input, | |
backup_vocals_track_input, | |
main_vocals_track_input, | |
shifted_instrumentals_track_input, | |
shifted_backup_vocals_track_input, | |
) = input_tracks | |
( | |
song_output, | |
primary_stem_output, | |
secondary_stem_output, | |
converted_vocals_track_output, | |
effected_vocals_track_output, | |
shifted_instrumentals_track_output, | |
shifted_backup_vocals_track_output, | |
song_cover_output, | |
) = [ | |
gr.Audio(label=label, type="filepath", interactive=False, render=False) | |
for label in [ | |
"Song", | |
"Primary stem", | |
"Secondary stem", | |
"Converted vocals", | |
"Effected vocals", | |
"Pitch-shifted instrumentals", | |
"Pitch-shifted backup vocals", | |
"Song cover", | |
] | |
] | |
transfer_defaults = [ | |
["Step 1: audio"], | |
["Step 2: vocals"], | |
["Step 4: instrumentals"], | |
["Step 3: vocals"], | |
["Step 5: main vocals"], | |
["Step 5: instrumentals"], | |
["Step 5: backup vocals"], | |
[], | |
] | |
( | |
song_transfer_default, | |
primary_stem_transfer_default, | |
secondary_stem_transfer_default, | |
converted_vocals_transfer_default, | |
effected_vocals_transfer_default, | |
shifted_instrumentals_transfer_default, | |
shifted_backup_vocals_transfer_default, | |
song_cover_transfer_default, | |
) = transfer_defaults | |
( | |
song_transfer, | |
primary_stem_transfer, | |
secondary_stem_transfer, | |
converted_vocals_transfer, | |
effected_vocals_transfer, | |
shifted_instrumentals_transfer, | |
shifted_backup_vocals_transfer, | |
song_cover_transfer, | |
) = [ | |
gr.Dropdown( | |
[ | |
"Step 1: audio", | |
"Step 2: vocals", | |
"Step 3: vocals", | |
"Step 4: instrumentals", | |
"Step 4: backup vocals", | |
"Step 5: main vocals", | |
"Step 5: instrumentals", | |
"Step 5: backup vocals", | |
], | |
label=f"{label_prefix} destination", | |
info=( | |
"Select the input track(s) to transfer the" | |
f" {label_prefix.lower()} to when the 'Transfer" | |
f" {label_prefix.lower()}' button is clicked." | |
), | |
render=False, | |
type="index", | |
multiselect=True, | |
value=value, | |
) | |
for value, label_prefix in zip( | |
transfer_defaults, | |
[ | |
"Song", | |
"Primary stem", | |
"Secondary stem", | |
"Converted vocals", | |
"Effected vocals", | |
"Pitch-shifted instrumentals", | |
"Pitch-shifted backup vocals", | |
"Song cover", | |
], | |
strict=True, | |
) | |
] | |
with gr.Accordion("Step 0: song retrieval", open=True): | |
gr.Markdown("") | |
gr.Markdown("**Inputs**") | |
with gr.Row(): | |
with gr.Column(): | |
source_type = gr.Dropdown( | |
list(SourceType), | |
value=SourceType.PATH, | |
label="Source type", | |
type="index", | |
info="The type of source to retrieve a song from.", | |
) | |
with gr.Column(): | |
source = gr.Textbox( | |
label="Source", | |
info=( | |
"Link to a song on YouTube or the full path of a local" | |
" audio file." | |
), | |
) | |
local_file = gr.Audio( | |
label="Source", | |
type="filepath", | |
visible=False, | |
) | |
cached_song_multi.render() | |
source_type.input( | |
partial(toggle_visible_component, 3), | |
inputs=source_type, | |
outputs=[source, local_file, cached_song_multi], | |
show_progress="hidden", | |
) | |
local_file.change( | |
update_value, | |
inputs=local_file, | |
outputs=source, | |
show_progress="hidden", | |
) | |
cached_song_multi.input( | |
update_value, | |
inputs=cached_song_multi, | |
outputs=source, | |
show_progress="hidden", | |
) | |
gr.Markdown("**Settings**") | |
song_transfer.render() | |
gr.Markdown("**Outputs**") | |
song_output.render() | |
gr.Markdown("**Controls**") | |
retrieve_song_btn = gr.Button("Retrieve song", variant="primary") | |
song_transfer_btn = gr.Button("Transfer song") | |
retrieve_song_reset_btn = gr.Button("Reset settings") | |
retrieve_song_reset_btn.click( | |
lambda: gr.Dropdown(value=song_transfer_default), | |
outputs=song_transfer, | |
show_progress="hidden", | |
) | |
retrieve_song_btn.click( | |
partial( | |
exception_harness( | |
retrieve_song, | |
info_msg="Song retrieved successfully!", | |
), | |
progress_bar=PROGRESS_BAR, | |
), | |
inputs=source, | |
outputs=[song_output, current_song_dir], | |
).then( | |
partial( | |
update_cached_songs, | |
len(song_dirs) + 2, | |
value_indices=range(len(song_dirs)), | |
), | |
inputs=current_song_dir, | |
outputs=([*song_dirs, cached_song_multi, cached_song_1click]), | |
show_progress="hidden", | |
).then( | |
partial(update_cached_songs, 1, [], [0]), | |
outputs=intermediate_audio, | |
show_progress="hidden", | |
) | |
with gr.Accordion("Step 1: vocal separation", open=False): | |
gr.Markdown("") | |
gr.Markdown("**Inputs**") | |
audio_track_input.render() | |
separate_audio_dir.render() | |
gr.Markdown("**Settings**") | |
with gr.Row(): | |
separation_model = gr.Dropdown( | |
list(SeparationModel), | |
value=SeparationModel.UVR_MDX_NET_VOC_FT, | |
label="Separation model", | |
info="The model to use for audio separation.", | |
) | |
segment_size = gr.Radio( | |
list(SegmentSize), | |
value=SegmentSize.SEG_512, | |
label="Segment size", | |
info=( | |
"Size of segments into which the audio is split. Larger" | |
" consumes more resources, but may give better results." | |
), | |
) | |
with gr.Row(): | |
primary_stem_transfer.render() | |
secondary_stem_transfer.render() | |
gr.Markdown("**Outputs**") | |
with gr.Row(): | |
primary_stem_output.render() | |
secondary_stem_output.render() | |
gr.Markdown("**Controls**") | |
separate_vocals_btn = gr.Button("Separate vocals", variant="primary") | |
with gr.Row(): | |
primary_stem_transfer_btn = gr.Button("Transfer primary stem") | |
secondary_stem_transfer_btn = gr.Button("Transfer secondary stem") | |
separate_audio_reset_btn = gr.Button("Reset settings") | |
separate_audio_reset_btn.click( | |
lambda: [ | |
SeparationModel.UVR_MDX_NET_VOC_FT, | |
SegmentSize.SEG_512, | |
gr.Dropdown(value=primary_stem_transfer_default), | |
gr.Dropdown(value=secondary_stem_transfer_default), | |
], | |
outputs=[ | |
separation_model, | |
segment_size, | |
primary_stem_transfer, | |
secondary_stem_transfer, | |
], | |
show_progress="hidden", | |
) | |
separate_vocals_btn.click( | |
partial( | |
exception_harness( | |
separate_audio, | |
info_msg="Vocals separated successfully!", | |
), | |
progress_bar=PROGRESS_BAR, | |
), | |
inputs=[ | |
audio_track_input, | |
separate_audio_dir, | |
separation_model, | |
segment_size, | |
], | |
outputs=[primary_stem_output, secondary_stem_output], | |
concurrency_limit=1, | |
concurrency_id=ConcurrencyId.GPU, | |
) | |
with gr.Accordion("Step 2: vocal conversion", open=False): | |
gr.Markdown("") | |
gr.Markdown("**Inputs**") | |
vocals_track_input.render() | |
with gr.Row(): | |
convert_vocals_dir.render() | |
if model_multi.info: | |
model_multi.info += "<br><br>" | |
model_multi.render() | |
gr.Markdown("**Settings**") | |
with gr.Row(): | |
n_octaves = gr.Slider( | |
-3, | |
3, | |
value=0, | |
step=1, | |
label="Pitch shift (octaves)", | |
info=( | |
"The number of octaves to pitch-shift the converted vocals by." | |
" Use 1 for male-to-female and -1 for vice-versa." | |
), | |
) | |
n_semitones = gr.Slider( | |
-12, | |
12, | |
value=0, | |
step=1, | |
label="Pitch shift (semi-tones)", | |
info=( | |
"The number of semi-tones to pitch-shift the converted vocals" | |
" by. Altering this slightly reduces sound quality." | |
), | |
) | |
with gr.Row(): | |
index_rate = gr.Slider( | |
0, | |
1, | |
value=0.5, | |
label="Index rate", | |
info=( | |
"How much of the accent in the voice model to keep in the" | |
" converted vocals. Increase to bias the conversion towards the" | |
" accent of the voice model." | |
), | |
) | |
filter_radius = gr.Slider( | |
0, | |
7, | |
value=3, | |
step=1, | |
label="Filter radius", | |
info=( | |
"If >=3: apply median filtering to harvested pitch results." | |
" Can help reduce breathiness in the converted vocals." | |
), | |
) | |
rms_mix_rate = gr.Slider( | |
0, | |
1, | |
value=0.25, | |
label="RMS mix rate", | |
info=( | |
"How much to mimic the loudness (0) of the input vocals or a" | |
" fixed loudness (1)." | |
"<br><br>" | |
), | |
) | |
with gr.Row(): | |
protect = gr.Slider( | |
0, | |
0.5, | |
value=0.33, | |
label="Protect rate", | |
info=( | |
"Protection of voiceless consonants and breath sounds. Decrease" | |
" to increase protection at the cost of indexing accuracy. Set" | |
" to 0.5 to disable." | |
"<br>" | |
), | |
) | |
f0_method = gr.Dropdown( | |
list(F0Method), | |
value=F0Method.RMVPE, | |
label="Pitch detection algorithm", | |
info=( | |
"The method to use for pitch detection. Best option is" | |
" RMVPE (clarity in vocals), then Mangio-CREPE (smoother" | |
" vocals)." | |
"<br><br>" | |
), | |
) | |
hop_length = gr.Slider( | |
32, | |
320, | |
value=128, | |
step=1, | |
label="Hop length", | |
info=( | |
"How often the CREPE-based pitch detection algorithm checks" | |
" for pitch changes. Measured in milliseconds. Lower values" | |
" lead to longer conversion times and a higher risk of" | |
" voice cracks, but better pitch accuracy." | |
), | |
) | |
converted_vocals_transfer.render() | |
gr.Markdown("**Outputs**") | |
converted_vocals_track_output.render() | |
gr.Markdown("**Controls**") | |
convert_vocals_btn = gr.Button("Convert vocals", variant="primary") | |
converted_vocals_transfer_btn = gr.Button("Transfer converted vocals") | |
convert_vocals_reset_btn = gr.Button("Reset settings") | |
convert_vocals_reset_btn.click( | |
lambda: [ | |
0, | |
0, | |
0.5, | |
3, | |
0.25, | |
0.33, | |
F0Method.RMVPE, | |
128, | |
gr.Dropdown(value=converted_vocals_transfer_default), | |
], | |
outputs=[ | |
n_octaves, | |
n_semitones, | |
index_rate, | |
filter_radius, | |
rms_mix_rate, | |
protect, | |
f0_method, | |
hop_length, | |
converted_vocals_transfer, | |
], | |
show_progress="hidden", | |
) | |
convert_vocals_btn.click( | |
partial( | |
exception_harness( | |
convert, | |
info_msg="Vocals converted successfully!", | |
), | |
progress_bar=PROGRESS_BAR, | |
), | |
inputs=[ | |
vocals_track_input, | |
convert_vocals_dir, | |
model_multi, | |
n_octaves, | |
n_semitones, | |
f0_method, | |
index_rate, | |
filter_radius, | |
rms_mix_rate, | |
protect, | |
hop_length, | |
], | |
outputs=converted_vocals_track_output, | |
concurrency_id=ConcurrencyId.GPU, | |
concurrency_limit=1, | |
) | |
with gr.Accordion("Step 3: vocal post-processing", open=False): | |
gr.Markdown("") | |
gr.Markdown("**Inputs**") | |
converted_vocals_track_input.render() | |
postprocess_vocals_dir.render() | |
gr.Markdown("**Settings**") | |
with gr.Row(): | |
room_size = gr.Slider( | |
0, | |
1, | |
value=0.15, | |
label="Room size", | |
info=( | |
"Size of the room which reverb effect simulates. Increase for" | |
" longer reverb time." | |
), | |
) | |
with gr.Row(): | |
wet_level = gr.Slider( | |
0, | |
1, | |
value=0.2, | |
label="Wetness level", | |
info="Loudness of converted vocals with reverb effect applied.", | |
) | |
dry_level = gr.Slider( | |
0, | |
1, | |
value=0.8, | |
label="Dryness level", | |
info="Loudness of converted vocals without reverb effect applied.", | |
) | |
damping = gr.Slider( | |
0, | |
1, | |
value=0.7, | |
label="Damping level", | |
info="Absorption of high frequencies in reverb effect.", | |
) | |
effected_vocals_transfer.render() | |
gr.Markdown("**Outputs**") | |
effected_vocals_track_output.render() | |
gr.Markdown("**Controls**") | |
postprocess_vocals_btn = gr.Button( | |
"Post-process vocals", | |
variant="primary", | |
) | |
effected_vocals_transfer_btn = gr.Button("Transfer effected vocals") | |
postprocess_vocals_reset_btn = gr.Button("Reset settings") | |
postprocess_vocals_reset_btn.click( | |
lambda: [ | |
0.15, | |
0.2, | |
0.8, | |
0.7, | |
gr.Dropdown(value=effected_vocals_transfer_default), | |
], | |
outputs=[ | |
room_size, | |
wet_level, | |
dry_level, | |
damping, | |
effected_vocals_transfer, | |
], | |
show_progress="hidden", | |
) | |
postprocess_vocals_btn.click( | |
partial( | |
exception_harness( | |
postprocess, | |
info_msg="Vocals post-processed successfully!", | |
), | |
progress_bar=PROGRESS_BAR, | |
), | |
inputs=[ | |
converted_vocals_track_input, | |
postprocess_vocals_dir, | |
room_size, | |
wet_level, | |
dry_level, | |
damping, | |
], | |
outputs=effected_vocals_track_output, | |
) | |
with gr.Accordion("Step 4: pitch shift of background audio", open=False): | |
gr.Markdown("") | |
gr.Markdown("**Inputs**") | |
with gr.Row(): | |
instrumentals_track_input.render() | |
backup_vocals_track_input.render() | |
pitch_shift_background_dir.render() | |
gr.Markdown("**Settings**") | |
with gr.Row(): | |
n_semitones_instrumentals = gr.Slider( | |
-12, | |
12, | |
value=0, | |
step=1, | |
label="Instrumental pitch shift", | |
info="The number of semi-tones to pitch-shift the instrumentals by", | |
) | |
n_semitones_backup_vocals = gr.Slider( | |
-12, | |
12, | |
value=0, | |
step=1, | |
label="Backup vocal pitch shift", | |
info="The number of semi-tones to pitch-shift the backup vocals by", | |
) | |
with gr.Row(): | |
if shifted_instrumentals_transfer.info: | |
shifted_instrumentals_transfer.info += "<br><br>" | |
shifted_instrumentals_transfer.render() | |
shifted_backup_vocals_transfer.render() | |
gr.Markdown("**Outputs**") | |
with gr.Row(): | |
shifted_instrumentals_track_output.render() | |
shifted_backup_vocals_track_output.render() | |
gr.Markdown("**Controls**") | |
with gr.Row(): | |
pitch_shift_instrumentals_btn = gr.Button( | |
"Pitch shift instrumentals", | |
variant="primary", | |
) | |
pitch_shift_backup_vocals_btn = gr.Button( | |
"Pitch shift backup vocals", | |
variant="primary", | |
) | |
with gr.Row(): | |
shifted_instrumentals_transfer_btn = gr.Button( | |
"Transfer pitch-shifted instrumentals", | |
) | |
shifted_backup_vocals_transfer_btn = gr.Button( | |
"Transfer pitch-shifted backup vocals", | |
) | |
pitch_shift_background_reset_btn = gr.Button("Reset settings") | |
pitch_shift_background_reset_btn.click( | |
lambda: [ | |
0, | |
0, | |
gr.Dropdown(value=shifted_instrumentals_transfer_default), | |
gr.Dropdown(value=shifted_backup_vocals_transfer_default), | |
], | |
outputs=[ | |
n_semitones_instrumentals, | |
n_semitones_backup_vocals, | |
shifted_instrumentals_transfer, | |
shifted_backup_vocals_transfer, | |
], | |
show_progress="hidden", | |
) | |
pitch_shift_instrumentals_btn.click( | |
partial( | |
exception_harness( | |
pitch_shift, | |
info_msg="Instrumentals pitch-shifted successfully!", | |
), | |
display_msg="Pitch shifting instrumentals...", | |
progress_bar=PROGRESS_BAR, | |
), | |
inputs=[ | |
instrumentals_track_input, | |
pitch_shift_background_dir, | |
n_semitones_instrumentals, | |
], | |
outputs=shifted_instrumentals_track_output, | |
) | |
pitch_shift_backup_vocals_btn.click( | |
partial( | |
exception_harness( | |
pitch_shift, | |
info_msg="Backup vocals pitch-shifted successfully!", | |
), | |
display_msg="Pitch shifting backup vocals...", | |
progress_bar=PROGRESS_BAR, | |
), | |
inputs=[ | |
backup_vocals_track_input, | |
pitch_shift_background_dir, | |
n_semitones_backup_vocals, | |
], | |
outputs=shifted_backup_vocals_track_output, | |
) | |
with gr.Accordion("Step 5: song mixing", open=False): | |
gr.Markdown("") | |
gr.Markdown("**Inputs**") | |
with gr.Row(): | |
main_vocals_track_input.render() | |
shifted_instrumentals_track_input.render() | |
shifted_backup_vocals_track_input.render() | |
mix_dir.render() | |
gr.Markdown("**Settings**") | |
with gr.Row(): | |
main_gain = gr.Slider( | |
-20, | |
20, | |
value=0, | |
step=1, | |
label="Main gain", | |
info="The gain to apply to the main vocals.", | |
) | |
inst_gain = gr.Slider( | |
-20, | |
20, | |
value=0, | |
step=1, | |
label="Instrumentals gain", | |
info="The gain to apply to the instrumentals.", | |
) | |
backup_gain = gr.Slider( | |
-20, | |
20, | |
value=0, | |
step=1, | |
label="Backup gain", | |
info="The gain to apply to the backup vocals.", | |
) | |
with gr.Row(): | |
output_name = gr.Textbox( | |
value=update_song_cover_name, | |
inputs=[main_vocals_track_input, mix_dir], | |
label="Output name", | |
placeholder="Ultimate RVC song cover", | |
info=( | |
"If no name is provided, a suitable name will be generated" | |
" automatically." | |
), | |
) | |
output_sr = gr.Dropdown( | |
choices=list(SampleRate), | |
value=SampleRate.HZ_44100, | |
label="Output sample rate", | |
info="The sample rate to save the generated song in.", | |
) | |
output_format = gr.Dropdown( | |
list(AudioExt), | |
value=AudioExt.MP3, | |
label="Output format", | |
info="The format to save the generated song in.", | |
) | |
song_cover_transfer.render() | |
gr.Markdown("**Outputs**") | |
song_cover_output.render() | |
gr.Markdown("**Controls**") | |
mix_btn = gr.Button("Mix song cover", variant="primary") | |
song_cover_transfer_btn = gr.Button("Transfer song cover") | |
mix_reset_btn = gr.Button("Reset settings") | |
mix_reset_btn.click( | |
lambda: [ | |
0, | |
0, | |
0, | |
SampleRate.HZ_44100, | |
AudioExt.MP3, | |
gr.Dropdown(value=song_cover_transfer_default), | |
], | |
outputs=[ | |
main_gain, | |
inst_gain, | |
backup_gain, | |
output_sr, | |
output_format, | |
song_cover_transfer, | |
], | |
show_progress="hidden", | |
) | |
temp_audio_gains = gr.State() | |
mix_btn.click( | |
partial( | |
_pair_audio_tracks_and_gain, | |
[ | |
main_vocals_track_input, | |
shifted_instrumentals_track_input, | |
shifted_backup_vocals_track_input, | |
], | |
[main_gain, inst_gain, backup_gain], | |
), | |
inputs={ | |
main_vocals_track_input, | |
shifted_instrumentals_track_input, | |
shifted_backup_vocals_track_input, | |
main_gain, | |
inst_gain, | |
backup_gain, | |
}, | |
outputs=temp_audio_gains, | |
).then( | |
partial( | |
exception_harness( | |
mix_song, | |
info_msg="Song cover succesfully generated.", | |
), | |
progress_bar=PROGRESS_BAR, | |
), | |
inputs=[ | |
temp_audio_gains, | |
mix_dir, | |
output_sr, | |
output_format, | |
output_name, | |
], | |
outputs=song_cover_output, | |
).then( | |
partial(update_output_audio, 1, [], [0]), | |
outputs=output_audio, | |
show_progress="hidden", | |
) | |
for btn, transfer, output in [ | |
(song_transfer_btn, song_transfer, song_output), | |
(primary_stem_transfer_btn, primary_stem_transfer, primary_stem_output), | |
( | |
secondary_stem_transfer_btn, | |
secondary_stem_transfer, | |
secondary_stem_output, | |
), | |
( | |
converted_vocals_transfer_btn, | |
converted_vocals_transfer, | |
converted_vocals_track_output, | |
), | |
( | |
effected_vocals_transfer_btn, | |
effected_vocals_transfer, | |
effected_vocals_track_output, | |
), | |
( | |
shifted_instrumentals_transfer_btn, | |
shifted_instrumentals_transfer, | |
shifted_instrumentals_track_output, | |
), | |
( | |
shifted_backup_vocals_transfer_btn, | |
shifted_backup_vocals_transfer, | |
shifted_backup_vocals_track_output, | |
), | |
(song_cover_transfer_btn, song_cover_transfer, song_cover_output), | |
]: | |
btn.click( | |
partial(_update_audio, len(input_tracks)), | |
inputs=[transfer, output], | |
outputs=input_tracks, | |
show_progress="hidden", | |
) | |