Esempio n. 1
0
def stream_memory(
        data: bytes,
        ma_output_format: int = ma_format_s16,
        nchannels: int = 2,
        sample_rate: int = 44100,
        frames_to_read: int = 1024) -> Generator[array.array, int, None]:
    """
    Convenience generator function to decode and stream any supported audio file in memory
    as chunks of raw PCM samples in the chosen format.
    If you send() a number into the generator rather than just using next() on it,
    you'll get that given number of frames, instead of the default configured amount.
    This is particularly useful to plug this stream into an audio device callback that
    wants a variable number of frames per call.
    """
    decoder = ffi.new("ma_decoder *")
    decoder_config = lib.ma_decoder_config_init(ma_output_format, nchannels,
                                                sample_rate)
    result = lib.ma_decoder_init_memory(data, len(data),
                                        ffi.addressof(decoder_config), decoder)
    if result != lib.MA_SUCCESS:
        raise DecodeError("failed to decode memory", result)
    g = _samples_generator(frames_to_read, nchannels, ma_output_format,
                           decoder, data)
    dummy = next(g)
    assert len(dummy) == 0
    return g
Esempio n. 2
0
def stream_file(filename: str,
                output_format: LibSampleFormat = LibSampleFormat.SIGNED16,
                nchannels: int = 2,
                sample_rate: int = 44100,
                frames_to_read: int = 1024,
                dither: DitherMode = DitherMode.NONE,
                seek_frame: int = 0) -> Generator[array.array, int, None]:
    """
    Convenience generator function to decode and stream any supported audio file
    as chunks of raw PCM samples in the chosen format.
    If you send() a number into the generator rather than just using next() on it,
    you'll get that given number of frames, instead of the default configured amount.
    This is particularly useful to plug this stream into an audio device callback that
    wants a variable number of frames per call.
    """
    filenamebytes = _get_filename_bytes(filename)
    decoder = ffi.new("ma_decoder *")
    decoder_config = lib.ma_decoder_config_init(output_format.value, nchannels,
                                                sample_rate)
    decoder_config.ditherMode = dither.value
    result = lib.ma_decoder_init_file(filenamebytes,
                                      ffi.addressof(decoder_config), decoder)
    if result != lib.MA_SUCCESS:
        raise DecodeError("failed to init decoder", result)
    if seek_frame > 0:
        result = lib.ma_decoder_seek_to_pcm_frame(decoder, seek_frame)
        if result != lib.MA_SUCCESS:
            raise DecodeError("failed to seek to frame", result)
    g = _samples_stream_generator(frames_to_read, nchannels, output_format,
                                  decoder, None)
    dummy = next(g)
    assert len(dummy) == 0
    return g
Esempio n. 3
0
def decode(data: bytes,
           ma_output_format: int = ma_format_s16,
           nchannels: int = 2,
           sample_rate: int = 44100) -> DecodedSoundFile:
    """Convenience function to decode any supported audio file in memory to raw PCM samples in your chosen format."""
    sample_width, samples = _decode_ma_format(ma_output_format)
    frames = ffi.new("ma_uint64 *")
    memory = ffi.new("void **")
    decoder_config = lib.ma_decoder_config_init(ma_output_format, nchannels,
                                                sample_rate)
    result = lib.ma_decode_memory(data, len(data),
                                  ffi.addressof(decoder_config), frames,
                                  memory)
    if result != lib.MA_SUCCESS:
        raise DecodeError("failed to decode data", result)
    buffer = ffi.buffer(memory[0], frames[0] * nchannels * sample_width)
    samples.frombytes(buffer)
    return DecodedSoundFile("<memory>", nchannels, sample_rate, sample_width,
                            ma_output_format, samples)
Esempio n. 4
0
def decode_file(filename: str,
                output_format: LibSampleFormat = LibSampleFormat.SIGNED16,
                nchannels: int = 2,
                sample_rate: int = 44100,
                dither: DitherMode = DitherMode.NONE):
    """Convenience function to decode any supported audio file to raw PCM samples in your chosen format."""
    sample_width = _width_from_format(output_format)
    filenamebytes = _get_filename_bytes(filename)
    with ffi.new("ma_uint64 *") as frames, ffi.new("void **") as memory:
        decoder_config = lib.ma_decoder_config_init(output_format.value,
                                                    nchannels, sample_rate)
        decoder_config.ditherMode = dither.value
        result = lib.ma_decode_file(filenamebytes,
                                    ffi.addressof(decoder_config), frames,
                                    memory)
        if result != lib.MA_SUCCESS:
            raise DecodeError("failed to decode file", result)
        buflen = frames[0] * nchannels * sample_width
        buffer = ffi.buffer(memory[0], buflen)
        # byte = bytearray(buflen)
        # byte[:] = buffer
        byte = bytes(buffer)
        lib.ma_free(memory[0], ffi.NULL)
        return byte