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
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
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)
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