Skip to content

Commit e4757be

Browse files
committed
a few little improvements
1 parent 1d2a83e commit e4757be

File tree

3 files changed

+48
-15
lines changed

3 files changed

+48
-15
lines changed

audio_io/audio_io.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,9 @@ def get(*keys, default_value=None):
287287

288288

289289
def read_audio_file_metadata(in_path) -> AudioFileMetadata:
290+
if not path.exists(in_path):
291+
raise ValueError(f'Path "{in_path}" doesn''t exist')
292+
290293
p = sp.Popen(
291294
(ex_ffprobe,
292295
'-v', 'error',
@@ -320,7 +323,7 @@ def seconds_to_samples(seconds: Number):
320323
return int(sample_rate * seconds)
321324

322325
# noinspection PyTypeChecker
323-
p = sp.Popen((ex_ffmpeg,) + ffmpeg_args, stderr=None, stdout=PIPE)
326+
p = sp.Popen([ex_ffmpeg] + ffmpeg_args, stderr=None, stdout=PIPE)
324327

325328
sample_type = np.dtype(numpy_sample_type)
326329
frombuffer = np.frombuffer

audio_metrics/audio_metrics.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@ def decibel(a):
3838
return np.log10(a) * 20
3939

4040

41-
def compute_dr(pool, a: AudioSourceInfo, samples: Iterator[np.ndarray], keep_precision: bool) -> DynamicRangeMetrics:
41+
def compute_dr(pool, a: AudioSourceInfo, samples: Iterator[np.ndarray],
42+
keep_precision: bool,
43+
) -> DynamicRangeMetrics:
4244
channel_count = a.channel_count
4345

4446
sample_count = [0]

main.py

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ def parse_args():
9595
ap.add_argument("--no-log", help='Do not write log (dr.txt), by default a log file is written after analysis',
9696
action='store_true')
9797
ap.add_argument("--keep-precision", help='Do not round values, this also disables log', action='store_true')
98+
ap.add_argument("--no-resample", help='Do not resample everything to 44.1kHz (unlike the "standard" meter), '
99+
'this also disables log',
100+
action='store_true')
98101
args = sys.argv[1:]
99102
if args:
100103
return ap.parse_args(args)
@@ -111,8 +114,12 @@ def main():
111114
input_path = os.path.expanduser(args.input)
112115
input_path = os.path.abspath(input_path)
113116

114-
should_write_log = not args.no_log and not args.keep_precision
117+
should_write_log = \
118+
not args.no_log \
119+
and not args.keep_precision \
120+
and not args.no_resample
115121
keep_precision = args.keep_precision
122+
no_resample = args.no_resample
116123

117124
if should_write_log:
118125
log_path = get_log_path(input_path)
@@ -125,7 +132,9 @@ def track_cb(track_info: TrackInfo, dr):
125132
print(f"{track_info.global_index:02d} - {title}: {dr_formatted}")
126133

127134
time_start = time.time()
128-
dr_log_items, dr_mean, dr_median = analyze_dr(input_path, track_cb, keep_precision)
135+
dr_log_items, dr_mean, dr_median = analyze_dr(
136+
input_path, track_cb, keep_precision, no_resample,
137+
)
129138
print(f'Official DR = {dr_mean}, Median DR = {dr_median}')
130139
print(f'Analyzed all tracks in {time.time() - time_start:.2f} seconds')
131140

@@ -141,7 +150,7 @@ def track_cb(track_info: TrackInfo, dr):
141150

142151

143152
def fix_tty():
144-
"""I don't know why this is needed, but it is. Otherwise the terminal may cease to
153+
"""I don't know why this is needed, but it is. Otherwise, the terminal may cease to
145154
accept any keyboard input after this application finishes. Hopefully I will find
146155
something better eventually."""
147156
platform = sys.platform.lower()
@@ -150,7 +159,12 @@ def fix_tty():
150159
os.system('stty sane')
151160

152161

153-
def analyze_dr(in_path: str, track_cb, keep_precision: bool):
162+
def analyze_dr(
163+
in_path: str,
164+
track_cb,
165+
keep_precision: bool,
166+
no_resample: bool,
167+
):
154168
audio_info = tuple(read_audio_info(in_path))
155169
num_files = len(audio_info)
156170
assert num_files > 0
@@ -177,22 +191,37 @@ def analyze_part_tracks(audio_data: AudioData, audio_info_part: AudioSourceInfo,
177191
yield track_info, dr_metrics
178192

179193
def analyze_part(map_impl, audio_info_part: AudioSourceInfo):
180-
ffmpeg_args = (
194+
ffmpeg_args = []
195+
ffmpeg_args += [
181196
'-loglevel', 'fatal',
182197
'-i', audio_info_part.file_path,
183198
'-map', '0:a:0',
184199
'-c:a', 'pcm_f32le',
185-
'-ar', str(MEASURE_SAMPLE_RATE),
186-
# ^ because apparently official meter resamples to 44k before measuring;
187-
# using default low quality resampling because it doesn't affect measurements and is faster
200+
]
201+
202+
if not no_resample:
203+
ffmpeg_args += [
204+
'-ar', str(MEASURE_SAMPLE_RATE),
205+
# ^ because apparently official meter resamples to 44k before measuring;
206+
# using default low quality resampling because it doesn't affect measurements and is faster
207+
]
208+
209+
ffmpeg_args += [
188210
'-f', 'f32le',
189-
'-')
211+
'-',
212+
]
213+
214+
if no_resample:
215+
sample_rate = audio_info_part.sample_rate
216+
else:
217+
sample_rate = MEASURE_SAMPLE_RATE
218+
190219
audio_data = read_audio_data(audio_info_part,
191-
samples_per_block=3 * MEASURE_SAMPLE_RATE,
220+
samples_per_block=3 * sample_rate,
192221
ffmpeg_args=ffmpeg_args,
193222
bytes_per_sample_mono=4,
194223
numpy_sample_type='<f4',
195-
sample_rate=MEASURE_SAMPLE_RATE)
224+
sample_rate=sample_rate)
196225
return audio_info_part, analyze_part_tracks(audio_data, audio_info_part, map_impl)
197226

198227
dr_items = []
@@ -232,8 +261,7 @@ def process_part(map_impl, audio_info_part: AudioSourceInfo):
232261
dr_mean_rounded = int(numpy.round(numpy.mean(dr_items))) # official
233262
dr_median = numpy.median(dr_items)
234263

235-
dr_log_items = make_log_groups(dr_log_items)
236-
return dr_log_items, dr_mean_rounded, dr_median
264+
return make_log_groups(dr_log_items), dr_mean_rounded, dr_median
237265

238266

239267
if __name__ == '__main__':

0 commit comments

Comments
 (0)