Skip to content

Commit 51e15c0

Browse files
authored
Merge pull request #22 from amiaopensource/phase
Add normalization for phase scope
2 parents aea2b36 + 1afd091 commit 51e15c0

File tree

1 file changed

+65
-17
lines changed

1 file changed

+65
-17
lines changed

audioqc

Lines changed: 65 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -186,11 +186,47 @@ class QcTarget
186186
end
187187
end
188188

189-
def find_peaks_loudness_n_phase
190-
high_db_frames = []
189+
def get_ffprobe_phase_normalized(volume_command)
190+
ffprobe_command = 'ffmpeg -i ' + @input_path + volume_command + ' -f wav - | ffprobe -print_format json -threads auto -show_entries frame_tags=lavfi.aphasemeter.phase -f lavfi -i "amovie=' + "'" + 'pipe\\:0' + "'" + ',astats=reset=1:metadata=1,aphasemeter=video=0,ebur128=metadata=1"'
191+
@ffprobe_phase = JSON.parse(`#{ffprobe_command}`)
192+
end
193+
194+
def get_ffprobe
195+
if @channel_count == "2"
196+
channel_one_vol = []
197+
channel_two_vol = []
198+
ffprobe_command = 'ffprobe -print_format json -threads auto -show_entries frame_tags=lavfi.astats.Overall.Number_of_samples,lavfi.astats.Overall.Peak_level,lavfi.astats.Overall.Max_difference,lavfi.astats.1.Peak_level,lavfi.astats.2.Peak_level,lavfi.astats.1.Peak_level,lavfi.astats.Overall.Mean_difference,lavfi.astats.Overall.Peak_level,lavfi.r128.I -f lavfi -i "amovie=' + "\\'" + @input_path + "\\'" + ',astats=reset=1:metadata=1,ebur128=metadata=1"'
199+
@ffprobe_out = JSON.parse(`#{ffprobe_command}`)
200+
@ffprobe_out['frames'].each do |frame|
201+
if frame['tags']['lavfi.astats.1.Peak_level'] == '-inf' || frame['tags']['lavfi.astats.2.Peak_level'] == 'inf'
202+
next
203+
else
204+
channel_one_vol << frame['tags']['lavfi.astats.1.Peak_level'].to_f
205+
channel_two_vol << frame['tags']['lavfi.astats.2.Peak_level'].to_f
206+
end
207+
@channel_one_max = channel_one_vol.max
208+
@channel_two_max = channel_two_vol.max
209+
channel_dif = (channel_one_vol.max - channel_two_vol.max).abs.to_s
210+
if channel_two_vol.max < channel_one_vol.max
211+
@volume_command = ' -filter_complex "[0:a]channelsplit[a][b],[b]volume=volume=' + channel_dif + 'dB:precision=fixed[c],[a][c]amerge[out1]" -map [out1] '
212+
else
213+
@volume_command = ' -filter_complex "[0:a]channelsplit[a][b],[a]volume=volume=' + channel_dif + 'dB:precision=fixed[c],[c][b]amerge[out1]" -map [out1] '
214+
end
215+
end
216+
get_ffprobe_phase_normalized(@volume_command)
217+
else
218+
ffprobe_command = 'ffprobe -print_format json -threads auto -show_entries frame_tags=lavfi.astats.Overall.Number_of_samples,lavfi.astats.Overall.Peak_level,lavfi.astats.Overall.Max_difference,lavfi.astats.1.Peak_level,lavfi.astats.Overall.Mean_difference,lavfi.astats.Overall.Peak_level,lavfi.aphasemeter.phase,lavfi.r128.I -f lavfi -i "amovie=' + "\\'" + @input_path + "\\'" + ',astats=reset=1:metadata=1,aphasemeter=video=0,ebur128=metadata=1"'
219+
@ffprobe_out = JSON.parse(`#{ffprobe_command}`)
220+
@ffprobe_phase = @ffprobe_out
221+
end
222+
@total_frame_count = @ffprobe_out['frames'].size
223+
# change this to find peak volume for each channel and calculate difference
224+
# volume_ratio = peak1 / peak 2
225+
end
226+
227+
def check_phase
191228
out_of_phase_frames = []
192229
phase_frames = []
193-
@levels = []
194230
unless @mediainfo_out['media']['track'][0]['extra'].nil? || TARGET_EXTENSION != 'wav'
195231
if @mediainfo_out['media']['track'][0]['extra']['bext_Present'] == 'Yes' && @mediainfo_out['media']['track'][0]['Encoded_Library_Settings']
196232
@stereo_count = @mediainfo_out['media']['track'][0]['Encoded_Library_Settings'].scan(/stereo/i).count
@@ -208,35 +244,40 @@ class QcTarget
208244
else
209245
phase_limit = Configurations['generic_audio_phase_limit']
210246
end
211-
@ffprobe_out['frames'].each do |frames|
212-
peaklevel = frames['tags']['lavfi.astats.Overall.Peak_level']
247+
@ffprobe_phase['frames'].each do |frames|
213248
audiophase = frames['tags']['lavfi.aphasemeter.phase'].to_f
214249
phase_frames << audiophase
215250
out_of_phase_frames << audiophase if audiophase < phase_limit
251+
end
252+
@phasey_frame_count = out_of_phase_frames.size
253+
if Ruby_Version > 2.7
254+
@average_phase = (phase_frames.sum(0.0) / phase_frames.size).round(2)
255+
else
256+
@average_phase = (phase_frames.reduce(:+) / phase_frames.size).round(2)
257+
end
258+
@warnings << 'PHASE WARNING' if @phasey_frame_count > 50
259+
end
260+
261+
def find_peaks_loudness_n_phase
262+
high_db_frames = []
263+
@levels = []
264+
@ffprobe_out['frames'].each do |frames|
265+
peaklevel = frames['tags']['lavfi.astats.Overall.Peak_level']
216266
if peaklevel != '-inf'
217267
high_db_frames << peaklevel.to_f if peaklevel.to_f > Configurations['high_level_warning']
218268
@levels << peaklevel.to_f
219269
end
220270
end
271+
221272
@max_level = @levels.max.round(2)
222273
@high_level_count = high_db_frames.size
223-
@phasey_frame_count = out_of_phase_frames.size
224274
if Ruby_Version > 2.7
225275
@average_levels = (@levels.sum(0.0) / @levels.size).round(2)
226-
@average_phase = (phase_frames.sum(0.0) / phase_frames.size).round(2)
227276
else
228277
@average_levels = (@levels.reduce(:+) / @levels.size).round(2)
229-
@average_phase = (phase_frames.reduce(:+) / phase_frames.size).round(2)
230278
end
231279
@integratedLoudness = @ffprobe_out['frames'][@ffprobe_out.length - 3]['tags']['lavfi.r128.I']
232280
@warnings << 'LEVEL WARNING' if @high_level_count > 0
233-
@warnings << 'PHASE WARNING' if @phasey_frame_count > 50
234-
end
235-
236-
def get_ffprobe
237-
ffprobe_command = 'ffprobe -print_format json -threads auto -show_entries frame_tags=lavfi.astats.Overall.Number_of_samples,lavfi.astats.Overall.Peak_level,lavfi.astats.Overall.Max_difference,lavfi.astats.Overall.Mean_difference,lavfi.astats.Overall.Peak_level,lavfi.aphasemeter.phase,lavfi.r128.I -f lavfi -i "amovie=' + "\\'" + @input_path + "\\'" + ',astats=reset=1:metadata=1,aphasemeter=video=0,ebur128=metadata=1"'
238-
@ffprobe_out = JSON.parse(`#{ffprobe_command}`)
239-
@total_frame_count = @ffprobe_out['frames'].size
240281
end
241282

242283
def get_mediainfo
@@ -281,7 +322,13 @@ class QcTarget
281322
line << @possible_drops
282323
end
283324
if options.include?('signal')
284-
line += [@average_levels, @max_level, @high_level_count, @average_phase, @phasey_frame_count, @integratedLoudness]
325+
line += [@average_levels, @max_level,@high_level_count]
326+
if @channel_count == "2"
327+
line+= [@channel_one_max,@channel_two_max]
328+
else
329+
line += [' ', ' ']
330+
end
331+
line +=[@average_phase, @phasey_frame_count, @integratedLoudness]
285332
end
286333
if options.include?('meta')
287334
line += [@wave_conformance] unless TARGET_EXTENSION != 'wav'
@@ -363,7 +410,7 @@ CSV.open(output_csv, 'wb') do |csv|
363410
end
364411

365412
if options.include?('signal')
366-
headers += ['Average Level', 'Peak Level', 'Number of Frames w/ High Levels', 'Average Phase', 'Number of Phase Warnings', 'Integrated Loudness']
413+
headers += ['Average Level', 'Peak Level', 'Number of Frames w/ High Levels', 'Channel 1 Max', 'Channel 2 Max', 'Average Phase', 'Number of Phase Warnings', 'Integrated Loudness']
367414
end
368415

369416
if options.include?('meta')
@@ -399,6 +446,7 @@ file_inputs.each do |fileinput|
399446
target.get_ffprobe
400447
if options.include?('signal')
401448
target.find_peaks_loudness_n_phase
449+
target.check_phase
402450
end
403451
if options.include?('dropouts')
404452
target.check_dropouts

0 commit comments

Comments
 (0)