Source code for brownify.splitters

from abc import ABC, abstractmethod
from enum import Enum, auto
from typing import List

from spleeter import SpleeterError
from spleeter.separator import Separator

from brownify.errors import InvalidInputError, SplittingError


[docs]class AudioSplitter(ABC): """Abstract class for an object that splits audio files into sources AudioSplitter is the top of the class hierarchy for objects which can take in audio files and split them into multiple separated sources """ separator: Separator @abstractmethod def _init_separator(self) -> None: """Initialize the separator Each concrete implementation of a separator must implement this method to initialize its separator. """
[docs] @abstractmethod def get_channels(self) -> List[str]: """Get the list of named of channels that the splitter will create"""
[docs] def split(self, filename: str) -> None: """Split an audio file into multiple sources Args: filename (str): Path to the file which should be split into multiple sources Raises: SplittingError: If unable to perform the operation of splitting into multiple tracks """ try: self.separator.separate_to_file(filename, ".") except SpleeterError: raise SplittingError("Unable to split into separate tracks")
[docs]class AudioSplitter5Channel(AudioSplitter): """Split a file into bass, drums, piano, vocals, and other tracks AudioSplitter5Channel objects can split a single track into separate bass, drum, piano, vocals, and other tracks. It is useful when an audio source should be split into all of those tracks with the potential of a less clean separation than the other splitters with fewer tracks. """ CHANNELS = [ "bass", "drums", "other", "piano", "vocals", ] def __init__(self): self._init_separator() def _init_separator(self) -> None: self.separator = Separator("spleeter:5stems") # pragma: no cover
[docs] def get_channels(self) -> List[str]: return self.CHANNELS
[docs]class AudioSplitter4Channel(AudioSplitter): """Split a file into bass, drums, vocals, and other tracks AudioSplitter4Channel objects can split a single track into separate bass, drum, vocals, and other tracks. It is useful when an audio source should be split into all of those tracks with the potential of a less clean separation than the other splitters with fewer tracks. """ CHANNELS = [ "bass", "drums", "other", "vocals", ] def __init__(self): self._init_separator() def _init_separator(self) -> None: self.separator = Separator("spleeter:4stems") # pragma: no cover
[docs] def get_channels(self) -> List[str]: return self.CHANNELS
[docs]class AudioSplitter2Channel(AudioSplitter): """Split a file into vocal and other tracks AudioSplitter2Channel objects can split a single track into separate voice and other tracks. It may provide the cleanest track separation if only vocal isolation is desired. """ CHANNELS = [ "other", "vocals", ] def __init__(self): self._init_separator() def _init_separator(self) -> None: self.separator = Separator("spleeter:2stems") # pragma: no cover
[docs] def get_channels(self) -> List[str]: return self.CHANNELS
[docs]class AudioSplitterType(Enum): """Enumerate AudioSplitter types for the AudioSplitterFactory""" ONLY_VOCALS = auto() FOUR_STEM = auto() FIVE_STEM = auto()
[docs]class AudioSplitterFactory: """Factory class for creating AudioSplitter objects"""
[docs] @staticmethod def get_audio_splitter( audio_splitter_type: AudioSplitterType = AudioSplitterType.FIVE_STEM, ) -> AudioSplitter: """Method for getting AudioSplitter instances Args: audio_splitter_type (AudioSplitterType, optional): Type of AudioSplitter to create. See the class documentation of each type for assistance choosing. Defaults to AudioSplitterType.FIVE_STEM. Returns: AudioSplitter: A concrete instance of an AudioSplitter """ if audio_splitter_type == AudioSplitterType.ONLY_VOCALS: return AudioSplitter2Channel() elif audio_splitter_type == AudioSplitterType.FOUR_STEM: return AudioSplitter4Channel() elif audio_splitter_type == AudioSplitterType.FIVE_STEM: return AudioSplitter5Channel() else: raise InvalidInputError( f"Unknown splitter type provided: {audio_splitter_type}" )