Esempio n. 1
0
def mp3_stream_file(
        filename: str,
        frames_to_read: int = 1024,
        want_nchannels: int = 0,
        want_sample_rate: int = 0) -> Generator[array.array, None, None]:
    """Streams the mp3 audio file as interleaved 16 bit signed integer sample arrays segments."""
    filenamebytes = _get_filename_bytes(filename)
    config = ffi.new("drmp3_config *")
    config.outputChannels = want_nchannels
    config.outputSampleRate = want_sample_rate
    mp3 = ffi.new("drmp3 *")
    if not lib.drmp3_init_file(mp3, filenamebytes, config):
        raise DecodeError("could not open/decode file")
    try:
        decodebuffer = ffi.new("drmp3_int16[]", frames_to_read * mp3.channels)
        buf_ptr = ffi.cast("drmp3_int16 *", decodebuffer)
        while True:
            num_samples = lib.drmp3_read_pcm_frames_s16(
                mp3, frames_to_read, buf_ptr)
            if num_samples <= 0:
                break
            buffer = ffi.buffer(decodebuffer, num_samples * 2 * mp3.channels)
            samples = _create_int_array(2)
            samples.frombytes(buffer)
            yield samples
    finally:
        lib.drmp3_uninit(mp3)
Esempio n. 2
0
 def __init__(self,
              ma_output_format: int = ma_format_s16,
              nchannels: int = 2,
              sample_rate: int = 44100,
              buffersize_msec: int = 200):
     self.format = ma_output_format
     self.sample_width, self.samples_array_proto = _decode_ma_format(
         ma_output_format)
     self.nchannels = nchannels
     self.sample_rate = sample_rate
     self.buffersize_msec = buffersize_msec
     self._device = ffi.new("ma_device *")
     _callback_data[id(self)] = self
     self.userdata_ptr = ffi.new("char[]", struct.pack('q', id(self)))
     self._devconfig = lib.ma_device_config_init(
         lib.ma_device_type_playback)
     lib.ma_device_config_set_params(ffi.addressof(self._devconfig),
                                     self.sample_rate, self.buffersize_msec,
                                     0, self.format, self.nchannels, 0, 0)
     self._devconfig.pUserData = self.userdata_ptr
     self._devconfig.dataCallback = lib.internal_data_callback
     self.audio_producer = None  # type: Optional[AudioProducerType]
     result = lib.ma_device_init(ffi.NULL, ffi.addressof(self._devconfig),
                                 self._device)
     if result != lib.MA_SUCCESS:
         raise MiniaudioError("failed to init device", result)
     if self._device.pContext.backend == lib.ma_backend_null:
         raise MiniaudioError("no suitable audio backend found")
     self.backend = ffi.string(
         lib.ma_get_backend_name(self._device.pContext.backend)).decode()
Esempio n. 3
0
def get_devices() -> Tuple[List[str], List[str]]:
    """Get two lists of supported audio devices: playback devices, recording devices."""
    playback_infos = ffi.new("ma_device_info**")
    playback_count = ffi.new("ma_uint32*")
    capture_infos = ffi.new("ma_device_info**")
    capture_count = ffi.new("ma_uint32*")
    context = ffi.new("ma_context*")
    result = lib.ma_context_init(ffi.NULL, 0, ffi.NULL, context)
    if result != lib.MA_SUCCESS:
        raise MiniaudioError("cannot init context", result)
    try:
        result = lib.ma_context_get_devices(context, playback_infos,
                                            playback_count, capture_infos,
                                            capture_count)
        if result != lib.MA_SUCCESS:
            raise MiniaudioError("cannot get device infos", result)
        devs_playback = []
        devs_captures = []
        for i in range(playback_count[0]):
            ma_device_info = playback_infos[0][i]
            devs_playback.append(ffi.string(ma_device_info.name).decode())
            # rest of the info structure is not filled...
        for i in range(capture_count[0]):
            ma_device_info = capture_infos[0][i]
            devs_captures.append(ffi.string(ma_device_info.name).decode())
            # rest of the info structure is not filled...
        return devs_playback, devs_captures
    finally:
        lib.ma_context_uninit(context)
Esempio n. 4
0
def vorbis_stream_file(filename: str) -> Generator[array.array, None, None]:
    """Streams the ogg vorbis audio file as interleaved 16 bit signed integer sample arrays segments."""
    filenamebytes = _get_filename_bytes(filename)
    error = ffi.new("int *")
    vorbis = lib.stb_vorbis_open_filename(filenamebytes, error, ffi.NULL)
    if not vorbis:
        raise DecodeError("could not open/decode file")
    try:
        info = lib.stb_vorbis_get_info(vorbis)
        decode_buffer1 = ffi.new("short[]", 4096 * info.channels)
        decodebuf_ptr1 = ffi.cast("short *", decode_buffer1)
        decode_buffer2 = ffi.new("short[]", 4096 * info.channels)
        decodebuf_ptr2 = ffi.cast("short *", decode_buffer2)
        # note: we decode several frames to reduce the overhead of very small sample sizes a little
        while True:
            num_samples1 = lib.stb_vorbis_get_frame_short_interleaved(
                vorbis, info.channels, decodebuf_ptr1, 4096 * info.channels)
            num_samples2 = lib.stb_vorbis_get_frame_short_interleaved(
                vorbis, info.channels, decodebuf_ptr2, 4096 * info.channels)
            if num_samples1 + num_samples2 <= 0:
                break
            buffer = ffi.buffer(decode_buffer1,
                                num_samples1 * 2 * info.channels)
            samples = _create_int_array(2)
            samples.frombytes(buffer)
            if num_samples2 > 0:
                buffer = ffi.buffer(decode_buffer2,
                                    num_samples2 * 2 * info.channels)
                samples.frombytes(buffer)
            yield samples
    finally:
        lib.stb_vorbis_close(vorbis)
Esempio n. 5
0
def mp3_get_info(data: bytes) -> SoundFileInfo:
    """Fetch some information about the audio data (mp3 format)."""
    config = ffi.new("drmp3_config *")
    config.outputChannels = 0
    config.outputSampleRate = 0
    mp3 = ffi.new("drmp3 *")
    if not lib.drmp3_init_memory(mp3, data, len(data), config):
        raise DecodeError("could not open/decode data")
    try:
        num_frames = lib.drmp3_get_pcm_frame_count(mp3)
        duration = num_frames / mp3.sampleRate
        return SoundFileInfo("<memory>", "mp3", mp3.channels, mp3.sampleRate,
                             2, ma_format_s16, duration, num_frames, 0)
    finally:
        lib.drmp3_uninit(mp3)
Esempio n. 6
0
def _samples_generator(frames_to_read: int, nchannels: int,
                       ma_output_format: int, decoder: ffi.CData,
                       data: Any) -> Generator[array.array, int, None]:
    _reference = data  # make sure any data passed in is not garbage collected
    sample_width, samples_proto = _decode_ma_format(ma_output_format)
    allocated_buffer_frames = max(frames_to_read, 16384)
    try:
        decodebuffer = ffi.new(
            "int8_t[]", allocated_buffer_frames * nchannels * sample_width)
        buf_ptr = ffi.cast("void *", decodebuffer)
        want_frames = (yield samples_proto) or frames_to_read
        while True:
            if want_frames > allocated_buffer_frames:
                raise MiniaudioError(
                    "wanted to read more frames than storage was allocated for ({} vs {})"
                    .format(want_frames, allocated_buffer_frames))
            num_frames = lib.ma_decoder_read_pcm_frames(
                decoder, buf_ptr, want_frames)
            if num_frames <= 0:
                break
            buffer = ffi.buffer(decodebuffer,
                                num_frames * sample_width * nchannels)
            samples = array.array(samples_proto.typecode)
            samples.frombytes(buffer)
            want_frames = (yield samples) or frames_to_read
    finally:
        lib.ma_decoder_uninit(decoder)
Esempio n. 7
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. 8
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. 9
0
def _samples_stream_generator(
        frames_to_read: int,
        nchannels: int,
        output_format: LibSampleFormat,
        decoder: ffi.CData,
        data: Any,
        on_close: Optional[Callable] = None
) -> Generator[array.array, int, None]:
    _reference = data  # make sure any data passed in is not garbage collected
    sample_width = _width_from_format(output_format)
    samples_proto = _array_proto_from_format(output_format)
    allocated_buffer_frames = max(frames_to_read, 16384)
    try:
        with ffi.new("int8_t[]", allocated_buffer_frames * nchannels *
                     sample_width) as decodebuffer:
            buf_ptr = ffi.cast("void *", decodebuffer)
            want_frames = (yield samples_proto) or frames_to_read
            while True:
                num_frames = lib.ma_decoder_read_pcm_frames(
                    decoder, buf_ptr, want_frames)
                if num_frames <= 0:
                    break
                buffer = ffi.buffer(decodebuffer,
                                    num_frames * sample_width * nchannels)
                samples = array.array(samples_proto.typecode)
                samples.frombytes(buffer)
                want_frames = (yield samples) or frames_to_read
    finally:
        if on_close:
            on_close()
        lib.ma_decoder_uninit(decoder)
Esempio n. 10
0
def mp3_get_file_info(filename: str) -> SoundFileInfo:
    """Fetch some information about the audio file (mp3 format)."""
    filenamebytes = _get_filename_bytes(filename)
    config = ffi.new("drmp3_config *")
    config.outputChannels = 0
    config.outputSampleRate = 0
    mp3 = ffi.new("drmp3 *")
    if not lib.drmp3_init_file(mp3, filenamebytes, config):
        raise DecodeError("could not open/decode file")
    try:
        num_frames = lib.drmp3_get_pcm_frame_count(mp3)
        duration = num_frames / mp3.sampleRate
        return SoundFileInfo(filename, "mp3", mp3.channels, mp3.sampleRate, 2,
                             ma_format_s16, duration, num_frames, 0)
    finally:
        lib.drmp3_uninit(mp3)
Esempio n. 11
0
def flac_read_s16(data: bytes) -> DecodedSoundFile:
    """Reads and decodes the whole flac audio data. Resulting sample format is 16 bits signed integer."""
    channels = ffi.new("unsigned int *")
    sample_rate = ffi.new("unsigned int *")
    num_frames = ffi.new("drflac_uint64 *")
    memory = lib.drflac_open_memory_and_read_pcm_frames_s16(
        data, len(data), channels, sample_rate, num_frames)
    if not memory:
        raise DecodeError("cannot load/decode data")
    try:
        samples = _create_int_array(2)
        buffer = ffi.buffer(memory, num_frames[0] * channels[0] * 2)
        samples.frombytes(buffer)
        return DecodedSoundFile("<memory>", channels[0], sample_rate[0], 2,
                                ma_format_s16, samples)
    finally:
        lib.drflac_free(memory)
Esempio n. 12
0
def wav_read_f32(data: bytes) -> DecodedSoundFile:
    """Reads and decodes the whole wav audio data. Resulting sample format is 32 bits float."""
    channels = ffi.new("unsigned int *")
    sample_rate = ffi.new("unsigned int *")
    num_frames = ffi.new("drwav_uint64 *")
    memory = lib.drwav_open_memory_and_read_pcm_frames_f32(
        data, len(data), channels, sample_rate, num_frames)
    if not memory:
        raise DecodeError("cannot load/decode data")
    try:
        samples = array.array('f')
        buffer = ffi.buffer(memory, num_frames[0] * channels[0] * 4)
        samples.frombytes(buffer)
        return DecodedSoundFile("<memory>", channels[0], sample_rate[0], 4,
                                ma_format_f32, samples)
    finally:
        lib.drwav_free(memory)
Esempio n. 13
0
def vorbis_read(data: bytes) -> DecodedSoundFile:
    """Reads and decodes the whole vorbis audio data. Resulting sample format is 16 bits signed integer."""
    channels = ffi.new("int *")
    sample_rate = ffi.new("int *")
    output = ffi.new("short **")
    num_samples = lib.stb_vorbis_decode_memory(data, len(data), channels,
                                               sample_rate, output)
    if num_samples <= 0:
        raise DecodeError("cannot load/decode data")
    try:
        buffer = ffi.buffer(output[0], num_samples * channels[0] * 2)
        samples = _create_int_array(2)
        samples.frombytes(buffer)
        return DecodedSoundFile("<memory>", channels[0], sample_rate[0], 2,
                                ma_format_s16, samples)
    finally:
        lib.free(output[0])
Esempio n. 14
0
def wav_read_file_s16(filename: str) -> DecodedSoundFile:
    """Reads and decodes the whole wav audio file. Resulting sample format is 16 bits signed integer."""
    filenamebytes = _get_filename_bytes(filename)
    channels = ffi.new("unsigned int *")
    sample_rate = ffi.new("unsigned int *")
    num_frames = ffi.new("drwav_uint64 *")
    memory = lib.drwav_open_file_and_read_pcm_frames_s16(
        filenamebytes, channels, sample_rate, num_frames)
    if not memory:
        raise DecodeError("cannot load/decode file")
    try:
        samples = _create_int_array(2)
        buffer = ffi.buffer(memory, num_frames[0] * channels[0] * 2)
        samples.frombytes(buffer)
        return DecodedSoundFile(filename, channels[0], sample_rate[0], 2,
                                ma_format_s16, samples)
    finally:
        lib.drwav_free(memory)
Esempio n. 15
0
def flac_read_file_f32(filename: str) -> DecodedSoundFile:
    """Reads and decodes the whole flac audio file. Resulting sample format is 32 bits float."""
    filenamebytes = _get_filename_bytes(filename)
    channels = ffi.new("unsigned int *")
    sample_rate = ffi.new("unsigned int *")
    num_frames = ffi.new("drflac_uint64 *")
    memory = lib.drflac_open_file_and_read_pcm_frames_f32(
        filenamebytes, channels, sample_rate, num_frames)
    if not memory:
        raise DecodeError("cannot load/decode file")
    try:
        samples = array.array('f')
        buffer = ffi.buffer(memory, num_frames[0] * channels[0] * 4)
        samples.frombytes(buffer)
        return DecodedSoundFile(filename, channels[0], sample_rate[0], 4,
                                ma_format_f32, samples)
    finally:
        lib.drflac_free(memory)
Esempio n. 16
0
def vorbis_read_file(filename: str) -> DecodedSoundFile:
    """Reads and decodes the whole vorbis audio file. Resulting sample format is 16 bits signed integer."""
    filenamebytes = _get_filename_bytes(filename)
    channels = ffi.new("int *")
    sample_rate = ffi.new("int *")
    output = ffi.new("short **")
    num_frames = lib.stb_vorbis_decode_filename(filenamebytes, channels,
                                                sample_rate, output)
    if num_frames <= 0:
        raise DecodeError("cannot load/decode file")
    try:
        buffer = ffi.buffer(output[0], num_frames * channels[0] * 2)
        samples = _create_int_array(2)
        samples.frombytes(buffer)
        return DecodedSoundFile(filename, channels[0], sample_rate[0], 2,
                                ma_format_s16, samples)
    finally:
        lib.free(output[0])
Esempio n. 17
0
def wav_write_file(filename: str, data, nchannels, sample_rate,
                   sample_width) -> None:
    """Writes the pcm sound to a WAV file"""
    with ffi.new("drwav_data_format*") as fmt, ffi.new("drwav*") as pwav:
        fmt.container = lib.drwav_container_riff
        fmt.format = lib.DR_WAVE_FORMAT_PCM
        fmt.channels = nchannels
        fmt.sampleRate = sample_rate
        fmt.bitsPerSample = sample_width * 8
        # what about floating point format?
        filename_bytes = filename.encode(sys.getfilesystemencoding())
        buffer_len = int(len(data) / sample_width)
        if not lib.drwav_init_file_write_sequential(pwav, filename_bytes, fmt,
                                                    buffer_len, ffi.NULL):
            raise IOError("can't open file for writing")
        try:
            lib.drwav_write_pcm_frames(pwav, int(buffer_len / nchannels), data)
        finally:
            lib.drwav_uninit(pwav)
Esempio n. 18
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. 19
0
def mp3_read_s16(data: bytes,
                 want_nchannels: int = 0,
                 want_sample_rate: int = 0) -> DecodedSoundFile:
    """Reads and decodes the whole mp3 audio data. Resulting sample format is 16 bits signed integer."""
    config = ffi.new("drmp3_config *")
    config.outputChannels = want_nchannels
    config.outputSampleRate = want_sample_rate
    num_frames = ffi.new("drmp3_uint64 *")
    memory = lib.drmp3_open_memory_and_read_s16(data, len(data), config,
                                                num_frames)
    if not memory:
        raise DecodeError("cannot load/decode data")
    try:
        samples = _create_int_array(2)
        buffer = ffi.buffer(memory, num_frames[0] * config.outputChannels * 2)
        samples.frombytes(buffer)
        return DecodedSoundFile("<memory>", config.outputChannels,
                                config.outputSampleRate, 2, ma_format_s16,
                                samples)
    finally:
        lib.drmp3_free(memory)
Esempio n. 20
0
def mp3_get_info(data: bytes) -> SoundFileInfo:
    """Fetch some information about the audio data (mp3 format)."""
    with ffi.new("drmp3 *") as mp3:
        if not lib.drmp3_init_memory(mp3, data, len(data), ffi.NULL):
            raise DecodeError("could not open/decode data")
        try:
            num_frames = lib.drmp3_get_pcm_frame_count(mp3)
            duration = num_frames / mp3.sampleRate
            return SoundFileInfo("<memory>", FileFormat.MP3, mp3.channels,
                                 mp3.sampleRate, LibSampleFormat.SIGNED16,
                                 duration, num_frames)
        finally:
            lib.drmp3_uninit(mp3)
Esempio n. 21
0
def mp3_read_file_f32(filename: str,
                      want_nchannels: int = 0,
                      want_sample_rate: int = 0) -> DecodedSoundFile:
    """Reads and decodes the whole mp3 audio file. Resulting sample format is 32 bits float."""
    filenamebytes = _get_filename_bytes(filename)
    config = ffi.new("drmp3_config *")
    config.outputChannels = want_nchannels
    config.outputSampleRate = want_sample_rate
    num_frames = ffi.new("drmp3_uint64 *")
    memory = lib.drmp3_open_file_and_read_f32(filenamebytes, config,
                                              num_frames)
    if not memory:
        raise DecodeError("cannot load/decode file")
    try:
        samples = array.array('f')
        buffer = ffi.buffer(memory, num_frames[0] * config.outputChannels * 4)
        samples.frombytes(buffer)
        return DecodedSoundFile(filename, config.outputChannels,
                                config.outputSampleRate, 4, ma_format_f32,
                                samples)
    finally:
        lib.drmp3_free(memory)
Esempio n. 22
0
def mp3_get_file_info(filename: str) -> SoundFileInfo:
    """Fetch some information about the audio file (mp3 format)."""
    filenamebytes = _get_filename_bytes(filename)
    with ffi.new("drmp3 *") as mp3:
        if not lib.drmp3_init_file(mp3, filenamebytes, ffi.NULL):
            raise DecodeError("could not open/decode file")
        try:
            num_frames = lib.drmp3_get_pcm_frame_count(mp3)
            duration = num_frames / mp3.sampleRate
            return SoundFileInfo(filename, FileFormat.MP3, mp3.channels,
                                 mp3.sampleRate, LibSampleFormat.SIGNED16,
                                 duration, num_frames)
        finally:
            lib.drmp3_uninit(mp3)
Esempio n. 23
0
def wav_get_info(data: bytes) -> SoundFileInfo:
    """Fetch some information about the audio data (wav format)."""
    with ffi.new("drwav*") as wav:
        if not lib.drwav_init_memory(wav, data, len(data), ffi.NULL):
            raise DecodeError("could not open/decode data")
        try:
            duration = wav.totalPCMFrameCount / wav.sampleRate
            sample_width = wav.bitsPerSample // 8
            is_float = wav.translatedFormatTag == lib.DR_WAVE_FORMAT_IEEE_FLOAT
            return SoundFileInfo("<memory>", FileFormat.WAV, wav.channels,
                                 wav.sampleRate,
                                 _format_from_width(sample_width, is_float),
                                 duration, wav.totalPCMFrameCount)
        finally:
            lib.drwav_uninit(wav)
Esempio n. 24
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
Esempio n. 25
0
def vorbis_get_info(data: bytes) -> SoundFileInfo:
    """Fetch some information about the audio data (vorbis format)."""
    with ffi.new("int *") as error:
        vorbis = lib.stb_vorbis_open_memory(data, len(data), error, ffi.NULL)
        if not vorbis:
            raise DecodeError("could not open/decode data")
        try:
            info = lib.stb_vorbis_get_info(vorbis)
            duration = lib.stb_vorbis_stream_length_in_seconds(vorbis)
            num_frames = lib.stb_vorbis_stream_length_in_samples(vorbis)
            return SoundFileInfo("<memory>", FileFormat.VORBIS, info.channels,
                                 info.sample_rate, LibSampleFormat.SIGNED16,
                                 duration, num_frames)
        finally:
            lib.stb_vorbis_close(vorbis)
Esempio n. 26
0
def vorbis_get_info(data: bytes) -> SoundFileInfo:
    """Fetch some information about the audio data (vorbis format)."""
    error = ffi.new("int *")
    vorbis = lib.stb_vorbis_open_memory(data, len(data), error, ffi.NULL)
    if not vorbis:
        raise DecodeError("could not open/decode data")
    try:
        info = lib.stb_vorbis_get_info(vorbis)
        duration = lib.stb_vorbis_stream_length_in_seconds(vorbis)
        num_frames = lib.stb_vorbis_stream_length_in_samples(vorbis)
        return SoundFileInfo("<memory>", "vorbis", info.channels,
                             info.sample_rate, 2, ma_format_s16, duration,
                             num_frames, info.max_frame_size)
    finally:
        lib.stb_vorbis_close(vorbis)
Esempio n. 27
0
def wav_get_file_info(filename: str) -> SoundFileInfo:
    """Fetch some information about the audio file (wav format)."""
    filenamebytes = _get_filename_bytes(filename)
    with ffi.new("drwav*") as wav:
        if not lib.drwav_init_file(wav, filenamebytes, ffi.NULL):
            raise DecodeError("could not open/decode file")
        try:
            duration = wav.totalPCMFrameCount / wav.sampleRate
            sample_width = wav.bitsPerSample // 8
            is_float = wav.translatedFormatTag == lib.DR_WAVE_FORMAT_IEEE_FLOAT
            return SoundFileInfo(filename, FileFormat.WAV, wav.channels,
                                 wav.sampleRate,
                                 _format_from_width(sample_width, is_float),
                                 duration, wav.totalPCMFrameCount)
        finally:
            lib.drwav_uninit(wav)
Esempio n. 28
0
def vorbis_get_file_info(filename: str) -> SoundFileInfo:
    """Fetch some information about the audio file (vorbis format)."""
    filenamebytes = _get_filename_bytes(filename)
    error = ffi.new("int *")
    vorbis = lib.stb_vorbis_open_filename(filenamebytes, error, ffi.NULL)
    if not vorbis:
        raise DecodeError("could not open/decode file")
    try:
        info = lib.stb_vorbis_get_info(vorbis)
        duration = lib.stb_vorbis_stream_length_in_seconds(vorbis)
        num_frames = lib.stb_vorbis_stream_length_in_samples(vorbis)
        return SoundFileInfo(filename, "vorbis", info.channels,
                             info.sample_rate, 2, ma_format_s16, duration,
                             num_frames, info.max_frame_size)
    finally:
        lib.stb_vorbis_close(vorbis)
Esempio n. 29
0
def vorbis_get_file_info(filename: str) -> SoundFileInfo:
    """Fetch some information about the audio file (vorbis format)."""
    filenamebytes = _get_filename_bytes(filename)
    with ffi.new("int *") as error:
        vorbis = lib.stb_vorbis_open_filename(filenamebytes, error, ffi.NULL)
        if not vorbis:
            raise DecodeError("could not open/decode file")
        try:
            info = lib.stb_vorbis_get_info(vorbis)
            duration = lib.stb_vorbis_stream_length_in_seconds(vorbis)
            num_frames = lib.stb_vorbis_stream_length_in_samples(vorbis)
            return SoundFileInfo(filename, FileFormat.VORBIS, info.channels,
                                 info.sample_rate, LibSampleFormat.SIGNED16,
                                 duration, num_frames)
        finally:
            lib.stb_vorbis_close(vorbis)
Esempio n. 30
0
def wav_stream_file(
        filename: str,
        frames_to_read: int = 1024) -> Generator[array.array, None, None]:
    """Streams the WAV audio file as interleaved 16 bit signed integer sample arrays segments."""
    filenamebytes = _get_filename_bytes(filename)
    wav = lib.drwav_open_file(filenamebytes)
    if not wav:
        raise DecodeError("could not open/decode file")
    try:
        decodebuffer = ffi.new("drwav_int16[]", frames_to_read * wav.channels)
        buf_ptr = ffi.cast("drwav_int16 *", decodebuffer)
        while True:
            num_samples = lib.drwav_read_pcm_frames_s16(
                wav, frames_to_read, buf_ptr)
            if num_samples <= 0:
                break
            buffer = ffi.buffer(decodebuffer, num_samples * 2 * wav.channels)
            samples = _create_int_array(2)
            samples.frombytes(buffer)
            yield samples
    finally:
        lib.drwav_close(wav)