Spaces:
Sleeping
Sleeping
| import random | |
| import librosa | |
| import soundfile as sf | |
| import gradio as gr | |
| from pydub import AudioSegment | |
| from pydub.silence import split_on_silence | |
| def load_audio(file): | |
| audio, sr = librosa.load(file, sr=None) | |
| return audio, sr | |
| def sync_to_same_bpm(instrumental_1, instrumental_2): | |
| bpm_1 = librosa.beat.tempo(instrumental_1)[0] | |
| bpm_2 = librosa.beat.tempo(instrumental_2)[0] | |
| target_bpm = max(bpm_1, bpm_2) | |
| rate_1 = target_bpm / bpm_1 | |
| rate_2 = target_bpm / bpm_2 | |
| inst1_synced = librosa.effects.time_stretch(instrumental_1, rate_1) | |
| inst2_synced = librosa.effects.time_stretch(instrumental_2, rate_2) | |
| return inst1_synced, inst2_synced, target_bpm | |
| def split_vocals_on_silence(vocals_file): | |
| vocals_audio = AudioSegment.from_file(vocals_file) | |
| # Split vocals at points with at least 0.8 seconds of silence or near-silence | |
| vocal_segments = split_on_silence( | |
| vocals_audio, min_silence_len=800, silence_thresh=vocals_audio.dBFS - 14 | |
| ) | |
| return vocal_segments | |
| def create_mashup(opponent_vocals, player_vocals, instrumental_1, instrumental_2): | |
| # Load and sync audio files | |
| inst1_audio, sr = load_audio(instrumental_1) | |
| inst2_audio, _ = load_audio(instrumental_2) | |
| inst1_sync, inst2_sync, bpm = sync_to_same_bpm(inst1_audio, inst2_audio) | |
| # Split vocals into segments based on silence detection | |
| opponent_segments = split_vocals_on_silence(opponent_vocals) | |
| player_segments = split_vocals_on_silence(player_vocals) | |
| # Randomly alternate between opponent and player vocal segments | |
| vocal_turns = [] | |
| for _ in range(10): # Set the number of turns (adjustable) | |
| segment = random.choice(opponent_segments + player_segments) | |
| vocal_turns.append(segment) | |
| # Generate mashup by combining each vocal turn with alternating instrumentals | |
| mashup = [] | |
| for i, vocal_segment in enumerate(vocal_turns): | |
| inst = inst1_sync if i % 2 == 0 else inst2_sync | |
| vocal_segment = vocal_segment.set_frame_rate(sr).set_channels(1) | |
| combined = vocal_segment.overlay(AudioSegment.from_array(inst, frame_rate=sr)) | |
| mashup.append(combined) | |
| final_mashup = sum(mashup) | |
| output_file = "mashup.wav" | |
| final_mashup.export(output_file, format="wav") | |
| return output_file | |
| # Interface with Gradio | |
| iface = gr.Interface( | |
| fn=create_mashup, | |
| inputs=[ | |
| gr.Audio(label="Opponent Vocals", type="filepath"), | |
| gr.Audio(label="Player Vocals", type="filepath"), | |
| gr.Audio(label="Instrumental #1", type="filepath"), | |
| gr.Audio(label="Instrumental #2", type="filepath"), | |
| ], | |
| outputs=gr.Audio(label="Mashup Output"), | |
| title="FNF Mashup Maker", | |
| description="Upload FNF opponent and player vocals along with two instrumentals to generate a randomized mashup." | |
| ) | |
| iface.launch() | |