Spaces:
Running
Running
File size: 6,432 Bytes
d9da484 5d53ece d9da484 5d53ece d9da484 5d53ece d9da484 5d53ece d9da484 5d53ece d9da484 7b80999 d9da484 5d53ece 6a1e9e7 5d53ece 7b80999 d9da484 7b80999 d9da484 7b80999 d9da484 7b80999 d9da484 7b80999 d9da484 5d53ece d9da484 7b80999 d9da484 5d53ece d9da484 732135c d9da484 5d53ece d9da484 0a324b7 d9da484 5d53ece d9da484 7b80999 5d53ece 7b80999 2f3270f 7b80999 2f3270f 3f05781 2f3270f 3f05781 d9da484 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
import numpy as np
import soundfile as sf
import gradio as gr
import librosa
def binauralize(audio_file, simulate_rotation, rotation_speed, auto_rotation):
"""
Simulate a binaural (stereo) effect by applying a dynamic panning effect
to an input audio file. No HRIR files are required.
If auto_rotation is enabled, AI beat detection (via librosa) is used to
determine the rotation speed based on the tempo of the audio.
Parameters:
audio_file (str): Path to input audio file (mono or stereo).
simulate_rotation (bool): If True, apply a dynamic rotation (panning) effect.
rotation_speed (float): Speed of the rotation effect (in Hz).
auto_rotation (bool): If True, auto-detect rotation speed using AI beat detection.
Returns:
output_file (str): Path to the output stereo audio file.
status (str): Status message.
"""
try:
# Load input audio file using soundfile
audio, sr = sf.read(audio_file)
except Exception as e:
return None, f"Error reading input audio file: {e}"
# If the audio is stereo, convert to mono by averaging channels
if audio.ndim > 1:
audio = np.mean(audio, axis=1)
# If auto_rotation is enabled, use librosa to detect tempo and adjust rotation speed.
if auto_rotation:
try:
# librosa expects float32 input.
audio_float = audio.astype(np.float32)
tempo, _ = librosa.beat.beat_track(y=audio_float, sr=sr)
# Cast tempo to float in case it's a NumPy array.
tempo = float(tempo)
rotation_speed = tempo / 60.0 # Convert BPM to Hz (approx.)
status_msg = f"Auto rotation enabled: Detected tempo = {tempo:.1f} BPM, setting rotation speed = {rotation_speed:.3f} Hz."
except Exception as e:
status_msg = f"Auto rotation failed, using user provided rotation speed. Error: {e}"
else:
status_msg = "Using user provided rotation speed."
# Create a time vector for the audio length
t = np.arange(len(audio)) / sr
if simulate_rotation:
# Compute a time-varying angle for a full cycle (2π) at the desired rotation speed.
angle = 2 * np.pi * rotation_speed * t
# Constant power panning: left uses cosine, right uses sine.
left = np.cos(angle) * audio
right = np.sin(angle) * audio
else:
# If rotation is not enabled, duplicate the audio to both channels.
left = audio
right = audio
# Combine the channels into a stereo signal.
binaural_audio = np.stack((left, right), axis=-1)
# Normalize to prevent clipping.
max_val = np.max(np.abs(binaural_audio))
if max_val > 0:
binaural_audio = binaural_audio / max_val
# Save the output to a WAV file.
output_file = "output_binaural.wav"
try:
sf.write(output_file, binaural_audio, sr)
except Exception as e:
return None, f"Error writing output audio file: {e}"
return output_file, f"Binaural conversion complete! {status_msg}"
# Create an enhanced UI using Gradio Blocks and Tabs.
with gr.Blocks(title="SonicOrbit", css="""
/* Custom CSS to enhance spacing and font styling */
.title { font-size: 2.5em; font-weight: bold; text-align: center; margin-bottom: 0.5em; }
.subtitle { font-size: 1.2em; text-align: center; margin-bottom: 1em; }
.footer { text-align: center; font-size: 0.9em; margin-top: 2em; color: #555; }
""") as demo:
gr.Markdown("<div class='title'>SonicOrbit</div>")
gr.Markdown("<div class='subtitle'>Binaural 360 Audio Converter with Dynamic Rotation & AI Beat Detection</div>")
with gr.Tabs():
with gr.Tab("Converter"):
with gr.Row():
input_audio = gr.Audio(type="filepath", label="Upload Audio (Mono or Stereo)")
with gr.Row():
simulate_rotation = gr.Checkbox(label="Simulate Rotation", value=True)
rotation_speed = gr.Slider(0.01, 5.0, value=0.1, step=0.01, label="Rotation Speed (Hz)")
auto_rotation = gr.Checkbox(label="Auto Detect Rotation Speed (AI)", value=False)
convert_button = gr.Button("Convert Audio")
with gr.Row():
output_audio = gr.Audio(type="filepath", label="Binaural Audio Output")
status_text = gr.Textbox(label="Status", interactive=False)
convert_button.click(
fn=binauralize,
inputs=[input_audio, simulate_rotation, rotation_speed, auto_rotation],
outputs=[output_audio, status_text]
)
with gr.Tab("Instructions"):
gr.Markdown("""
### How to Use SonicOrbit
1. **Upload Audio:**
Upload a mono or stereo audio file. If you upload a stereo file, it will be converted to mono by averaging the channels.
2. **Simulate Rotation:**
Enable this option to apply a dynamic panning effect that simulates a rotating sound source.
3. **Rotation Speed:**
Adjust the slider to set the speed of the rotation effect (in Hertz).
4. **Auto Detect Rotation Speed (AI):**
Enable this option to let SonicOrbit analyze your audio and automatically set the rotation speed based on the detected tempo.
5. **Convert Audio:**
Click the **Convert Audio** button to process your audio file. The output is a binaural (stereo) audio file with the simulated 360° effect.
Enjoy your immersive 3D audio experience!
""")
gr.Markdown("""
<div class='footer'>
© 2025 SonicOrbit. All rights reserved.
<br>
Created with ❤️ by <a href="https://bilsimaging.com" target="_blank" style="color: #88aaff;">bilsimaging.com</a>
</div>
""")
gr.HTML("""
<div style="text-align: center; margin-top: 1rem;">
<a href="https://visitorbadge.io/status?path=https%3A%2F%2Fhuggingface.co%2Fspaces%2FBils%2FSonicOrbit" target="_blank">
<img src="https://api.visitorbadge.io/api/visitors?path=https%3A%2F%2Fhuggingface.co%2Fspaces%2FBils%2FSonicOrbit&countColor=%23263759" alt="visitor badge" /></a>
</div>
""")
if __name__ == "__main__":
demo.launch()
|