nakas commited on
Commit
f283239
1 Parent(s): b12a7fc

Delete add_reverb_to_file.py

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