Spaces:
Running
Running
| # This file is part of audioread. | |
| # Copyright 2013, Adrian Sampson. | |
| # | |
| # Permission is hereby granted, free of charge, to any person obtaining | |
| # a copy of this software and associated documentation files (the | |
| # "Software"), to deal in the Software without restriction, including | |
| # without limitation the rights to use, copy, modify, merge, publish, | |
| # distribute, sublicense, and/or sell copies of the Software, and to | |
| # permit persons to whom the Software is furnished to do so, subject to | |
| # the following conditions: | |
| # | |
| # The above copyright notice and this permission notice shall be | |
| # included in all copies or substantial portions of the Software. | |
| """Decode audio files.""" | |
| from . import ffdec | |
| from .exceptions import DecodeError, NoBackendError | |
| from .version import version as __version__ # noqa | |
| from .base import AudioFile # noqa | |
| def _gst_available(): | |
| """Determine whether Gstreamer and the Python GObject bindings are | |
| installed. | |
| """ | |
| try: | |
| import gi | |
| except ImportError: | |
| return False | |
| try: | |
| gi.require_version('Gst', '1.0') | |
| except (ValueError, AttributeError): | |
| return False | |
| try: | |
| from gi.repository import Gst # noqa | |
| except ImportError: | |
| return False | |
| return True | |
| def _ca_available(): | |
| """Determines whether CoreAudio is available (i.e., we're running on | |
| Mac OS X). | |
| """ | |
| import ctypes.util | |
| lib = ctypes.util.find_library('AudioToolbox') | |
| return lib is not None | |
| def _mad_available(): | |
| """Determines whether the pymad bindings are available.""" | |
| try: | |
| import mad # noqa | |
| except ImportError: | |
| return False | |
| else: | |
| return True | |
| # A cache for the available backends. | |
| BACKENDS = [] | |
| def available_backends(flush_cache=False): | |
| """Returns a list of backends that are available on this system. | |
| The list of backends is cached after the first call. | |
| If the parameter `flush_cache` is set to `True`, then the cache | |
| will be flushed and the backend list will be reconstructed. | |
| """ | |
| if BACKENDS and not flush_cache: | |
| return BACKENDS | |
| # Standard-library WAV and AIFF readers. | |
| from . import rawread | |
| result = [rawread.RawAudioFile] | |
| # Core Audio. | |
| if _ca_available(): | |
| from . import macca | |
| result.append(macca.ExtAudioFile) | |
| # GStreamer. | |
| if _gst_available(): | |
| from . import gstdec | |
| result.append(gstdec.GstAudioFile) | |
| # MAD. | |
| if _mad_available(): | |
| from . import maddec | |
| result.append(maddec.MadAudioFile) | |
| # FFmpeg. | |
| if ffdec.available(): | |
| result.append(ffdec.FFmpegAudioFile) | |
| # Cache the backends we found | |
| BACKENDS[:] = result | |
| return BACKENDS | |
| def audio_open(path, backends=None): | |
| """Open an audio file using a library that is available on this | |
| system. | |
| The optional `backends` parameter can be a list of audio file | |
| classes to try opening the file with. If it is not provided, | |
| `audio_open` tries all available backends. If you call this function | |
| many times, you can avoid the cost of checking for available | |
| backends every time by calling `available_backends` once and passing | |
| the result to each `audio_open` call. | |
| If all backends fail to read the file, a NoBackendError exception is | |
| raised. | |
| """ | |
| if backends is None: | |
| backends = available_backends() | |
| for BackendClass in backends: | |
| try: | |
| return BackendClass(path) | |
| except DecodeError: | |
| pass | |
| # All backends failed! | |
| raise NoBackendError() | |