File size: 4,921 Bytes
d9da484
 
 
5d53ece
d9da484
5d53ece
3736599
d9da484
3736599
d9da484
 
 
 
 
 
 
5d53ece
 
3736599
5d53ece
 
3736599
6a1e9e7
3736599
5d53ece
 
 
 
 
 
3736599
d9da484
 
 
3736599
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
import numpy as np
import soundfile as sf
import gradio as gr
import librosa

def binauralize(audio_file, simulate_rotation, rotation_speed, auto_rotation):
   
    try:
        
        audio, sr = sf.read(audio_file)
    except Exception as e:
        return None, f"Error reading input audio file: {e}"
    
    if audio.ndim > 1:
        audio = np.mean(audio, axis=1)
    
    if auto_rotation:
        try:
           
            audio_float = audio.astype(np.float32)
            tempo, _ = librosa.beat.beat_track(y=audio_float, sr=sr)
           
            tempo = float(tempo)
            rotation_speed = tempo / 60.0 
            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."
    
    
    t = np.arange(len(audio)) / sr
    
    if simulate_rotation:
        
        angle = 2 * np.pi * rotation_speed * t
        left = np.cos(angle) * audio
        right = np.sin(angle) * audio
    else:
        left = audio
        right = audio
    
    binaural_audio = np.stack((left, right), axis=-1)
    
    max_val = np.max(np.abs(binaural_audio))
    if max_val > 0:
        binaural_audio = binaural_audio / max_val
    
    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}"

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()