def reduce_noise_and_get_rms(input_audio, noise_file, channels=1, bits=16, rate=48000): """Reduces noise in the input audio by the given noise file and then gets the RMS values of all channels of the input audio. @param input_audio: The input audio file to be analyzed. @param noise_file: The noise file used to reduce noise in the input audio. @param channels: The number of channels in the input audio. @param bits: The number of bits of each audio sample. @param rate: The sampling rate. """ with tempfile.NamedTemporaryFile() as reduced_file: p1 = cmd_utils.popen(sox_utils.noise_profile_cmd(noise_file, '-', channels=channels, bits=bits, rate=rate), stdout=subprocess.PIPE) p2 = cmd_utils.popen(sox_utils.noise_reduce_cmd(input_audio, reduced_file.name, '-', channels=channels, bits=bits, rate=rate), stdin=p1.stdout) cmd_utils.wait_and_check_returncode(p1, p2) return get_rms(reduced_file.name, channels, bits, rate)
def get_channel_sox_stat( input_audio, channel_index, channels=2, bits=16, rate=48000): """Gets the sox stat info of the selected channel in the input audio file. @param input_audio: The input audio file to be analyzed. @param channel_index: The index of the channel to be analyzed. (1 for the first channel). @param channels: The number of channels in the input audio. @param bits: The number of bits of each audio sample. @param rate: The sampling rate. """ if channel_index <= 0 or channel_index > channels: raise ValueError('incorrect channel_indexi: %d' % channel_index) if channels == 1: return sox_utils.get_stat( input_audio, channels=channels, bits=bits, rate=rate) p1 = cmd_utils.popen( sox_utils.extract_channel_cmd( input_audio, '-', channel_index, channels=channels, bits=bits, rate=rate), stdout=subprocess.PIPE) p2 = cmd_utils.popen( sox_utils.stat_cmd('-', channels=1, bits=bits, rate=rate), stdin=p1.stdout, stderr=subprocess.PIPE) stat_output = p2.stderr.read() cmd_utils.wait_and_check_returncode(p1, p2) return sox_utils.parse_stat_output(stat_output)
def run_once(self): """Entry point of this test.""" self.chrome.browser.platform.SetHTTPServerDirectories(self.bindir) video_url = self.chrome.browser.platform.http_server.UrlOf( os.path.join(self.bindir, 'youtube.html')) logging.info('Playing back youtube media file %s.', video_url) noise_file = os.path.join(self.resultsdir, "noise.wav") recorded_file = os.path.join(self.resultsdir, "recorded.wav") loopback_file = os.path.join(self.resultsdir, "loopback.wav") # Record a sample of "silence" to use as a noise profile. cras_utils.capture(noise_file, duration=3) # Play a video and record the audio output self.play_video(self.chrome.browser.tabs[0], video_url) p1 = cmd_utils.popen( cras_utils.capture_cmd(recorded_file, duration=TEST_DURATION)) p2 = cmd_utils.popen( cras_utils.loopback_cmd(loopback_file, duration=TEST_DURATION)) cmd_utils.wait_and_check_returncode(p1, p2) # See if we recorded something loopback_stats = [ audio_helper.get_channel_sox_stat(loopback_file, i) for i in (1, 2) ] logging.info('loopback stats: %s', [str(s) for s in loopback_stats]) rms_value = audio_helper.reduce_noise_and_get_rms( recorded_file, noise_file)[0] self.write_perf_keyval({'rms_value': rms_value})
def rms_test(self, tab, media_file, noiseprof_file, test_duration): logging.info('rms test on media file %s.', media_file) recorded_file = os.path.join(self.resultsdir, 'recorded.wav') loopback_file = os.path.join(self.resultsdir, 'loopback.wav') # Plays the media_file in the browser. self.play_media(tab, media_file) # Record the audio output and also the CRAS loopback output. p1 = cmd_utils.popen( cras_utils.capture_cmd(recorded_file, duration=test_duration)) p2 = cmd_utils.popen( cras_utils.loopback_cmd(loopback_file, duration=test_duration)) cmd_utils.wait_and_check_returncode(p1, p2) # See if we recorded something. # We captured two channels of audio in the CRAS loopback. # The RMS values are for debugging only. loopback_stats = [ audio_helper.get_channel_sox_stat(loopback_file, i) for i in (1, 2) ] logging.info('loopback stats: %s', [str(s) for s in loopback_stats]) reduced_file = tempfile.NamedTemporaryFile() sox_utils.noise_reduce(recorded_file, reduced_file.name, noiseprof_file) rms = audio_helper.get_rms(reduced_file.name)[0] self._rms_values['%s_rms_value' % media_file.replace('.', '_')] = rms # Make sure the audio can be played to the end. self.wait_player_end(tab)
def get_stat(*args, **kargs): """A helper function to execute the stat_cmd. It returns the statistical information (in text) read from the standard error. """ p = cmd_utils.popen(stat_cmd(*args, **kargs), stderr=cmd_utils.PIPE) #The output is read from the stderr instead of stdout stat_output = p.stderr.read() cmd_utils.wait_and_check_returncode(p) return parse_stat_output(stat_output)
def playback(blocking=True, *args, **kargs): """A helper function to execute the playback_cmd. @param blocking: Blocks this call until playback finishes. @param args: args passed to playback_cmd. @param kargs: kargs passed to playback_cmd. @returns: The process running the playback command. Note that if the blocking parameter is true, this will return a finished process. """ process = cmd_utils.popen(playback_cmd(*args, **kargs)) if blocking: cmd_utils.wait_and_check_returncode(process) return process