def _prepare_impl(self, use_file, sample_width, sample_rate, num_channels, frequency): """Prepare for audio recording (interface override). @param use_file: If a file was used to produce audio. This is necessary if audio of a particular frequency is being produced. @param sample_width: The recorded sample width. @param sample_rate: The recorded sample rate. @param num_channels: The number of recorded channels. @param frequency: Frequency of audio being produced. """ req = sequenced_request.SequencedFeedbackRequest( self.test, self.dut, 'Audio recording') # TODO(ralphnathan) Lift the restriction regarding recording time once # the test allows recording for arbitrary periods of time (b/26924426). req.append_question( 'Device %(dut)s will start recording audio for 10 seconds. ' 'Please prepare for producing sound and hit Enter to ' 'continue...', input_handlers.PauseInputHandler()) self._process_request(req) self._sample_width = sample_width self._sample_rate = sample_rate self._num_channels = num_channels if use_file: self._frequency = frequency else: self._frequency = None
def _validate_impl(self, audio_file=None): """Validate playback (interface override). @param audio_file: Name of audio file on the test host to validate against. """ req = sequenced_request.SequencedFeedbackRequest( self.test, self.dut, None) msg = 'Playback finished on %(dut)s.' if audio_file is None: req.append_question(msg, input_handlers.YesNoInputHandler(default=True), prompt='Did you hear audible sound?') err_msg = 'User did not hear audible feedback' else: if not self._playback_wav_file(msg, audio_file): return (tester_feedback_client.QUERY_RET_ERROR, 'Failed to playback recorded audio') req.append_question( None, input_handlers.YesNoInputHandler(default=True), prompt=('Was the audio produced identical to the refernce ' 'audio file?')) err_msg = ('Audio produced was not identical to the reference ' 'audio file') if not self._process_request(req): return (tester_feedback_client.QUERY_RET_FAIL, err_msg)
def _playback_wav_file(self, msg, audio_file): """Plays a WAV file via user selected method. Looks for available playback commands and presents them to the user to choose from. Also lists "manual playback" as the last option. @param msg: Introductory message to present to the user. @param audio_file: The audio file to play. @return: Whether playback was successful. """ choices = [] cmds = [] for tool, cmd in _KNOWN_WAV_PLAYBACK_METHODS: if site_utils.which(tool): choices.append(tool) cmds.append(cmd) choices.append('Manual playback') msg += (' The audio file is %s. Available playback methods include:' % audio_file) req = sequenced_request.SequencedFeedbackRequest( self.test, self.dut, None) req.append_question(msg, input_handlers.MultipleChoiceInputHandler( choices, default=1), prompt='Choose your playback method') idx, _ = self._process_request(req) if idx < len(choices) - 1: cmd = [tok % {'file': audio_file} for tok in cmds[idx]] return subprocess.call(cmd) == 0 return True
def _emit_impl(self): """Emit sound for recording (interface override).""" req = sequenced_request.SequencedFeedbackRequest( self.test, self.dut, None) req.append_question( 'Device %(dut)s is recording audio, hit Enter when done ' 'producing sound...', input_handlers.PauseInputHandler()) self._process_request(req)
def _prepare_impl(self, **kwargs): """Prepare for audio playback (interface override).""" req = sequenced_request.SequencedFeedbackRequest( self.test, self.dut, 'Audible playback') req.append_question( 'Device %(dut)s will play a short audible sample. Please ' 'prepare for listening to this playback and hit Enter to ' 'continue...', input_handlers.PauseInputHandler()) self._process_request(req)
def _prepare_impl(self): """Prepare for silent playback (interface override).""" req = sequenced_request.SequencedFeedbackRequest( self.test, self.dut, 'Silent playback') req.append_question( 'Device %(dut)s will play nothing for a short time. Please ' 'prepare for listening to this silence and hit Enter to ' 'continue...', input_handlers.PauseInputHandler()) self._process_request(req)
def _prepare_impl(self): """Prepare for audio recording (interface override).""" req = sequenced_request.SequencedFeedbackRequest( self.test, self.dut, 'Audio recording') # TODO(ralphnathan) Lift the restriction regarding recording time once # the test allows recording for arbitrary periods of time (b/26924426). req.append_question( 'Device %(dut)s will start recording audio for 10 seconds. ' 'Please prepare for producing sound and hit Enter to ' 'continue...', input_handlers.PauseInputHandler()) self._process_request(req)
def _validate_impl(self, captured_audio_file, sample_width, sample_rate=None, num_channels=None, peak_percent_min=1, peak_percent_max=100): """Validate recording (interface override). @param captured_audio_file: Path to the recorded WAV file. @param sample_width: The recorded sample width. @param sample_rate: The recorded sample rate. @param num_channels: The number of recorded channels. @peak_percent_min: Lower bound on peak recorded volume as percentage of max molume (0-100). Default is 1%. @peak_percent_max: Upper bound on peak recorded volume as percentage of max molume (0-100). Default is 100% (no limit). """ # Check the WAV file properties first. try: site_utils.check_wav_file(captured_audio_file, num_channels=num_channels, sample_rate=sample_rate, sample_width=sample_width) except ValueError as e: return (tester_feedback_client.QUERY_RET_FAIL, 'Recorded audio file is invalid: %s' % e) # Verify playback of the recorded audio. props = ['has sample width of %d' % sample_width] if sample_rate is not None: props.append('has sample rate of %d' % sample_rate) if num_channels is not None: props.append('has %d recorded channels' % num_channels) props_str = '%s%s%s' % (', '.join( props[:-1]), ', and ' if len(props) > 1 else '', props[-1]) msg = 'Recording finished on %%(dut)s. It %s.' % props_str if not self._playback_wav_file(msg, captured_audio_file): return (tester_feedback_client.QUERY_RET_ERROR, 'Failed to playback recorded audio') req = sequenced_request.SequencedFeedbackRequest( self.test, self.dut, None) req.append_question( None, input_handlers.YesNoInputHandler(default=True), prompt='Did the recording capture the sound produced?') if not self._process_request(req): return ( tester_feedback_client.QUERY_RET_FAIL, 'Recorded audio is not identical to what the user produced')
def _validate_impl(self, audio_file=None): """Validate silence (interface override). @param audio_file: Name of audio file on the test host to validate against. """ if audio_file is not None: return ( tester_feedback_client.QUERY_RET_ERROR, 'Not expecting an audio file entry when validating silence') req = sequenced_request.SequencedFeedbackRequest( self.test, self.dut, None) req.append_question('Silence playback finished on %(dut)s.', input_handlers.YesNoInputHandler(default=True), prompt='Did you hear silence?') if not self._process_request(req): return (tester_feedback_client.QUERY_RET_FAIL, 'User did not hear silence')
def _validate_impl(self, captured_audio_file): """Validate recording (interface override). @param captured_audio_file: Path to the recorded WAV file. """ # Check the WAV file properties first. try: audio_utils.check_wav_file(captured_audio_file, num_channels=self._num_channels, sample_rate=self._sample_rate, sample_width=self._sample_width) except ValueError as e: return (tester_feedback_client.QUERY_RET_FAIL, 'Recorded audio file is invalid: %s' % e) # Verify playback of the recorded audio. props = [ 'as sample width of %d' % self._sample_width, 'has sample rate of %d' % self._sample_rate, 'has %d recorded channels' % self._num_channels ] if self._frequency is not None: props.append('has frequency of %d Hz' % self._frequency) props_str = '%s%s%s' % (', '.join( props[:-1]), ', and ' if len(props) > 1 else '', props[-1]) msg = 'Recording finished on %%(dut)s. It %s.' % props_str if not self._playback_wav_file(msg, captured_audio_file): return (tester_feedback_client.QUERY_RET_ERROR, 'Failed to playback recorded audio') req = sequenced_request.SequencedFeedbackRequest( self.test, self.dut, None) req.append_question( None, input_handlers.YesNoInputHandler(default=True), prompt='Did the recording capture the sound produced?') if not self._process_request(req): return ( tester_feedback_client.QUERY_RET_FAIL, 'Recorded audio is not identical to what the user produced')
def _handle_requests(self, stdin): """Processes feedback requests until termination is signaled. This method is run in a separate process and needs to override stdin in order for raw_input() to work. """ sys.stdin = stdin try: while True: req_idx = None # Wait for a (suitable) request to become available. while True: if self._atomic_seq is None: if self._pending: break else: req_idx = self._atomic_seq_cont() if req_idx is not None: break self._dequeue_request(block=True) # If no request was pre-selected, prompt the user to choose one. if req_idx is None: raw_input('Pending feedback requests, hit Enter to ' 'process... ') # Pull all remaining queued requests. while self._dequeue_request(): pass # Select the request to process. if len(self._pending) == 1: print('Processing: %s' % self._pending[0].obj.get_title()) req_idx = 0 else: choose_req = sequenced_request.SequencedFeedbackRequest( None, None, None) choose_req.append_question( 'List of pending feedback requests:', input_handlers.MultipleChoiceInputHandler( [ req_tuple.obj.get_title() for req_tuple in self._pending ], default=1), prompt='Choose a request to process') req_idx, _ = choose_req.execute() # Pop and handle selected request, then close pipe. req_tuple = self._pending.pop(req_idx) if req_tuple.obj is not None: try: ret = req_tuple.obj.execute() except request.FeedbackRequestError as e: ret = (tester_feedback_client.QUERY_RET_ERROR, str(e)) reply_pipe = req_tuple.reduced_reply_pipe[0]( *req_tuple.reduced_reply_pipe[1]) reply_pipe.send(ret) reply_pipe.close() # Set the atomic sequence if so instructed. self._atomic_seq = (req_tuple.query_num if req_tuple.atomic else None) except self.RequestProcessingTerminated: pass