Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def flac_get_file_info(filename: str) -> SoundFileInfo:
"""Fetch some information about the audio file (flac format)."""
filenamebytes = _get_filename_bytes(filename)
flac = lib.drflac_open_file(filenamebytes, ffi.NULL)
if not flac:
raise DecodeError("could not open/decode file")
try:
duration = flac.totalPCMFrameCount / flac.sampleRate
sample_width = flac.bitsPerSample // 8
return SoundFileInfo(filename, FileFormat.FLAC, flac.channels, flac.sampleRate,
_format_from_width(sample_width), duration, flac.totalPCMFrameCount)
finally:
lib.drflac_close(flac)
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, 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,
SampleFormat.SIGNED16, duration, num_frames)
finally:
lib.drmp3_uninit(mp3)
Convenience generator function to decode and stream any source of encoded audio data
(such as a network stream). Stream result is 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(output_format.value, nchannels, sample_rate)
decoder_config.ditherMode = dither.value
_callback_decoder_sources[id(source)] = source
source.userdata_ptr = ffi.new("char[]", struct.pack('q', id(source)))
decoder_init = {
FileFormat.UNKNOWN: lib.ma_decoder_init,
FileFormat.VORBIS: lib.ma_decoder_init_vorbis,
FileFormat.WAV: lib.ma_decoder_init_wav,
FileFormat.FLAC: lib.ma_decoder_init_flac,
FileFormat.MP3: lib.ma_decoder_init_mp3
}[source_format]
result = decoder_init(lib._internal_decoder_read_callback, lib._internal_decoder_seek_callback,
source.userdata_ptr, 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)
def on_close() -> None:
if id(source) in _callback_decoder_sources:
del _callback_decoder_sources[id(source)]
dither: DitherMode = DitherMode.NONE, seek_frame: int = 0) -> Generator[array.array, int, None]:
"""
Convenience generator function to decode and stream any source of encoded audio data
(such as a network stream). Stream result is 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(output_format.value, nchannels, sample_rate)
decoder_config.ditherMode = dither.value
_callback_decoder_sources[id(source)] = source
source.userdata_ptr = ffi.new("char[]", struct.pack('q', id(source)))
decoder_init = {
FileFormat.UNKNOWN: lib.ma_decoder_init,
FileFormat.VORBIS: lib.ma_decoder_init_vorbis,
FileFormat.WAV: lib.ma_decoder_init_wav,
FileFormat.FLAC: lib.ma_decoder_init_flac,
FileFormat.MP3: lib.ma_decoder_init_mp3
}[source_format]
result = decoder_init(lib._internal_decoder_read_callback, lib._internal_decoder_seek_callback,
source.userdata_ptr, 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)
def on_close() -> None:
if id(source) in _callback_decoder_sources:
"""
Convenience generator function to decode and stream any source of encoded audio data
(such as a network stream). Stream result is 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(output_format.value, nchannels, sample_rate)
decoder_config.ditherMode = dither.value
_callback_decoder_sources[id(source)] = source
source.userdata_ptr = ffi.new("char[]", struct.pack('q', id(source)))
decoder_init = {
FileFormat.UNKNOWN: lib.ma_decoder_init,
FileFormat.VORBIS: lib.ma_decoder_init_vorbis,
FileFormat.WAV: lib.ma_decoder_init_wav,
FileFormat.FLAC: lib.ma_decoder_init_flac,
FileFormat.MP3: lib.ma_decoder_init_mp3
}[source_format]
result = decoder_init(lib._internal_decoder_read_callback, lib._internal_decoder_seek_callback,
source.userdata_ptr, 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)
def on_close() -> None:
if id(source) in _callback_decoder_sources:
del _callback_decoder_sources[id(source)]