tee342 commited on
Commit
664f177
·
verified ·
1 Parent(s): d9349e6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +20 -224
app.py CHANGED
@@ -2,230 +2,26 @@ import gradio as gr
2
  from pydub import AudioSegment
3
  import numpy as np
4
  import tempfile
5
- import os
6
- import noisereduce as nr
7
- import torch
8
- from demucs import pretrained
9
- from demucs.apply import apply_model
10
- import torchaudio
11
- from pathlib import Path
12
- import matplotlib.pyplot as plt
13
- from io import BytesIO
14
- from PIL import Image
15
- import zipfile
16
- import datetime
17
- import librosa
18
- import warnings
19
- import json
20
- import pickle
21
  import soundfile as sf
22
 
23
- warnings.filterwarnings("ignore")
24
-
25
- ### Helper Functions ###
26
-
27
- def audiosegment_to_array(audio):
28
- return np.array(audio.get_array_of_samples()), audio.frame_rate
29
-
30
- def array_to_audiosegment(samples, frame_rate, channels=1):
31
- return AudioSegment(
32
- samples.tobytes(),
33
- frame_rate=int(frame_rate),
34
- sample_width=samples.dtype.itemsize,
35
- channels=channels
36
- )
37
-
38
- def save_audiosegment_to_temp(audio: AudioSegment, suffix=".wav"):
39
- with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as f:
40
- audio.export(f.name, format=suffix.lstrip('.'))
41
- return f.name
42
-
43
- def load_audiofile_to_numpy(path):
44
- samples, sr = sf.read(path, dtype="int16")
45
- if samples.ndim > 1 and samples.shape[1] > 2:
46
- samples = samples[:, :2]
47
- return samples, sr
48
-
49
- def show_waveform(audio_file):
50
- try:
51
- audio = AudioSegment.from_file(audio_file)
52
- samples = np.array(audio.get_array_of_samples())
53
- plt.figure(figsize=(10,2))
54
- plt.plot(samples[:10000], color="skyblue")
55
- plt.axis('off')
56
- buf = BytesIO()
57
- plt.savefig(buf, format='png', bbox_inches='tight')
58
- plt.close()
59
- buf.seek(0)
60
- return Image.open(buf)
61
- except Exception:
62
  return None
63
-
64
- ### Effects ###
65
-
66
- def apply_normalize(audio): return audio.normalize()
67
-
68
- def apply_noise_reduction(audio):
69
- samples, sr = audiosegment_to_array(audio)
70
- reduced = nr.reduce_noise(y=samples, sr=sr)
71
- return array_to_audiosegment(reduced, sr, audio.channels)
72
-
73
- def apply_compression(audio): return audio.compress_dynamic_range()
74
-
75
- def apply_reverb(audio):
76
- reverb = audio - 10
77
- return audio.overlay(reverb, position=1000)
78
-
79
- def apply_pitch_shift(audio, semitones=-2):
80
- new_fr = int(audio.frame_rate * (2 ** (semitones / 12)))
81
- return audio._spawn(audio.raw_data, overrides={"frame_rate": new_fr}).set_frame_rate(audio.frame_rate)
82
-
83
- def apply_echo(audio, delay_ms=500, decay=0.5):
84
- echo = audio - 10
85
- return audio.overlay(echo, position=delay_ms)
86
-
87
- def apply_stereo_widen(audio, pan_amount=0.3):
88
- left = audio.pan(-pan_amount)
89
- right = audio.pan(pan_amount)
90
- return AudioSegment.from_mono_audiosegments(left, right)
91
-
92
- def apply_bass_boost(audio, gain=10): return audio.low_pass_filter(100).apply_gain(gain)
93
-
94
- def apply_treble_boost(audio, gain=10): return audio.high_pass_filter(4000).apply_gain(gain)
95
-
96
- def apply_limiter(audio, limit_dB=-1):
97
- limiter = audio._spawn(audio.raw_data, overrides={"frame_rate": audio.frame_rate})
98
- return limiter.apply_gain(limit_dB)
99
-
100
- def apply_auto_gain(audio, target_dB=-20):
101
- change = target_dB - audio.dBFS
102
- return audio.apply_gain(change)
103
-
104
- def apply_vocal_distortion(audio, intensity=0.3):
105
- samples = np.array(audio.get_array_of_samples()).astype(np.float32)
106
- distorted = samples + intensity * np.sin(samples * 2 * np.pi / 32768)
107
- return array_to_audiosegment(distorted.astype(np.int16), audio.frame_rate, audio.channels)
108
-
109
- def apply_harmony(audio, shift_semitones=4):
110
- shifted_up = apply_pitch_shift(audio, shift_semitones)
111
- shifted_down = apply_pitch_shift(audio, -shift_semitones)
112
- return audio.overlay(shifted_up).overlay(shifted_down)
113
-
114
- def apply_stage_mode(audio):
115
- processed = apply_reverb(audio)
116
- processed = apply_bass_boost(processed, gain=6)
117
- return apply_limiter(processed, limit_dB=-2)
118
-
119
- def apply_bitcrush(audio, bit_depth=8):
120
- samples = np.array(audio.get_array_of_samples())
121
- max_value = 2 ** bit_depth - 1
122
- downsampled = np.round(samples / (32768 / max_value)).astype(np.int16)
123
- return array_to_audiosegment(downsampled, audio.frame_rate // 2, audio.channels)
124
-
125
- ### Presets ###
126
-
127
- preset_choices = {
128
- "Default": [],
129
- "Clean Podcast": ["Noise Reduction", "Normalize"],
130
- "Podcast Mastered": ["Noise Reduction", "Normalize", "Compress Dynamic Range"],
131
- "Radio Ready": ["Bass Boost", "Treble Boost", "Limiter"],
132
- "Music Production": ["Reverb", "Stereo Widening", "Pitch Shift"],
133
- "ASMR Creator": ["Noise Gate", "Auto Gain", "Low-Pass Filter"],
134
- "Voiceover Pro": ["Vocal Isolation", "TTS", "EQ Match"],
135
- "8-bit Retro": ["Bitcrusher", "Echo", "Mono Downmix"],
136
- "🎙 Clean Vocal": ["Noise Reduction", "Normalize", "High Pass Filter (80Hz)"],
137
- "🧪 Vocal Distortion": ["Vocal Distortion", "Reverb", "Compress Dynamic Range"],
138
- "🎶 Singer's Harmony": ["Harmony", "Stereo Widening", "Pitch Shift"],
139
- "🌫 ASMR Vocal": ["Auto Gain", "Low-Pass Filter (3000Hz)", "Noise Gate"],
140
- "🎼 Stage Mode": ["Reverb", "Bass Boost", "Limiter"],
141
- }
142
-
143
- preset_names = list(preset_choices.keys())
144
-
145
- ### Main processing ###
146
-
147
- def process_audio(audio_file, selected_effects, isolate_vocals, preset_name, export_format):
148
- try:
149
- audio = AudioSegment.from_file(audio_file)
150
- effect_map = {
151
- "Noise Reduction": apply_noise_reduction,
152
- "Compress Dynamic Range": apply_compression,
153
- "Add Reverb": apply_reverb,
154
- "Pitch Shift": apply_pitch_shift,
155
- "Echo": apply_echo,
156
- "Stereo Widening": apply_stereo_widen,
157
- "Bass Boost": apply_bass_boost,
158
- "Treble Boost": apply_treble_boost,
159
- "Normalize": apply_normalize,
160
- "Limiter": lambda x: apply_limiter(x, limit_dB=-1),
161
- "Auto Gain": lambda x: apply_auto_gain(x, target_dB=-20),
162
- "Vocal Distortion": apply_vocal_distortion,
163
- "Stage Mode": apply_stage_mode,
164
- "Harmony": apply_harmony,
165
- "Bitcrusher": apply_bitcrush,
166
- }
167
- for effect in selected_effects:
168
- if effect in effect_map:
169
- audio = effect_map[effect](audio)
170
- if isolate_vocals:
171
- temp_path = save_audiosegment_to_temp(audio, suffix=".wav")
172
- vocal_path = apply_vocal_isolation(temp_path)
173
- audio = AudioSegment.from_file(vocal_path)
174
- output_path = save_audiosegment_to_temp(audio, suffix='.' + export_format.lower())
175
- samples, sr = load_audiofile_to_numpy(output_path)
176
- waveform = show_waveform(output_path)
177
- session_log = json.dumps({
178
- "timestamp": str(datetime.datetime.now()),
179
- "filename": os.path.basename(audio_file),
180
- "effects_applied": selected_effects,
181
- "isolate_vocals": isolate_vocals,
182
- "export_format": export_format,
183
- "detected_genre": "Unknown"
184
- }, indent=2)
185
- return (samples, sr), waveform, session_log, "Unknown", "🎉 Done!"
186
- except Exception as e:
187
- return None, None, f"Error: {e}", "", f"Error: {e}"
188
-
189
- ### Other necessary functions (batch, AI remaster...) would follow similar patterns.
190
-
191
- # ===================================================
192
- # Now, the Gradio UI:
193
- # Paste this after all function definitions above
194
- # ===================================================
195
-
196
- with gr.Blocks() as demo:
197
- gr.HTML('<h3 style="text-align:center;">Where Your Audio Meets Intelligence</h3>')
198
- gr.Markdown('### Upload, edit, export — powered by AI!')
199
-
200
- with gr.Tab("🎵 Single File Studio"):
201
- with gr.Row():
202
- with gr.Column():
203
- input_audio = gr.Audio(label="Upload Audio", type="filepath")
204
- effect_checkbox = gr.CheckboxGroup(choices=list({e for effects in preset_choices.values() for e in effects}), label="Apply Effects in Order")
205
- preset_dropdown = gr.Dropdown(choices=preset_names, label="Select Preset")
206
- export_format = gr.Dropdown(choices=["WAV", "MP3"], label="Export Format", value="WAV")
207
- isolate_vocals = gr.Checkbox(label="Isolate Vocals After Effects")
208
- process_btn = gr.Button("Process Audio")
209
-
210
- with gr.Column():
211
- processed_audio = gr.Audio(label="Processed Audio", type="numpy")
212
- waveform_image = gr.Image(label="Waveform Preview")
213
- session_log = gr.Textbox(label="Session Log", lines=6)
214
- detected_genre = gr.Textbox(label="Detected Genre")
215
- status = gr.Textbox(label="Status", lines=1, value="Ready")
216
-
217
- def update_effects(preset):
218
- return preset_choices.get(preset, [])
219
-
220
- preset_dropdown.change(update_effects, inputs=preset_dropdown, outputs=effect_checkbox)
221
-
222
- def run_processing(audio, effects, isolate, preset, fmt):
223
- effs = preset_choices.get(preset, []) if preset in preset_choices else effects
224
- return process_audio(audio, effs, isolate, preset, fmt)
225
-
226
- process_btn.click(run_processing,
227
- inputs=[input_audio, effect_checkbox, isolate_vocals, preset_dropdown, export_format],
228
- outputs=[processed_audio, waveform_image, session_log, detected_genre, status]
229
- )
230
-
231
- demo.launch()
 
2
  from pydub import AudioSegment
3
  import numpy as np
4
  import tempfile
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  import soundfile as sf
6
 
7
+ # Normalize audio using pydub
8
+ def normalize_audio(file):
9
+ if file is None:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  return None
11
+ audio = AudioSegment.from_file(file)
12
+ normalized_audio = audio.normalize()
13
+ temp_path = tempfile.NamedTemporaryFile(suffix=".wav", delete=False).name
14
+ normalized_audio.export(temp_path, format="wav")
15
+ samples, sample_rate = sf.read(temp_path)
16
+ return samples, sample_rate
17
+
18
+ app = gr.Interface(
19
+ fn=normalize_audio,
20
+ inputs=gr.Audio(source="upload", type="filepath"),
21
+ outputs=gr.Audio(type="numpy"),
22
+ title="Normalize Audio Test",
23
+ description="Upload an audio file to normalize it and get the processed audio back."
24
+ )
25
+
26
+ if __name__ == "__main__":
27
+ app.launch()