Example #1
0
def get_song_meta(song_filename, chunk_size):
    music_file = audio_decoder.open(song_filename)
    sample_rate = music_file.getframerate()
    num_channels = music_file.getnchannels()
    sample_width = music_file.getsampwidth()
    frame = music_file.readframes(1)

    filename = os.path.basename(song_filename)
    dirname = os.path.dirname(song_filename)
    config_cache, fft_cache = check_cache_exists(dirname, filename)

    # TODO(mdietz): Try to get an id3 tag so we can get album and title
    meta = {
        "filename": filename,
        "path": dirname,
        "sample_rate": sample_rate,
        "num_channels": num_channels,
        "sample_width": sample_width,
        "frame_width": sample_width * num_channels,
        "config_cache": config_cache,
        "fft_cache": fft_cache,
        "chunk_size": chunk_size
    }
    meta.update(fetch_id3_meta(song_filename))

    music_file.close()
    return meta
Example #2
0
def cache_song(song_filename, chunk_size):
    music_file = audio_decoder.open(song_filename)
    sample_rate = music_file.getframerate()
    num_channels = music_file.getnchannels()
    logging.info("Sample rate: %s" % sample_rate)
    logging.info("Channels: %s" % num_channels)
    logging.info("Frame size: %s" % music_file.getsampwidth())

    fft_calc = fft.FFT(chunk_size, sample_rate, hc.GPIOLEN, _MIN_FREQUENCY,
                       _MAX_FREQUENCY, _CUSTOM_CHANNEL_MAPPING,
                       _CUSTOM_CHANNEL_FREQUENCIES)

    # Init cache matrix
    cache_matrix = np.empty(shape=[0, hc.GPIOLEN])
    cache_filename = os.path.dirname(song_filename) + "/." + os.path.basename(
        song_filename) + ".sync"
    cache_found = fft_calc.compare_config(cache_filename)

    if cache_found:
        mean, std, cache_matrix = load_cached_fft(fft_calc, cache_filename)
    else:
        # The values 12 and 1.5 are good estimates for first time playing back
        # (i.e. before we have the actual mean and standard deviations
        # calculated for each channel).
        mean = [12.0] * hc.GPIOLEN
        std = [1.5] * hc.GPIOLEN
        total = 0
        while True:
            data = music_file.readframes(chunk_size)
            if not data:
                break
            total += len(data)

            matrix = fft_calc.calculate_levels(data)
            # Add the matrix to the end of the cache
            cache_matrix = np.vstack([cache_matrix, matrix])

        for i in range(0, hc.GPIOLEN):
            std[i] = np.std([item for item in cache_matrix[:, i] if item > 0])
            mean[i] = np.mean(
                [item for item in cache_matrix[:, i] if item > 0])

        # Add mean and std to the top of the cache
        cache_matrix = np.vstack([mean, cache_matrix])
        cache_matrix = np.vstack([std, cache_matrix])

        # Save the cache using numpy savetxt
        np.savetxt(cache_filename, cache_matrix)

        # Save fft config
        fft_calc.save_config()

        logging.info("Cached sync data written to '." + cache_filename +
                     "' [" + str(len(cache_matrix)) + " rows]")

        logging.info("Cached config data written to '." +
                     fft_calc.config_filename)
    music_file.close()
    return mean, std, cache_matrix
Example #3
0
    def __init__(self, song_filename, chunk_size):
        music_file = audio_decoder.open(song_filename)
        self._chunk_size = chunk_size

        # TODO(mdietz): We can get this from the cache, too
        self.sample_rate = music_file.getframerate()
        self.num_channels = music_file.getnchannels()
        self.sample_width = music_file.getsampwidth()

        # Just a vanity metric
        chunk_period = float(self._chunk_size) / float(self.sample_rate)

        logging.info("Playing: %s" % song_filename)
        logging.info("Sample Rate: %d" % self.sample_rate)
        logging.info("Number of Channels: %d" % self.num_channels)
        logging.info("Chunk size: %d" % self._chunk_size)
        logging.info("Chunk period: %f" % chunk_period)
        self._stream = music_file
Example #4
0
    def __init__(self, song_filename, chunk_size):
        music_file = audio_decoder.open(song_filename)
        self._chunk_size = chunk_size

        # TODO(mdietz): We can get this from the cache, too
        self.sample_rate = music_file.getframerate()
        self.num_channels = music_file.getnchannels()
        self.sample_width = music_file.getsampwidth()

        # Just a vanity metric
        chunk_period = float(self._chunk_size) / float(self.sample_rate)

        logging.info("Playing: %s" % song_filename)
        logging.info("Sample Rate: %d" % self.sample_rate)
        logging.info("Number of Channels: %d" % self.num_channels)
        logging.info("Chunk size: %d" % self._chunk_size)
        logging.info("Chunk period: %f" % chunk_period)
        self._stream = music_file
def cache_song(song_filename, chunk_size):
    music_file = audio_decoder.open(song_filename)
    sample_rate = music_file.getframerate()
    num_channels = music_file.getnchannels()
    logging.info("Sample rate: %s" % sample_rate)
    logging.info("Channels: %s" % num_channels)
    logging.info("Frame size: %s" % music_file.getsampwidth())

    fft_calc = fft.FFT(chunk_size,
                       sample_rate,
                       hc.GPIOLEN,
                       _MIN_FREQUENCY,
                       _MAX_FREQUENCY,
                       _CUSTOM_CHANNEL_MAPPING,
                       _CUSTOM_CHANNEL_FREQUENCIES)

    # Init cache matrix
    cache_matrix = np.empty(shape=[0, hc.GPIOLEN])
    cache_filename = os.path.dirname(song_filename) + "/." + os.path.basename(
        song_filename) + ".sync"
    cache_found = fft_calc.compare_config(cache_filename)

    if cache_found:
        mean, std, cache_matrix = load_cached_fft(fft_calc, cache_filename)
    else:
        # The values 12 and 1.5 are good estimates for first time playing back
        # (i.e. before we have the actual mean and standard deviations
        # calculated for each channel).
        mean = [12.0] * hc.GPIOLEN
        std = [1.5] * hc.GPIOLEN
        total = 0
        while True:
            data = music_file.readframes(chunk_size)
            if not data:
                break
            total += len(data)

            matrix = fft_calc.calculate_levels(data)
            # Add the matrix to the end of the cache
            cache_matrix = np.vstack([cache_matrix, matrix])

        for i in range(0, hc.GPIOLEN):
            std[i] = np.std([item for item in cache_matrix[:, i]
                             if item > 0])
            mean[i] = np.mean([item for item in cache_matrix[:, i]
                               if item > 0])

        # Add mean and std to the top of the cache
        cache_matrix = np.vstack([mean, cache_matrix])
        cache_matrix = np.vstack([std, cache_matrix])

        # Save the cache using numpy savetxt
        np.savetxt(cache_filename, cache_matrix)

        # Save fft config
        fft_calc.save_config()

        logging.info("Cached sync data written to '." + cache_filename
                     + "' [" + str(len(cache_matrix)) + " rows]")

        logging.info("Cached config data written to '." +
                     fft_calc.config_filename)
    music_file.close()
    return mean, std, cache_matrix