def _callback(self, in_data, frame_count, time_info, status):
        if self.status & self.recording_mask:
            pass

        if self.status & self.detecting_mask:
            self.detect_queue.put(in_data)

        if self.status & self.listening_mask:
            active = vad.is_speech(in_data)
            if active:
                if not self.active:
                    for d in self.listen_history:
                        self.listen_queue.put(d)
                        self.listen_countdown[0] -= 1

                    self.listen_history.clear()

                self.listen_queue.put(in_data)
                self.listen_countdown[0] -= 1
            else:
                if self.active:
                    self.listen_queue.put(in_data)
                else:
                    self.listen_history.append(in_data)

                self.listen_countdown[1] -= 1

            if self.listen_countdown[0] <= 0 or self.listen_countdown[1] <= 0:
                self.listen_queue.put('')
                self.status &= ~self.listening_mask
                logger.info('Stop listening')

            self.active = active

        return None, pyaudio.paContinue
Esempio n. 2
0
def main():
    sample_rate = 48000
    channels = 2
    N = 4096 * 4

    mic = Microphone(sample_rate, channels)
    window = np.hanning(N)

    sound_speed = 343
    distance = 0.14

    max_tau = distance / sound_speed

    def signal_handler(sig, num):
        print('Quit')
        mic.close()

    signal.signal(signal.SIGINT, signal_handler)

    for data in mic.read_chunks(N):
        buf = np.fromstring(data, dtype='int16')
        mono = buf[0::channels].tostring()
        if sample_rate != 16000:
            mono, _ = audioop.ratecv(mono, 2, 1, sample_rate, 16000, None)

        if vad.is_speech(mono):
            tau, _ = gcc_phat(buf[0::channels] * window,
                              buf[1::channels] * window,
                              fs=sample_rate,
                              max_tau=max_tau)
            theta = math.asin(tau / max_tau) * 180 / math.pi
            print('\ntheta: {}'.format(int(theta)))
Esempio n. 3
0
    def start(self,
              detected_callback=play_audio_file,
              interrupt_check=lambda: False,
              sleep_time=0.03):
        """
        Start the voice detector. For every `sleep_time` second it checks the
        audio buffer for triggering keywords. If detected, then call
        corresponding function in `detected_callback`, which can be a single
        function (single model) or a list of callback functions (multiple
        models). Every loop it also calls `interrupt_check` -- if it returns
        True, then breaks from the loop and return.

        :param detected_callback: a function or list of functions. The number of
                                  items must match the number of models in
                                  `decoder_model`.
        :param interrupt_check: a function that returns True if the main loop
                                needs to stop.
        :param float sleep_time: how much time in second every loop waits.
        :return: None
        """
        if interrupt_check():
            logger.debug("detect voice return")
            return

        tc = type(detected_callback)
        if tc is not list:
            detected_callback = [detected_callback]
        if len(detected_callback) == 1 and self.num_hotwords > 1:
            detected_callback *= self.num_hotwords

        assert self.num_hotwords == len(detected_callback), \
            "Error: hotwords in your models (%d) do not match the number of " \
            "callbacks (%d)" % (self.num_hotwords, len(detected_callback))

        logger.debug("detecting...")

        while True:
            if interrupt_check():
                logger.debug("detect voice break")
                break
            data = self.ring_buffer.get()
            if len(data) == 0:
                time.sleep(sleep_time)
                continue

            ans = self.detector.RunDetection(data)
            if ans == -1:
                logger.warning(
                    "Error initializing streams or reading audio data")
            elif ans > 0:
                message = "Keyword " + str(ans) + " detected at time: "
                message += time.strftime("%Y-%m-%d %H:%M:%S",
                                         time.localtime(time.time()))
                logger.info(message)
                play_audio_file(fname=DETECT_DING)
                callback = detected_callback[ans - 1]
                if callback is not None:
                    listen = True
                    listen_history = []
                    cnt = 0
                    VAD_DELAY = 0.2
                    MAX_CNT = int(3 / VAD_DELAY)
                    vad_trig = False
                    vad.reset()
                    while listen:
                        data = self.ring_buffer.get()
                        active = vad.is_speech(data)
                        if active and cnt > 1:
                            vad_trig = True
                        ans = self.detector.RunDetection(data)
                        logger.info("Detection status: %d, VAD: %s" %
                                    (ans, active))
                        if ans == 1:
                            listen_history = []
                            continue
                        elif ans == 0:
                            listen_history.extend(data)
                            cnt += 1
                            if cnt > MAX_CNT:
                                listen = False
                            elif vad_trig and not active:
                                listen = False
                        elif ans == -2:
                            if not vad_trig:
                                listen_history = []
                                cnt += 1
                                if cnt > MAX_CNT:
                                    listen = False
                                # elif vad_trig and not active:
                                #     listen_history.extend(data)
                                else:
                                    time.sleep(VAD_DELAY)
                                    continue
                            listen = False
                        time.sleep(VAD_DELAY)
                    if len(listen_history) > 0:
                        callback(listen_history,
                                 rate=self.detector.SampleRate())