Beispiel #1
0
class Music(Default):
    """
    Music reactive leds
    """

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.pattern_name = "Music"

        CONFIGS['n_pixels'] = self.strip_length

        # init visualizer
        self.vis = Visualizer(CONFIGS)

        # dict used to set the visualizer effect
        self.effect_dict = dict(
            spectrum=self.vis.visualize_spectrum,
            energy=self.vis.visualize_energy,
            scroll=self.vis.visualize_scroll,
        )

        # name of the effect to be used
        self.effect = Modifier('visualizer', "spectrum", options=list(self.effect_dict.keys()),
                               on_change=self.on_change)
        self._rate = Modifier('Delay', 0, minimum=0, maximum=0)

        self.modifiers = dict(
            effect=self.effect,
        )

        # attributes for the mic
        self.p = None
        self.stream = None
        self.frames_per_buffer = int(CONFIGS['mic_rate'] / CONFIGS['fps'])

        try:
            # do not initialize if the pattern is temp
            if kwargs['handler'] is not None:
                self.setup()
        except OSError:
            music_logger.warning(f"Could not initialize the audio stream")

    def setup(self):
        """
        Setup stream
        """
        self.p = pyaudio.PyAudio()
        self.stream = self.p.open(format=pyaudio.paInt16,
                                  channels=1,
                                  rate=CONFIGS['mic_rate'],
                                  input=True,
                                  frames_per_buffer=self.frames_per_buffer)

        music_logger.info(f"Audio stream initialized with {CONFIGS['fps']} fps")

    def on_change(self, value):
        """
        Set the effect to a certain value and change the visualization effect in the vis calss
        """
        try:
            ef = self.effect_dict[value]
            self.vis.visualization_effect = ef

        except KeyError as e:
            music_logger.warning(f"Error for key {value}\n{e}")

    @property
    def rate(self):
        """
        Rate should always be zero here
        """
        return self._rate

    @rate.setter
    def rate(self, value):
        """
        Cannot change the value of rate since music must be real time
        :param value:
        :return:
        """
        pass

    def read_audio(self):
        """
        Read audio and return it
        """
        try:
            y = np.fromstring(self.stream.read(self.frames_per_buffer, exception_on_overflow=False),
                              dtype=np.int16)
            y = y.astype(np.float32)
            return y
        except IOError:
            music_logger.warning('Audio buffer has overflowed')
        except AttributeError:
            music_logger.error("Could not read from audio buffer, do you have a microphone?")
            self.close()

    def fill(self):
        """
        Read from audio stream and set pixels
        """
        # read audio input, can also be none when the mic has not started yet
        output = self.read_audio()

        try:
            # use visualization
            pixels, _ = self.vis.audio_to_rgb(output)
            # Truncate values and cast to integer
            pixels = np.clip(pixels, 0, 255).astype(int)
            # Optional gamma correction
            pixels = _gamma[pixels]

            r, g, b = pixels
            for idx in range(len(r)):
                self.pixels[idx]['color'] = (r[idx], g[idx], b[idx], 255)

        except TypeError:
            pass

    def close(self):
        """
        Call super method and close audio stream
        """
        super(Music, self).close()

        try:
            # try to stop the stream if any
            self.stream.stop_stream()
            self.stream.close()
        except AttributeError:
            # if there is no recognized microphone then the close operation will fail on the stream
            pass
        finally:
            # terminate the py audio and log
            self.p.terminate()
            music_logger.info("Audio stream stopped")
Beispiel #2
0
class Music(Default):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.pattern_name = "Music"

        CONFIGS['n_pixels'] = self.strip_length

        # init visualizer
        self.vis = Visualizer(CONFIGS)

        # dict used to set the visualizer effect
        self.effect_dict = dict(
            spectrum=self.vis.visualize_spectrum,
            energy=self.vis.visualize_energy,
            scroll=self.vis.visualize_scroll,
        )

        # name of the effect to be used
        self.effect = 'spectrum'

        self.modifiers = dict(visualizer=self.effect, )

        # attributes for the mic
        self.p = None
        self.stream = None
        self.frames_per_buffer = int(CONFIGS['mic_rate'] / CONFIGS['fps'])

        self.setup()

    def setup(self):
        """
        Setup stream
        """
        self.p = pyaudio.PyAudio()
        self.stream = self.p.open(format=pyaudio.paInt16,
                                  channels=1,
                                  rate=CONFIGS['mic_rate'],
                                  input=True,
                                  frames_per_buffer=self.frames_per_buffer)

    @property
    def effect(self):
        return self._effect

    @effect.setter
    def effect(self, value):
        """
        Set the effect to a certain value and change the visualization effect in the vis calss
        """
        try:
            ef = self.effect_dict[value]
            self.vis.visualization_effect = ef
            self._effect = value

        except KeyError as e:
            print(f"Error for key {value}\n{e}")

    @property
    def rate(self):
        """
        Rate should always be zero here9
        """
        return 0

    @rate.setter
    def rate(self, value):
        pass

    def read_audio(self):
        """
        Read audio and return it
        """
        try:
            y = np.fromstring(self.stream.read(self.frames_per_buffer,
                                               exception_on_overflow=False),
                              dtype=np.int16)
            y = y.astype(np.float32)
            self.stream.read(self.stream.get_read_available(),
                             exception_on_overflow=False)
            return y
        except IOError:
            print('Audio buffer has overflowed')

    def fill(self):
        """
        Read from audio stream and set pixels
        """
        # read audio input, can also be none when the mic has not started yet
        output = self.read_audio()

        try:
            # use visualization
            pixels, _ = self.vis.audio_to_rgb(output)
            # Truncate values and cast to integer
            pixels = np.clip(pixels, 0, 255).astype(int)
            # Optional gamma correction
            pixels = _gamma[pixels]

            r, g, b = pixels
            for idx in range(len(r)):
                self.pixels[idx]['color'] = (r[idx], g[idx], b[idx], 255)

        except TypeError:
            pass

    def stop(self):
        """
        Call super method and close audio stream
        """
        super(Music, self).stop()

        self.stream.stop_stream()
        self.stream.close()
        self.p.terminate()