Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
@@ -9,9 +9,133 @@ from tqdm import tqdm
|
|
9 |
from tqdm.std import TqdmWarning
|
10 |
from pedalboard import Reverb
|
11 |
import gradio as gr
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
|
13 |
def greet(name):
|
14 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
|
16 |
-
iface = gr.Interface(fn=greet, inputs="
|
17 |
iface.launch()
|
|
|
9 |
from tqdm.std import TqdmWarning
|
10 |
from pedalboard import Reverb
|
11 |
import gradio as gr
|
12 |
+
BUFFER_SIZE_SAMPLES = 1024 * 16
|
13 |
+
NOISE_FLOOR = 1e-4
|
14 |
+
|
15 |
+
|
16 |
+
def get_num_frames(f: sf.SoundFile) -> int:
|
17 |
+
# On some platforms and formats, f.frames == -1L.
|
18 |
+
# Check for this bug and work around it:
|
19 |
+
if f.frames > 2 ** 32:
|
20 |
+
f.seek(0)
|
21 |
+
last_position = f.tell()
|
22 |
+
while True:
|
23 |
+
# Seek through the file in chunks, returning
|
24 |
+
# if the file pointer stops advancing.
|
25 |
+
f.seek(1024 * 1024 * 1024, sf.SEEK_CUR)
|
26 |
+
new_position = f.tell()
|
27 |
+
if new_position == last_position:
|
28 |
+
f.seek(0)
|
29 |
+
return new_position
|
30 |
+
else:
|
31 |
+
last_position = new_position
|
32 |
+
else:
|
33 |
+
return f.frames
|
34 |
+
|
35 |
|
36 |
def greet(name):
|
37 |
+
warnings.filterwarnings("ignore", category=TqdmWarning)
|
38 |
+
|
39 |
+
parser = argparse.ArgumentParser(description="Add reverb to an audio file.")
|
40 |
+
parser.add_argument("input_file", help="The input file to add reverb to.",default = name)
|
41 |
+
parser.add_argument(
|
42 |
+
"--output-file",
|
43 |
+
help=(
|
44 |
+
"The name of the output file to write to. If not provided, {input_file}.reverb.wav will"
|
45 |
+
" be used."
|
46 |
+
),
|
47 |
+
default=None,
|
48 |
+
)
|
49 |
+
|
50 |
+
# Instantiate the Reverb object early so we can read its defaults for the argparser --help:
|
51 |
+
reverb = Reverb()
|
52 |
+
|
53 |
+
parser.add_argument("--room-size", type=float, default=reverb.room_size)
|
54 |
+
parser.add_argument("--damping", type=float, default=reverb.damping)
|
55 |
+
parser.add_argument("--wet-level", type=float, default=reverb.wet_level)
|
56 |
+
parser.add_argument("--dry-level", type=float, default=reverb.dry_level)
|
57 |
+
parser.add_argument("--width", type=float, default=reverb.width)
|
58 |
+
parser.add_argument("--freeze-mode", type=float, default=reverb.freeze_mode)
|
59 |
+
|
60 |
+
parser.add_argument(
|
61 |
+
"-y",
|
62 |
+
"--overwrite",
|
63 |
+
action="store_true",
|
64 |
+
help="If passed, overwrite the output file if it already exists.",
|
65 |
+
)
|
66 |
+
|
67 |
+
parser.add_argument(
|
68 |
+
"--cut-reverb-tail",
|
69 |
+
action="store_true",
|
70 |
+
help=(
|
71 |
+
"If passed, remove the reverb tail to the end of the file. "
|
72 |
+
"The output file will be identical in length to the input file."
|
73 |
+
),
|
74 |
+
)
|
75 |
+
args = parser.parse_args()
|
76 |
+
|
77 |
+
for arg in ('room_size', 'damping', 'wet_level', 'dry_level', 'width', 'freeze_mode'):
|
78 |
+
setattr(reverb, arg, getattr(args, arg))
|
79 |
+
|
80 |
+
if not args.output_file:
|
81 |
+
args.output_file = args.input_file + ".reverb.wav"
|
82 |
+
|
83 |
+
sys.stderr.write(f"Opening {args.input_file}...\n")
|
84 |
+
|
85 |
+
with sf.SoundFile(args.input_file) as input_file:
|
86 |
+
sys.stderr.write(f"Writing to {args.output_file}...\n")
|
87 |
+
if os.path.isfile(args.output_file) and not args.overwrite:
|
88 |
+
raise ValueError(
|
89 |
+
f"Output file {args.output_file} already exists! (Pass -y to overwrite.)"
|
90 |
+
)
|
91 |
+
with sf.SoundFile(
|
92 |
+
args.output_file,
|
93 |
+
'w',
|
94 |
+
samplerate=input_file.samplerate,
|
95 |
+
channels=input_file.channels,
|
96 |
+
) as output_file:
|
97 |
+
length = get_num_frames(input_file)
|
98 |
+
length_seconds = length / input_file.samplerate
|
99 |
+
sys.stderr.write(f"Adding reverb to {length_seconds:.2f} seconds of audio...\n")
|
100 |
+
with tqdm(
|
101 |
+
total=length_seconds,
|
102 |
+
desc="Adding reverb...",
|
103 |
+
bar_format=(
|
104 |
+
"{percentage:.0f}%|{bar}| {n:.2f}/{total:.2f} seconds processed"
|
105 |
+
" [{elapsed}<{remaining}, {rate:.2f}x]"
|
106 |
+
),
|
107 |
+
# Avoid a formatting error that occurs if
|
108 |
+
# TQDM tries to print before we've processed a block
|
109 |
+
delay=1000,
|
110 |
+
) as t:
|
111 |
+
for dry_chunk in input_file.blocks(BUFFER_SIZE_SAMPLES, frames=length):
|
112 |
+
# Actually call Pedalboard here:
|
113 |
+
# (reset=False is necessary to allow the reverb tail to
|
114 |
+
# continue from one chunk to the next.)
|
115 |
+
effected_chunk = reverb.process(
|
116 |
+
dry_chunk, sample_rate=input_file.samplerate, reset=False
|
117 |
+
)
|
118 |
+
# print(effected_chunk.shape, np.amax(np.abs(effected_chunk)))
|
119 |
+
output_file.write(effected_chunk)
|
120 |
+
t.update(len(dry_chunk) / input_file.samplerate)
|
121 |
+
t.refresh()
|
122 |
+
if not args.cut_reverb_tail:
|
123 |
+
while True:
|
124 |
+
# Pull audio from the effect until there's nothing left:
|
125 |
+
effected_chunk = reverb.process(
|
126 |
+
np.zeros((BUFFER_SIZE_SAMPLES, input_file.channels), np.float32),
|
127 |
+
sample_rate=input_file.samplerate,
|
128 |
+
reset=False,
|
129 |
+
)
|
130 |
+
if np.amax(np.abs(effected_chunk)) < NOISE_FLOOR:
|
131 |
+
break
|
132 |
+
output_file.write(effected_chunk)
|
133 |
+
sys.stderr.write("Done!\n")
|
134 |
+
return output_file
|
135 |
+
|
136 |
+
|
137 |
+
|
138 |
+
|
139 |
|
140 |
+
iface = gr.Interface(fn=greet, inputs=gr.Audio("audio"), outputs="text")
|
141 |
iface.launch()
|