From 556ef2121492d72398a988af1b38b55176f5973a Mon Sep 17 00:00:00 2001 From: Romain Date: Mon, 28 Oct 2019 14:12:13 +0100 Subject: [PATCH] Initial commit from private spleeter --- .gitignore | 112 +++++++ LICENSE | 21 ++ MANIFEST.in | 3 + Makefile | 30 ++ README.md | 64 +++- audio_example.mp3 | Bin 0 -> 262867 bytes conda/spleeter-cpu.yaml | 18 ++ conda/spleeter-gpu.yaml | 19 ++ configs/2stems/base_config.json | 28 ++ configs/4stems/base_config.json | 31 ++ configs/5stems/base_config.json | 31 ++ configs/musdb_config.json | 32 ++ configs/musdb_train.csv | 87 +++++ configs/musdb_validation.csv | 15 + docker/cpu.Dockerfile | 24 ++ docker/gpu.Dockerfile | 35 ++ docker/install_miniconda.sh | 13 + setup.py | 108 +++++++ spleeter/__init__.py | 18 ++ spleeter/__main__.py | 52 +++ spleeter/commands/__init__.py | 182 +++++++++++ spleeter/commands/evaluate.py | 154 +++++++++ spleeter/commands/separate.py | 180 +++++++++++ spleeter/commands/train.py | 98 ++++++ spleeter/dataset.py | 464 +++++++++++++++++++++++++++ spleeter/model/__init__.py | 397 +++++++++++++++++++++++ spleeter/model/functions/__init__.py | 27 ++ spleeter/model/functions/blstm.py | 76 +++++ spleeter/model/functions/unet.py | 201 ++++++++++++ spleeter/model/provider/__init__.py | 79 +++++ spleeter/model/provider/github.py | 73 +++++ spleeter/resources/2stems.json | 28 ++ spleeter/resources/4stems.json | 31 ++ spleeter/resources/5stems.json | 31 ++ spleeter/resources/__init__.py | 8 + spleeter/resources/musdb.json | 32 ++ spleeter/separator.py | 127 ++++++++ spleeter/utils/__init__.py | 8 + spleeter/utils/audio/__init__.py | 15 + spleeter/utils/audio/adapter.py | 144 +++++++++ spleeter/utils/audio/convertor.py | 88 +++++ spleeter/utils/audio/ffmpeg.py | 263 +++++++++++++++ spleeter/utils/audio/spectrogram.py | 128 ++++++++ spleeter/utils/configuration.py | 47 +++ spleeter/utils/estimator.py | 69 ++++ spleeter/utils/logging.py | 45 +++ spleeter/utils/tensor.py | 191 +++++++++++ 47 files changed, 3924 insertions(+), 3 deletions(-) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 MANIFEST.in create mode 100644 Makefile create mode 100644 audio_example.mp3 create mode 100644 conda/spleeter-cpu.yaml create mode 100644 conda/spleeter-gpu.yaml create mode 100644 configs/2stems/base_config.json create mode 100644 configs/4stems/base_config.json create mode 100644 configs/5stems/base_config.json create mode 100644 configs/musdb_config.json create mode 100644 configs/musdb_train.csv create mode 100644 configs/musdb_validation.csv create mode 100644 docker/cpu.Dockerfile create mode 100644 docker/gpu.Dockerfile create mode 100644 docker/install_miniconda.sh create mode 100644 setup.py create mode 100644 spleeter/__init__.py create mode 100644 spleeter/__main__.py create mode 100644 spleeter/commands/__init__.py create mode 100644 spleeter/commands/evaluate.py create mode 100644 spleeter/commands/separate.py create mode 100644 spleeter/commands/train.py create mode 100644 spleeter/dataset.py create mode 100644 spleeter/model/__init__.py create mode 100644 spleeter/model/functions/__init__.py create mode 100644 spleeter/model/functions/blstm.py create mode 100644 spleeter/model/functions/unet.py create mode 100644 spleeter/model/provider/__init__.py create mode 100644 spleeter/model/provider/github.py create mode 100644 spleeter/resources/2stems.json create mode 100644 spleeter/resources/4stems.json create mode 100644 spleeter/resources/5stems.json create mode 100644 spleeter/resources/__init__.py create mode 100644 spleeter/resources/musdb.json create mode 100644 spleeter/separator.py create mode 100644 spleeter/utils/__init__.py create mode 100644 spleeter/utils/audio/__init__.py create mode 100644 spleeter/utils/audio/adapter.py create mode 100644 spleeter/utils/audio/convertor.py create mode 100644 spleeter/utils/audio/ffmpeg.py create mode 100644 spleeter/utils/audio/spectrogram.py create mode 100644 spleeter/utils/configuration.py create mode 100644 spleeter/utils/estimator.py create mode 100644 spleeter/utils/logging.py create mode 100644 spleeter/utils/tensor.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..29d7036f --- /dev/null +++ b/.gitignore @@ -0,0 +1,112 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.vscode +.DS_Store +__pycache__ +**/reporting + +pretrained_models +docs/build +.vscode \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..484aef79 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019-present, Deezer SA. + +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. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 00000000..31960c79 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,3 @@ +include src/resources/*.json +include README.md +include LICENSE \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..989f5ce3 --- /dev/null +++ b/Makefile @@ -0,0 +1,30 @@ +# ======================================================= +# Build script for distribution packaging. +# +# @author Deezer Research +# @licence MIT Licence +# ======================================================= + +clean: + rm -Rf *.egg-info + rm -Rf dist + +build: + @echo "=== Build CPU bdist package" + @python3 setup.py sdist + @echo "=== CPU version checksum" + @openssl sha256 dist/*.tar.gz + +build-gpu: + @echo "=== Build GPU bdist package" + @python3 setup.py sdist --target gpu + @echo "=== GPU version checksum" + @openssl sha256 dist/*.tar.gz + +upload: + twine upload dist/* + +test-upload: + twine upload --repository-url https://test.pypi.org/legacy/ dist/* + +all: clean build build-gpu upload \ No newline at end of file diff --git a/README.md b/README.md index a5f6615a..b80f83dd 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,64 @@ -# spleeter + - +[![PyPI version](https://badge.fury.io/py/spleeter.svg)](https://badge.fury.io/py/spleeter) ![Conda](https://img.shields.io/conda/dn/conda-forge/spleeter) +## About -spleeter will be made available soon! +**Spleeter** is the [Deezer](https://www.deezer.com/) source separation library with pretrained models +written in [Python](https://www.python.org/) and uses [Tensorflow](tensorflow.org/). It makes it easy +to train source separation model (assuming you have a dataset of isolated sources), and provides +already trained state of the art model for performing various flavour of separation : + +* Vocals (singing voice) / accompaniment separation ([2 stems](https://github.com/deezer/spleeter/wiki/2.-Getting-started#using-2stems-model)) +* Vocals / drums / bass / other separation ([4 stems](https://github.com/deezer/spleeter/wiki/2.-Getting-started#using-4stems-model)) +* Vocals / drums / bass / piano / other separation ([5 stems](https://github.com/deezer/spleeter/wiki/2.-Getting-started#using-5stems-model)) + +2 stems and 4 stems models have state of the art performances on the +[musdb](https://sigsep.github.io/datasets/musdb.html) dataset. It is also very fast as +it can perform separation of audio files to 4 stems 100x faster than real-time when run on a *GPU*. +We designed it so you can use it straight from [command line](https://github.com/deezer/spleeter/wiki/2.-Getting-started#usage) +as well as directly in your own development pipeline as a +[Python library](https://github.com/deezer/spleeter/wiki/4.-API-Reference#separator) + +**Spleeter** can be installed with [Conda](https://github.com/deezer/spleeter/wiki/1.-Installation#using-conda), +with [pip](https://github.com/deezer/spleeter/wiki/1.-Installation#using-pip) or be used with +[Docker](https://github.com/deezer/spleeter/wiki/2.-Getting-started#using-docker-image). + +## Quick start + +Want to try it out ? Just clone the repository and install a +[Conda](https://github.com/deezer/spleeter/wiki/1.-Installation#using-conda) +environment to start separating audio file as follows: + +```bash +$ git clone https://github.com/Deezer/spleeter +$ conda env create -f spleeter/conda/spleeter-cpu.yaml +$ conda activate spleeter-cpu +$ spleeter separate -i spleeter/audio_example.mp3 -p spleeter:2stems -o output +``` +You should get two separated audio files (`vocals.wav` and `accompaniment.wav`) +in the `output/audio_example` folder. + +For a more detailed documentation, please check the [repository wiki](https://github.com/deezer/spleeter/wiki) + +## Reference +If you use **Spleeter** in your work, please cite: + +``` +@misc{spleeter2019, + title={Spleeter: A Fast And State-of-the Art Music Source Separation Tool With Pre-trained Models}, + author={Romain Hennequin and Anis Khlif and Felix Voituret and Manuel Moussallam}, + howpublished={Late-Breaking/Demo ISMIR 2019}, + month={November}, + year={2019} +} +``` + +## License +The code of **Spleeter** is MIT-licensed. + +## Note +This repository include a demo audio file `audio_example.mp3` which is an excerpt +from Slow Motion Dream by Steven M Bryant (c) copyright 2011 Licensed under a Creative +Commons Attribution (3.0) license. http://dig.ccmixter.org/files/stevieb357/34740 +Ft: CSoul,Alex Beroza & Robert Siekawitch diff --git a/audio_example.mp3 b/audio_example.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..cc91788843d20ae7af169d6e0f72c2c5658fdb39 GIT binary patch literal 262867 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

@-lpw6AxNed+fJcXUEA{QLu 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 ~/.bashrc && \ +echo "conda activate base" >> ~/.bashrc \ No newline at end of file diff --git a/setup.py b/setup.py new file mode 100644 index 00000000..e350564f --- /dev/null +++ b/setup.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python +# coding: utf8 + +""" Distribution script. """ + +import sys + +from os import path +from setuptools import setup + +__email__ = 'research@deezer.com' +__author__ = 'Deezer Research' +__license__ = 'MIT License' + +# Default project values. +project_name = 'spleeter' +project_version = '1.4.0' +device_target = 'cpu' +tensorflow_dependency = 'tensorflow' +tensorflow_version = '1.14.0' +here = path.abspath(path.dirname(__file__)) +readme_path = path.join(here, 'README.md') +with open(readme_path, 'r') as stream: + readme = stream.read() + +# Check if GPU target is specified. +if '--target' in sys.argv: + target_index = sys.argv.index('--target') + 1 + target = sys.argv[target_index].lower() + sys.argv.remove('--target') + sys.argv.pop(target_index) + +# GPU target compatibility check. +if device_target == 'gpu': + project_name = '{}-gpu'.format(project_name) + tensorflow_dependency = 'tensorflow-gpu' + +# Package setup entrypoint. +setup( + name=project_name, + version=project_version, + description=''' + The Deezer source separation library with + pretrained models based on tensorflow. + ''', + long_description=readme, + long_description_content_type='text/markdown', + author='Deezer Research', + author_email='research@deezer.com', + url='https://github.com/deezer/spleeter', + license='MIT License', + packages=[ + 'spleeter', + 'spleeter.commands', + 'spleeter.model', + 'spleeter.model.functions', + 'spleeter.model.provider', + 'spleeter.resources', + 'spleeter.utils', + 'spleeter.utils.audio', + ], + package_data={'spleeter.resources': ['*.json']}, + python_requires='>=3.6, <3.8', + include_package_data=True, + install_requires=[ + 'importlib_resources ; python_version<"3.7"', + 'musdb==0.3.1', + 'museval==0.3.0', + 'norbert==0.2.1', + 'pandas==0.25.1', + 'requests', + '{}=={}'.format(tensorflow_dependency, tensorflow_version), + ], + entry_points={ + 'console_scripts': ['spleeter=spleeter.__main__:entrypoint'] + }, + classifiers=[ + 'Environment :: Console', + 'Environment :: MacOS X', + 'Intended Audience :: Developers', + 'Intended Audience :: Information Technology', + 'Intended Audience :: Science/Research', + 'License :: OSI Approved :: MIT License', + 'Natural Language :: English', + 'Operating System :: MacOS', + 'Operating System :: Microsoft :: Windows', + 'Operating System :: POSIX :: Linux', + 'Operating System :: Unix', + 'Programming Language :: Python', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3 :: Only', + 'Programming Language :: Python :: Implementation :: CPython', + 'Topic :: Artistic Software', + 'Topic :: Multimedia', + 'Topic :: Multimedia :: Sound/Audio', + 'Topic :: Multimedia :: Sound/Audio :: Analysis', + 'Topic :: Multimedia :: Sound/Audio :: Conversion', + 'Topic :: Multimedia :: Sound/Audio :: Sound Synthesis', + 'Topic :: Scientific/Engineering', + 'Topic :: Scientific/Engineering :: Artificial Intelligence', + 'Topic :: Scientific/Engineering :: Information Analysis', + 'Topic :: Software Development', + 'Topic :: Software Development :: Libraries', + 'Topic :: Software Development :: Libraries :: Python Modules', + 'Topic :: Utilities'] +) diff --git a/spleeter/__init__.py b/spleeter/__init__.py new file mode 100644 index 00000000..e3693719 --- /dev/null +++ b/spleeter/__init__.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python +# coding: utf8 + +""" + Spleeter is the Deezer source separation library with pretrained models. + The library is based on Tensorflow: + + - It provides already trained model for performing separation. + - It makes it easy to train source separation model with tensorflow + (provided you have a dataset of isolated sources). + + This module allows to interact easily from command line with Spleeter + by providing train, evaluation and source separation action. +""" + +__email__ = 'research@deezer.com' +__author__ = 'Deezer Research' +__license__ = 'MIT License' diff --git a/spleeter/__main__.py b/spleeter/__main__.py new file mode 100644 index 00000000..fde52924 --- /dev/null +++ b/spleeter/__main__.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python +# coding: utf8 + +""" + Python oneliner script usage. + + USAGE: python -m spleeter {train,evaluate,separate} ... +""" + +import sys +import warnings + +from .commands import create_argument_parser +from .utils.configuration import load_configuration +from .utils.logging import enable_logging, enable_verbose_logging + +__email__ = 'research@deezer.com' +__author__ = 'Deezer Research' +__license__ = 'MIT License' + + +def main(argv): + """ Spleeter runner. Parse provided command line arguments + and run entrypoint for required command (either train, + evaluate or separate). + + :param argv: Provided command line arguments. + """ + parser = create_argument_parser() + arguments = parser.parse_args(argv[1:]) + if arguments.verbose: + enable_verbose_logging() + else: + enable_logging() + if arguments.command == 'separate': + from .commands.separate import entrypoint + elif arguments.command == 'train': + from .commands.train import entrypoint + elif arguments.command == 'evaluate': + from .commands.evaluate import entrypoint + params = load_configuration(arguments.params_filename) + entrypoint(arguments, params) + + +def entrypoint(): + """ Command line entrypoint. """ + warnings.filterwarnings('ignore') + main(sys.argv) + + +if __name__ == '__main__': + entrypoint() diff --git a/spleeter/commands/__init__.py b/spleeter/commands/__init__.py new file mode 100644 index 00000000..25773998 --- /dev/null +++ b/spleeter/commands/__init__.py @@ -0,0 +1,182 @@ +#!/usr/bin/env python +# coding: utf8 + +""" This modules provides spleeter command as well as CLI parsing methods. """ + +import json + +from argparse import ArgumentParser +from tempfile import gettempdir +from os.path import exists, join + +__email__ = 'research@deezer.com' +__author__ = 'Deezer Research' +__license__ = 'MIT License' + +# -i opt specification. +OPT_INPUT = { + 'dest': 'audio_filenames', + 'nargs': '+', + 'help': 'List of input audio filenames', + 'required': True +} + +# -o opt specification. +OPT_OUTPUT = { + 'dest': 'output_path', + 'default': join(gettempdir(), 'separated_audio'), + 'help': 'Path of the output directory to write audio files in' +} + +# -p opt specification. +OPT_PARAMS = { + 'dest': 'params_filename', + 'default': 'spleeter:2stems', + 'type': str, + 'action': 'store', + 'help': 'JSON filename that contains params' +} + +# -n opt specification. +OPT_OUTPUT_NAMING = { + 'dest': 'output_naming', + 'default': 'filename', + 'choices': ('directory', 'filename'), + 'help': ( + 'Choice for naming the output base path: ' + '"filename" (use the input filename, i.e ' + '/path/to/audio/mix.wav will be separated to ' + '/mix/.wav, ' + '/mix/.wav...) or ' + '"directory" (use the name of the input last level' + ' directory, for instance /path/to/audio/mix.wav ' + 'will be separated to /audio/.wav' + ', /audio/.wav)') +} + +# -d opt specification (separate). +OPT_DURATION = { + 'dest': 'max_duration', + 'type': float, + 'default': 600., + 'help': ( + 'Set a maximum duration for processing audio ' + '(only separate max_duration first seconds of ' + 'the input file)') +} + +# -c opt specification. +OPT_CODEC = { + 'dest': 'audio_codec', + 'choices': ('wav', 'mp3', 'ogg', 'm4a', 'wma', 'flac'), + 'default': 'wav', + 'help': 'Audio codec to be used for the separated output' +} + +# -m opt specification. +OPT_MWF = { + 'dest': 'MWF', + 'action': 'store_const', + 'const': True, + 'default': False, + 'help': 'Whether to use multichannel Wiener filtering for separation', +} + +# --mus_dir opt specification. +OPT_MUSDB = { + 'dest': 'mus_dir', + 'type': str, + 'required': True, + 'help': 'Path to folder with musDB' +} + +# -d opt specification (train). +OPT_DATA = { + 'dest': 'audio_path', + 'type': str, + 'required': True, + 'help': 'Path of the folder containing audio data for training' +} + +# -a opt specification. +OPT_ADAPTER = { + 'dest': 'audio_adapter', + 'type': str, + 'help': 'Name of the audio adapter to use for audio I/O' +} + +# -a opt specification. +OPT_VERBOSE = { + 'action': 'store_true', + 'help': 'Shows verbose logs' +} + + +def _add_common_options(parser): + """ Add common option to the given parser. + + :param parser: Parser to add common opt to. + """ + parser.add_argument('-a', '--adapter', **OPT_ADAPTER) + parser.add_argument('-p', '--params_filename', **OPT_PARAMS) + parser.add_argument('--verbose', **OPT_VERBOSE) + + +def _create_train_parser(parser_factory): + """ Creates an argparser for training command + + :param parser_factory: Factory to use to create parser instance. + :returns: Created and configured parser. + """ + parser = parser_factory('train', help='Train a source separation model') + _add_common_options(parser) + parser.add_argument('-d', '--data', **OPT_DATA) + return parser + + +def _create_evaluate_parser(parser_factory): + """ Creates an argparser for evaluation command + + :param parser_factory: Factory to use to create parser instance. + :returns: Created and configured parser. + """ + parser = parser_factory( + 'evaluate', + help='Evaluate a model on the musDB test dataset') + _add_common_options(parser) + parser.add_argument('-o', '--output_path', **OPT_OUTPUT) + parser.add_argument('--mus_dir', **OPT_MUSDB) + parser.add_argument('-m', '--mwf', **OPT_MWF) + return parser + + +def _create_separate_parser(parser_factory): + """ Creates an argparser for separation command + + :param parser_factory: Factory to use to create parser instance. + :returns: Created and configured parser. + """ + parser = parser_factory('separate', help='Separate audio files') + _add_common_options(parser) + parser.add_argument('-i', '--audio_filenames', **OPT_INPUT) + parser.add_argument('-o', '--output_path', **OPT_OUTPUT) + parser.add_argument('-n', '--output_naming', **OPT_OUTPUT_NAMING) + parser.add_argument('-d', '--max_duration', **OPT_DURATION) + parser.add_argument('-c', '--audio_codec', **OPT_CODEC) + parser.add_argument('-m', '--mwf', **OPT_MWF) + return parser + + +def create_argument_parser(): + """ Creates overall command line parser for Spleeter. + + :returns: Created argument parser. + """ + parser = ArgumentParser(prog='python -m spleeter') + subparsers = parser.add_subparsers() + subparsers.dest = 'command' + subparsers.required = True + _create_separate_parser(subparsers.add_parser) + _create_train_parser(subparsers.add_parser) + _create_evaluate_parser(subparsers.add_parser) + return parser diff --git a/spleeter/commands/evaluate.py b/spleeter/commands/evaluate.py new file mode 100644 index 00000000..dc990ada --- /dev/null +++ b/spleeter/commands/evaluate.py @@ -0,0 +1,154 @@ +#!/usr/bin/env python +# coding: utf8 + +""" + Entrypoint provider for performing model evaluation. + + Evaluation is performed against musDB dataset. + + USAGE: python -m spleeter evaluate \ + -p /path/to/params \ + -o /path/to/output/dir \ + [-m] \ + --mus_dir /path/to/musdb dataset +""" + +import json + +from argparse import Namespace +from itertools import product +from glob import glob +from os.path import join, exists + +# pylint: disable=import-error +import musdb +import museval +import numpy as np +import pandas as pd +# pylint: enable=import-error + +from .separate import entrypoint as separate_entrypoint +from ..utils.logging import get_logger + +__email__ = 'research@deezer.com' +__author__ = 'Deezer Research' +__license__ = 'MIT License' + +_SPLIT = 'test' +_MIXTURE = 'mixture.wav' +_NAMING = 'directory' +_AUDIO_DIRECTORY = 'audio' +_METRICS_DIRECTORY = 'metrics' +_INSTRUMENTS = ('vocals', 'drums', 'bass', 'other') +_METRICS = ('SDR', 'SAR', 'SIR', 'ISR') + + +def _separate_evaluation_dataset(arguments, musdb_root_directory, params): + """ Performs audio separation on the musdb dataset from + the given directory and params. + + :param arguments: Entrypoint arguments. + :param musdb_root_directory: Directory to retrieve dataset from. + :param params: Spleeter configuration to apply to separation. + :returns: Separation output directory path. + """ + songs = glob(join(musdb_root_directory, _SPLIT, '*/')) + mixtures = [join(song, _MIXTURE) for song in songs] + audio_output_directory = join( + arguments.output_path, + _AUDIO_DIRECTORY) + separate_entrypoint( + Namespace( + audio_adapter=arguments.audio_adapter, + audio_filenames=mixtures, + audio_codec='wav', + output_path=join(audio_output_directory, _SPLIT), + output_naming=_NAMING, + max_duration=600., + MWF=arguments.MWF, + verbose=arguments.verbose), + params) + return audio_output_directory + + +def _compute_musdb_metrics( + arguments, + musdb_root_directory, + audio_output_directory): + """ Generates musdb metrics fro previsouly computed audio estimation. + + :param arguments: Entrypoint arguments. + :param audio_output_directory: Directory to get audio estimation from. + :returns: Path of generated metrics directory. + """ + metrics_output_directory = join( + arguments.output_path, + _METRICS_DIRECTORY) + get_logger().info('Starting musdb evaluation (this could be long) ...') + dataset = musdb.DB( + root=musdb_root_directory, + is_wav=True, + subsets=[_SPLIT]) + museval.eval_mus_dir( + dataset=dataset, + estimates_dir=audio_output_directory, + output_dir=metrics_output_directory) + get_logger().info('musdb evaluation done') + return metrics_output_directory + + +def _compile_metrics(metrics_output_directory): + """ Compiles metrics from given directory and returns + results as dict. + + :param metrics_output_directory: Directory to get metrics from. + :returns: Compiled metrics as dict. + """ + songs = glob(join(metrics_output_directory, 'test/*.json')) + index = pd.MultiIndex.from_tuples( + product(_INSTRUMENTS, _METRICS), + names=['instrument', 'metric']) + pd.DataFrame([], index=['config1', 'config2'], columns=index) + metrics = { + instrument: {k: [] for k in _METRICS} + for instrument in _INSTRUMENTS} + for song in songs: + with open(song, 'r') as stream: + data = json.load(stream) + for target in data['targets']: + instrument = target['name'] + for metric in _METRICS: + sdr_med = np.median([ + frame['metrics'][metric] + for frame in target['frames'] + if not np.isnan(frame['metrics'][metric])]) + metrics[instrument][metric].append(sdr_med) + return metrics + + +def entrypoint(arguments, params): + """ Command entrypoint. + + :param arguments: Command line parsed argument as argparse.Namespace. + :param params: Deserialized JSON configuration file provided in CLI args. + """ + # Parse and check musdb directory. + musdb_root_directory = arguments.mus_dir + if not exists(musdb_root_directory): + raise IOError(f'musdb directory {musdb_root_directory} not found') + # Separate musdb sources. + audio_output_directory = _separate_evaluation_dataset( + arguments, + musdb_root_directory, + params) + # Compute metrics with musdb. + metrics_output_directory = _compute_musdb_metrics( + arguments, + musdb_root_directory, + audio_output_directory) + # Compute and pretty print median metrics. + metrics = _compile_metrics(metrics_output_directory) + for instrument, metric in metrics.items(): + get_logger().info('%s:', instrument) + for metric, value in metric.items(): + get_logger().info('%s: %s', metric, f'{np.median(value):.3f}') diff --git a/spleeter/commands/separate.py b/spleeter/commands/separate.py new file mode 100644 index 00000000..0098351f --- /dev/null +++ b/spleeter/commands/separate.py @@ -0,0 +1,180 @@ +#!/usr/bin/env python +# coding: utf8 + +""" + Entrypoint provider for performing source separation. + + USAGE: python -m spleeter separate \ + -p /path/to/params \ + -i inputfile1 inputfile2 ... inputfilen + -o /path/to/output/dir \ + -i /path/to/audio1.wav /path/to/audio2.mp3 +""" + +from multiprocessing import Pool +from os.path import isabs, join, split, splitext +from tempfile import gettempdir + +# pylint: disable=import-error +import tensorflow as tf +import numpy as np +# pylint: enable=import-error + +from ..utils.audio.adapter import get_audio_adapter +from ..utils.audio.convertor import to_n_channels +from ..utils.estimator import create_estimator +from ..utils.tensor import set_tensor_shape + +__email__ = 'research@deezer.com' +__author__ = 'Deezer Research' +__license__ = 'MIT License' + + +def get_dataset(audio_adapter, filenames_and_crops, sample_rate, n_channels): + """" + Build a tensorflow dataset of waveform from a filename list wit crop + information. + + Params: + - audio_adapter: An AudioAdapter instance to load audio from. + - filenames_and_crops: list of (audio_filename, start, duration) + tuples separation is performed on each filaneme + from start (in seconds) to start + duration + (in seconds). + - sample_rate: audio sample_rate of the input and output audio + signals + - n_channels: int, number of channels of the input and output + audio signals + + Returns + A tensorflow dataset of waveform to feed a tensorflow estimator in + predict mode. + """ + filenames, starts, ends = list(zip(*filenames_and_crops)) + dataset = tf.data.Dataset.from_tensor_slices({ + 'audio_id': list(filenames), + 'start': list(starts), + 'end': list(ends) + }) + # Load waveform. + dataset = dataset.map( + lambda sample: dict( + sample, + **audio_adapter.load_tf_waveform( + sample['audio_id'], + sample_rate=sample_rate, + offset=sample['start'], + duration=sample['end'] - sample['start'])), + num_parallel_calls=2) + # Filter out error. + dataset = dataset.filter( + lambda sample: tf.logical_not(sample['waveform_error'])) + # Convert waveform to the right number of channels. + dataset = dataset.map( + lambda sample: dict( + sample, + waveform=to_n_channels(sample['waveform'], n_channels))) + # Set number of channels (required for the model). + dataset = dataset.map( + lambda sample: dict( + sample, + waveform=set_tensor_shape(sample['waveform'], (None, n_channels)))) + return dataset + + +def process_audio( + audio_adapter, + filenames_and_crops, estimator, output_path, + sample_rate, n_channels, codec, output_naming): + """ + Perform separation on a list of audio ids. + + Params: + - audio_adapter: Audio adapter to use for audio I/O. + - filenames_and_crops: list of (audio_filename, start, duration) + tuples separation is performed on each filaneme + from start (in seconds) to start + duration + (in seconds). + - estimator: the tensorflow estimator that performs the + source separation. + - output_path: output_path where to export separated files. + - sample_rate: audio sample_rate of the input and output audio + signals + - n_channels: int, number of channels of the input and output + audio signals + - codec: string codec to be used for export (could be + "wav", "mp3", "ogg", "m4a") could be anything + supported by ffmpeg. + - output_naming: string (= "filename" of "directory") + naming convention for output. + for an input file /path/to/audio/input_file.wav: + * if output_naming is equal to "filename": + output files will be put in the directory /input_file + (/input_file/., + /input_file/....). + * if output_naming is equal to "directory": + output files will be put in the directory /audio/ + (/audio/., + /audio/....) + Use "directory" when separating the MusDB dataset. + + """ + # Get estimator + prediction = estimator.predict( + lambda: get_dataset( + audio_adapter, + filenames_and_crops, + sample_rate, + n_channels), + yield_single_examples=False) + # initialize pool for audio export + pool = Pool(16) + tasks = [] + for sample in prediction: + sample_filename = sample.pop('audio_id', 'unknown_filename').decode() + input_directory, input_filename = split(sample_filename) + if output_naming == 'directory': + output_dirname = split(input_directory)[1] + elif output_naming == 'filename': + output_dirname = splitext(input_filename)[0] + else: + raise ValueError(f'Unknown output naming {output_naming}') + for instrument, waveform in sample.items(): + filename = join( + output_path, + output_dirname, + f'{instrument}.{codec}') + tasks.append( + pool.apply_async( + audio_adapter.save, + (filename, waveform, sample_rate, codec))) + # Wait for everything to be written + for task in tasks: + task.wait(timeout=20) + + +def entrypoint(arguments, params): + """ Command entrypoint. + + :param arguments: Command line parsed argument as argparse.Namespace. + :param params: Deserialized JSON configuration file provided in CLI args. + """ + audio_adapter = get_audio_adapter(arguments.audio_adapter) + filenames = arguments.audio_filenames + output_path = arguments.output_path + max_duration = arguments.max_duration + audio_codec = arguments.audio_codec + output_naming = arguments.output_naming + estimator = create_estimator(params, arguments.MWF) + filenames_and_crops = [ + (filename, 0., max_duration) + for filename in filenames] + process_audio( + audio_adapter, + filenames_and_crops, + estimator, + output_path, + params['sample_rate'], + params['n_channels'], + codec=audio_codec, + output_naming=output_naming) diff --git a/spleeter/commands/train.py b/spleeter/commands/train.py new file mode 100644 index 00000000..2814ae67 --- /dev/null +++ b/spleeter/commands/train.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python +# coding: utf8 + +""" + Entrypoint provider for performing model training. + + USAGE: python -m spleeter train -p /path/to/params +""" + +from functools import partial + +# pylint: disable=import-error +import tensorflow as tf +# pylint: enable=import-error + +from ..dataset import get_training_dataset, get_validation_dataset +from ..model import model_fn +from ..utils.audio.adapter import get_audio_adapter +from ..utils.logging import get_logger + +__email__ = 'research@deezer.com' +__author__ = 'Deezer Research' +__license__ = 'MIT License' + + +def _create_estimator(params): + """ Creates estimator. + + :param params: TF params to build estimator from. + :returns: Built estimator. + """ + session_config = tf.compat.v1.ConfigProto() + session_config.gpu_options.per_process_gpu_memory_fraction = 0.45 + estimator = tf.estimator.Estimator( + model_fn=model_fn, + model_dir=params['model_dir'], + params=params, + config=tf.estimator.RunConfig( + save_checkpoints_steps=params['save_checkpoints_steps'], + tf_random_seed=params['random_seed'], + save_summary_steps=params['save_summary_steps'], + session_config=session_config, + log_step_count_steps=10, + keep_checkpoint_max=2)) + return estimator + + +def _create_train_spec(params, audio_adapter, audio_path): + """ Creates train spec. + + :param params: TF params to build spec from. + :returns: Built train spec. + """ + input_fn = partial(get_training_dataset, params, audio_adapter, audio_path) + train_spec = tf.estimator.TrainSpec( + input_fn=input_fn, + max_steps=params['train_max_steps']) + return train_spec + + +def _create_evaluation_spec(params, audio_adapter, audio_path): + """ Setup eval spec evaluating ever n seconds + + :param params: TF params to build spec from. + :returns: Built evaluation spec. + """ + input_fn = partial( + get_validation_dataset, + params, + audio_adapter, + audio_path) + evaluation_spec = tf.estimator.EvalSpec( + input_fn=input_fn, + steps=None, + throttle_secs=params['throttle_secs']) + return evaluation_spec + + +def entrypoint(arguments, params): + """ Command entrypoint. + + :param arguments: Command line parsed argument as argparse.Namespace. + :param params: Deserialized JSON configuration file provided in CLI args. + """ + audio_adapter = get_audio_adapter(arguments.audio_adapter) + audio_path = arguments.audio_path + estimator = _create_estimator(params) + train_spec = _create_train_spec(params, audio_adapter, audio_path) + evaluation_spec = _create_evaluation_spec( + params, + audio_adapter, + audio_path) + get_logger().info('Start model training') + tf.estimator.train_and_evaluate( + estimator, + train_spec, + evaluation_spec) + get_logger().info('Model training done') diff --git a/spleeter/dataset.py b/spleeter/dataset.py new file mode 100644 index 00000000..dc656528 --- /dev/null +++ b/spleeter/dataset.py @@ -0,0 +1,464 @@ +#!/usr/bin/env python +# coding: utf8 + +""" + Module for building data preprocessing pipeline using the tensorflow data + API. + Data preprocessing such as audio loading, spectrogram computation, cropping, + feature caching or data augmentation is done using a tensorflow dataset object + that output a tuple (input_, output) where: + - input_ is a dictionary with a single key that contains the (batched) mix + spectrogram of audio samples + - output is a dictionary of spectrogram of the isolated tracks (ground truth) + +""" + +import time +import os +from os.path import exists, join, sep as SEPARATOR + +# pylint: disable=import-error +import pandas as pd +import numpy as np +import tensorflow as tf +# pylint: enable=import-error + +from .utils.audio.convertor import ( + db_uint_spectrogram_to_gain, + spectrogram_to_db_uint) +from .utils.audio.spectrogram import ( + compute_spectrogram_tf, + random_pitch_shift, + random_time_stretch) +from .utils.logging import get_logger +from .utils.tensor import ( + check_tensor_shape, + dataset_from_csv, + set_tensor_shape, + sync_apply) + +__email__ = 'research@deezer.com' +__author__ = 'Deezer Research' +__license__ = 'MIT License' + +# Default datasets path parameter to use. +DEFAULT_DATASETS_PATH = join( + 'audio_database', + 'separated_sources', + 'experiments', + 'karaoke_vocal_extraction', + 'tensorflow_experiment' +) + +# Default audio parameters to use. +DEFAULT_AUDIO_PARAMS = { + 'instrument_list': ('vocals', 'accompaniment'), + 'mix_name': 'mix', + 'sample_rate': 44100, + 'frame_length': 4096, + 'frame_step': 1024, + 'T': 512, + 'F': 1024 +} + + +def get_training_dataset(audio_params, audio_adapter, audio_path): + """ Builds training dataset. + + :param audio_params: Audio parameters. + :param audio_adapter: Adapter to load audio from. + :param audio_path: Path of directory containing audio. + :returns: Built dataset. + """ + builder = DatasetBuilder( + audio_params, + audio_adapter, + audio_path, + chunk_duration=audio_params.get('chunk_duration', 20.0), + random_seed=audio_params.get('random_seed', 0)) + return builder.build( + audio_params.get('train_csv'), + cache_directory=audio_params.get('training_cache'), + batch_size=audio_params.get('batch_size'), + n_chunks_per_song=audio_params.get('n_chunks_per_song', 2), + random_data_augmentation=False, + convert_to_uint=True, + wait_for_cache=False) + + +def get_validation_dataset(audio_params, audio_adapter, audio_path): + """ Builds validation dataset. + + :param audio_params: Audio parameters. + :param audio_adapter: Adapter to load audio from. + :param audio_path: Path of directory containing audio. + :returns: Built dataset. + """ + builder = DatasetBuilder( + audio_params, + audio_adapter, + audio_path, + chunk_duration=12.0) + return builder.build( + audio_params.get('validation_csv'), + batch_size=audio_params.get('batch_size'), + cache_directory=audio_params.get('training_cache'), + convert_to_uint=True, + infinite_generator=False, + n_chunks_per_song=1, + # should not perform data augmentation for eval: + random_data_augmentation=False, + random_time_crop=False, + shuffle=False, + ) + + +class InstrumentDatasetBuilder(object): + """ Instrument based filter and mapper provider. """ + + def __init__(self, parent, instrument): + """ Default constructor. + + :param parent: Parent dataset builder. + :param instrument: Target instrument. + """ + self._parent = parent + self._instrument = instrument + self._spectrogram_key = f'{instrument}_spectrogram' + self._min_spectrogram_key = f'min_{instrument}_spectrogram' + self._max_spectrogram_key = f'max_{instrument}_spectrogram' + + def load_waveform(self, sample): + """ Load waveform for given sample. """ + return dict(sample, **self._parent._audio_adapter.load_tf_waveform( + sample[f'{self._instrument}_path'], + offset=sample['start'], + duration=self._parent._chunk_duration, + sample_rate=self._parent._sample_rate, + waveform_name='waveform')) + + def compute_spectrogram(self, sample): + """ Compute spectrogram of the given sample. """ + return dict(sample, **{ + self._spectrogram_key: compute_spectrogram_tf( + sample['waveform'], + frame_length=self._parent._frame_length, + frame_step=self._parent._frame_step, + spec_exponent=1., + window_exponent=1.)}) + + def filter_frequencies(self, sample): + """ """ + return dict(sample, **{ + self._spectrogram_key: + sample[self._spectrogram_key][:, :self._parent._F, :]}) + + def convert_to_uint(self, sample): + """ Convert given sample from float to unit. """ + return dict(sample, **spectrogram_to_db_uint( + sample[self._spectrogram_key], + tensor_key=self._spectrogram_key, + min_key=self._min_spectrogram_key, + max_key=self._max_spectrogram_key)) + + def filter_infinity(self, sample): + """ Filter infinity sample. """ + return tf.logical_not( + tf.math.is_inf( + sample[self._min_spectrogram_key])) + + def convert_to_float32(self, sample): + """ Convert given sample from unit to float. """ + return dict(sample, **{ + self._spectrogram_key: db_uint_spectrogram_to_gain( + sample[self._spectrogram_key], + sample[self._min_spectrogram_key], + sample[self._max_spectrogram_key])}) + + def time_crop(self, sample): + """ """ + def start(sample): + """ mid_segment_start """ + return tf.cast( + tf.maximum( + tf.shape(sample[self._spectrogram_key])[0] + / 2 - self._parent._T / 2, 0), + tf.int32) + return dict(sample, **{ + self._spectrogram_key: sample[self._spectrogram_key][ + start(sample):start(sample) + self._parent._T, :, :]}) + + def filter_shape(self, sample): + """ Filter badly shaped sample. """ + return check_tensor_shape( + sample[self._spectrogram_key], ( + self._parent._T, self._parent._F, 2)) + + def reshape_spectrogram(self, sample): + """ """ + return dict(sample, **{ + self._spectrogram_key: set_tensor_shape( + sample[self._spectrogram_key], + (self._parent._T, self._parent._F, 2))}) + + +class DatasetBuilder(object): + """ + """ + + # Margin at beginning and end of songs in seconds. + MARGIN = 0.5 + + # Wait period for cache (in seconds). + WAIT_PERIOD = 60 + + def __init__( + self, + audio_params, audio_adapter, audio_path, + random_seed=0, chunk_duration=20.0): + """ Default constructor. + + NOTE: Probably need for AudioAdapter. + + :param audio_params: Audio parameters to use. + :param audio_adapter: Audio adapter to use. + :param audio_path: + :param random_seed: + :param chunk_duration: + """ + # Length of segment in frames (if fs=22050 and + # frame_step=512, then T=512 corresponds to 11.89s) + self._T = audio_params['T'] + # Number of frequency bins to be used (should + # be less than frame_length/2 + 1) + self._F = audio_params['F'] + self._sample_rate = audio_params['sample_rate'] + self._frame_length = audio_params['frame_length'] + self._frame_step = audio_params['frame_step'] + self._mix_name = audio_params['mix_name'] + self._instruments = [self._mix_name] + audio_params['instrument_list'] + self._instrument_builders = None + self._chunk_duration = chunk_duration + self._audio_adapter = audio_adapter + self._audio_params = audio_params + self._audio_path = audio_path + self._random_seed = random_seed + + def expand_path(self, sample): + """ Expands audio paths for the given sample. """ + return dict(sample, **{f'{instrument}_path': tf.string_join( + (self._audio_path, sample[f'{instrument}_path']), SEPARATOR) + for instrument in self._instruments}) + + def filter_error(self, sample): + """ Filter errored sample. """ + return tf.logical_not(sample['waveform_error']) + + def filter_waveform(self, sample): + """ Filter waveform from sample. """ + return {k: v for k, v in sample.items() if not k == 'waveform'} + + def harmonize_spectrogram(self, sample): + """ Ensure same size for vocals and mix spectrograms. """ + def _reduce(sample): + return tf.reduce_min([ + tf.shape(sample[f'{instrument}_spectrogram'])[0] + for instrument in self._instruments]) + return dict(sample, **{ + f'{instrument}_spectrogram': + sample[f'{instrument}_spectrogram'][:_reduce(sample), :, :] + for instrument in self._instruments}) + + def filter_short_segments(self, sample): + """ Filter out too short segment. """ + return tf.reduce_any([ + tf.shape(sample[f'{instrument}_spectrogram'])[0] >= self._T + for instrument in self._instruments]) + + def random_time_crop(self, sample): + """ Random time crop of 11.88s. """ + return dict(sample, **sync_apply({ + f'{instrument}_spectrogram': sample[f'{instrument}_spectrogram'] + for instrument in self._instruments}, + lambda x: tf.image.random_crop( + x, (self._T, len(self._instruments) * self._F, 2), + seed=self._random_seed))) + + def random_time_stretch(self, sample): + """ Randomly time stretch the given sample. """ + return dict(sample, **sync_apply({ + f'{instrument}_spectrogram': + sample[f'{instrument}_spectrogram'] + for instrument in self._instruments}, + lambda x: random_time_stretch( + x, factor_min=0.9, factor_max=1.1))) + + def random_pitch_shift(self, sample): + """ Randomly pitch shift the given sample. """ + return dict(sample, **sync_apply({ + f'{instrument}_spectrogram': + sample[f'{instrument}_spectrogram'] + for instrument in self._instruments}, + lambda x: random_pitch_shift( + x, shift_min=-1.0, shift_max=1.0), concat_axis=0)) + + def map_features(self, sample): + """ Select features and annotation of the given sample. """ + input_ = { + f'{self._mix_name}_spectrogram': + sample[f'{self._mix_name}_spectrogram']} + output = { + f'{instrument}_spectrogram': sample[f'{instrument}_spectrogram'] + for instrument in self._audio_params['instrument_list']} + return (input_, output) + + def compute_segments(self, dataset, n_chunks_per_song): + """ Computes segments for each song of the dataset. + + :param dataset: Dataset to compute segments for. + :param n_chunks_per_song: Number of segment per song to compute. + :returns: Segmented dataset. + """ + if n_chunks_per_song <= 0: + raise ValueError('n_chunks_per_song must be positif') + datasets = [] + for k in range(n_chunks_per_song): + if n_chunks_per_song > 1: + datasets.append( + dataset.map(lambda sample: dict(sample, start=tf.maximum( + k * ( + sample['duration'] - self._chunk_duration - 2 + * self.MARGIN) / (n_chunks_per_song - 1) + + self.MARGIN, 0)))) + elif n_chunks_per_song == 1: # Take central segment. + datasets.append( + dataset.map(lambda sample: dict(sample, start=tf.maximum( + sample['duration'] / 2 - self._chunk_duration / 2, + 0)))) + dataset = datasets[-1] + for d in datasets[:-1]: + dataset = dataset.concatenate(d) + return dataset + + @property + def instruments(self): + """ Instrument dataset builder generator. + + :yield InstrumentBuilder instance. + """ + if self._instrument_builders is None: + self._instrument_builders = [] + for instrument in self._instruments: + self._instrument_builders.append( + InstrumentDatasetBuilder(self, instrument)) + for builder in self._instrument_builders: + yield builder + + def cache(self, dataset, cache, wait): + """ Cache the given dataset if cache is enabled. Eventually waits for + cache to be available (useful if another process is already computing + cache) if provided wait flag is True. + + :param dataset: Dataset to be cached if cache is required. + :param cache: Path of cache directory to be used, None if no cache. + :param wait: If caching is enabled, True is cache should be waited. + :returns: Cached dataset if needed, original dataset otherwise. + """ + if cache is not None: + if wait: + while not exists(f'{cache}.index'): + get_logger().info( + 'Cache not available, wait %s', + self.WAIT_PERIOD) + time.sleep(self.WAIT_PERIOD) + cache_path = os.path.split(cache)[0] + os.makedirs(cache_path, exist_ok=True) + return dataset.cache(cache) + return dataset + + def build( + self, csv_path, + batch_size=8, shuffle=True, convert_to_uint=True, + random_data_augmentation=False, random_time_crop=True, + infinite_generator=True, cache_directory=None, + wait_for_cache=False, num_parallel_calls=4, n_chunks_per_song=2,): + """ + TO BE DOCUMENTED. + """ + dataset = dataset_from_csv(csv_path) + dataset = self.compute_segments(dataset, n_chunks_per_song) + # Shuffle data + if shuffle: + dataset = dataset.shuffle( + buffer_size=200000, + seed=self._random_seed, + # useless since it is cached : + reshuffle_each_iteration=True) + # Expand audio path. + dataset = dataset.map(self.expand_path) + # Load waveform, compute spectrogram, and filtering error, + # K bins frequencies, and waveform. + N = num_parallel_calls + for instrument in self.instruments: + dataset = ( + dataset + .map(instrument.load_waveform, num_parallel_calls=N) + .filter(self.filter_error) + .map(instrument.compute_spectrogram, num_parallel_calls=N) + .map(instrument.filter_frequencies)) + dataset = dataset.map(self.filter_waveform) + # Convert to uint before caching in order to save space. + if convert_to_uint: + for instrument in self.instruments: + dataset = dataset.map(instrument.convert_to_uint) + dataset = self.cache(dataset, cache_directory, wait_for_cache) + # Check for INFINITY (should not happen) + for instrument in self.instruments: + dataset = dataset.filter(instrument.filter_infinity) + # Repeat indefinitly + if infinite_generator: + dataset = dataset.repeat(count=-1) + # Ensure same size for vocals and mix spectrograms. + # NOTE: could be done before caching ? + dataset = dataset.map(self.harmonize_spectrogram) + # Filter out too short segment. + # NOTE: could be done before caching ? + dataset = dataset.filter(self.filter_short_segments) + # Random time crop of 11.88s + if random_time_crop: + dataset = dataset.map(self.random_time_crop, num_parallel_calls=N) + else: + # frame_duration = 11.88/T + # take central segment (for validation) + for instrument in self.instruments: + dataset = dataset.map(instrument.time_crop) + # Post cache shuffling. Done where the data are the lightest: + # after croping but before converting back to float. + if shuffle: + dataset = dataset.shuffle( + buffer_size=256, seed=self._random_seed, + reshuffle_each_iteration=True) + # Convert back to float32 + if convert_to_uint: + for instrument in self.instruments: + dataset = dataset.map( + instrument.convert_to_float32, num_parallel_calls=N) + M = 8 # Parallel call post caching. + # Must be applied with the same factor on mix and vocals. + if random_data_augmentation: + dataset = ( + dataset + .map(self.random_time_stretch, num_parallel_calls=M) + .map(self.random_pitch_shift, num_parallel_calls=M)) + # Filter by shape (remove badly shaped tensors). + for instrument in self.instruments: + dataset = ( + dataset + .filter(instrument.filter_shape) + .map(instrument.reshape_spectrogram)) + # Select features and annotation. + dataset = dataset.map(self.map_features) + # Make batch (done after selection to avoid + # error due to unprocessed instrument spectrogram batching). + dataset = dataset.batch(batch_size) + return dataset diff --git a/spleeter/model/__init__.py b/spleeter/model/__init__.py new file mode 100644 index 00000000..384e8389 --- /dev/null +++ b/spleeter/model/__init__.py @@ -0,0 +1,397 @@ +#!/usr/bin/env python +# coding: utf8 + +""" This package provide an estimator builder as well as model functions. """ + +import importlib + +# pylint: disable=import-error +import tensorflow as tf + +from tensorflow.contrib.signal import stft, inverse_stft, hann_window +# pylint: enable=import-error + +from ..utils.tensor import pad_and_partition, pad_and_reshape + +__email__ = 'research@deezer.com' +__author__ = 'Deezer Research' +__license__ = 'MIT License' + + +def get_model_function(model_type): + """ + Get tensorflow function of the model to be applied to the input tensor. + For instance "unet.softmax_unet" will return the softmax_unet function + in the "unet.py" submodule of the current module (spleeter.model). + + Params: + - model_type: str + the relative module path to the model function. + + Returns: + A tensorflow function to be applied to the input tensor to get the + multitrack output. + """ + relative_path_to_module = '.'.join(model_type.split('.')[:-1]) + model_name = model_type.split('.')[-1] + main_module = '.'.join((__name__, 'functions')) + path_to_module = f'{main_module}.{relative_path_to_module}' + module = importlib.import_module(path_to_module) + model_function = getattr(module, model_name) + return model_function + + +class EstimatorSpecBuilder(object): + """ A builder class that allows to builds a multitrack unet model + estimator. The built model estimator has a different behaviour when + used in a train/eval mode and in predict mode. + + * In train/eval mode: it takes as input and outputs magnitude spectrogram + * In predict mode: it takes as input and outputs waveform. The whole + separation process is then done in this function + for performance reason: it makes it possible to run + the whole spearation process (including STFT and + inverse STFT) on GPU. + + :Example: + + >>> from spleeter.model import EstimatorSpecBuilder + >>> builder = EstimatorSpecBuilder() + >>> builder.build_prediction_model() + >>> builder.build_evaluation_model() + >>> builder.build_training_model() + + >>> from spleeter.model import model_fn + >>> estimator = tf.estimator.Estimator(model_fn=model_fn, ...) + """ + + # Supported model functions. + DEFAULT_MODEL = 'unet.unet' + + # Supported loss functions. + L1_MASK = 'L1_mask' + WEIGHTED_L1_MASK = 'weighted_L1_mask' + + # Supported optimizers. + ADADELTA = 'Adadelta' + SGD = 'SGD' + + # Math constants. + WINDOW_COMPENSATION_FACTOR = 2./3. + EPSILON = 1e-10 + + def __init__(self, features, params): + """ Default constructor. Depending on built model + usage, the provided features should be different: + + * In train/eval mode: features is a dictionary with a + "mix_spectrogram" key, associated to the + mix magnitude spectrogram. + * In predict mode: features is a dictionary with a "waveform" + key, associated to the waveform of the sound + to be separated. + + :param features: The input features for the estimator. + :param params: Some hyperparameters as a dictionary. + """ + self._features = features + self._params = params + # Get instrument name. + self._mix_name = params['mix_name'] + self._instruments = params['instrument_list'] + # Get STFT/signals parameters + self._n_channels = params['n_channels'] + self._T = params['T'] + self._F = params['F'] + self._frame_length = params['frame_length'] + self._frame_step = params['frame_step'] + + def _build_output_dict(self): + """ Created a batch_sizexTxFxn_channels input tensor containing + mix magnitude spectrogram, then an output dict from it according + to the selected model in internal parameters. + + :returns: Build output dict. + :raise ValueError: If required model_type is not supported. + """ + input_tensor = self._features[f'{self._mix_name}_spectrogram'] + model = self._params.get('model', None) + if model is not None: + model_type = model.get('type', self.DEFAULT_MODEL) + else: + model_type = self.DEFAULT_MODEL + try: + apply_model = get_model_function(model_type) + except ModuleNotFoundError: + raise ValueError(f'No model function {model_type} found') + return apply_model( + input_tensor, + self._instruments, + self._params['model']['params']) + + def _build_loss(self, output_dict, labels): + """ Construct tensorflow loss and metrics + + :param output_dict: dictionary of network outputs (key: instrument + name, value: estimated spectrogram of the instrument) + :param labels: dictionary of target outputs (key: instrument + name, value: ground truth spectrogram of the instrument) + :returns: tensorflow (loss, metrics) tuple. + """ + loss_type = self._params.get('loss_type', self.L1_MASK) + if loss_type == self.L1_MASK: + losses = { + name: tf.reduce_mean(tf.abs(output - labels[name])) + for name, output in output_dict.items() + } + elif loss_type == self.WEIGHTED_L1_MASK: + losses = { + name: tf.reduce_mean( + tf.reduce_mean( + labels[name], + axis=[1, 2, 3], + keep_dims=True) * + tf.abs(output - labels[name])) + for name, output in output_dict.items() + } + else: + raise ValueError(f"Unkwnown loss type: {loss_type}") + loss = tf.reduce_sum(list(losses.values())) + # Add metrics for monitoring each instrument. + metrics = {k: tf.compat.v1.metrics.mean(v) for k, v in losses.items()} + metrics['absolute_difference'] = tf.compat.v1.metrics.mean(loss) + return loss, metrics + + def _build_optimizer(self): + """ Builds an optimizer instance from internal parameter values. + + Default to AdamOptimizer if not specified. + + :returns: Optimizer instance from internal configuration. + """ + name = self._params.get('optimizer') + if name == self.ADADELTA: + return tf.compat.v1.train.AdadeltaOptimizer() + rate = self._params['learning_rate'] + if name == self.SGD: + return tf.compat.v1.train.GradientDescentOptimizer(rate) + return tf.compat.v1.train.AdamOptimizer(rate) + + def _build_stft_feature(self): + """ Compute STFT of waveform and slice the STFT in segment + with the right length to feed the network. + """ + stft_feature = tf.transpose( + stft( + tf.transpose(self._features['waveform']), + self._frame_length, + self._frame_step, + window_fn=lambda frame_length, dtype: ( + hann_window(frame_length, periodic=True, dtype=dtype)), + pad_end=True), + perm=[1, 2, 0]) + self._features[f'{self._mix_name}_stft'] = stft_feature + self._features[f'{self._mix_name}_spectrogram'] = tf.abs( + pad_and_partition(stft_feature, self._T))[:, :, :self._F, :] + + def _inverse_stft(self, stft): + """ Inverse and reshape the given STFT + + :param stft: input STFT + :returns: inverse STFT (waveform) + """ + inversed = inverse_stft( + tf.transpose(stft, perm=[2, 0, 1]), + self._frame_length, + self._frame_step, + window_fn=lambda frame_length, dtype: ( + hann_window(frame_length, periodic=True, dtype=dtype)) + ) * self.WINDOW_COMPENSATION_FACTOR + reshaped = tf.transpose(inversed) + return reshaped[:tf.shape(self._features['waveform'])[0], :] + + def _build_mwf_output_waveform(self, output_dict): + """ Perform separation with multichannel Wiener Filtering using Norbert. + Note: multichannel Wiener Filtering is not coded in Tensorflow and thus + may be quite slow. + + :param output_dict: dictionary of estimated spectrogram (key: instrument + name, value: estimated spectrogram of the instrument) + :returns: dictionary of separated waveforms (key: instrument name, + value: estimated waveform of the instrument) + """ + import norbert # pylint: disable=import-error + x = self._features[f'{self._mix_name}_stft'] + v = tf.stack( + [ + pad_and_reshape( + output_dict[f'{instrument}_spectrogram'], + self._frame_length, + self._F)[:tf.shape(x)[0], ...] + for instrument in self._instruments + ], + axis=3) + input_args = [v, x] + stft_function = tf.py_function( + lambda v, x: norbert.wiener(v.numpy(), x.numpy()), + input_args, + tf.complex64), + return { + instrument: self._inverse_stft(stft_function[0][:, :, :, k]) + for k, instrument in enumerate(self._instruments) + } + + def _extend_mask(self, mask): + """ Extend mask, from reduced number of frequency bin to the number of + frequency bin in the STFT. + + :param mask: restricted mask + :returns: extended mask + :raise ValueError: If invalid mask_extension parameter is set. + """ + extension = self._params['mask_extension'] + # Extend with average + # (dispatch according to energy in the processed band) + if extension == "average": + extension_row = tf.reduce_mean(mask, axis=2, keepdims=True) + # Extend with 0 + # (avoid extension artifacts but not conservative separation) + elif extension == "zeros": + mask_shape = tf.shape(mask) + extension_row = tf.zeros(( + mask_shape[0], + mask_shape[1], + 1, + mask_shape[-1])) + else: + raise ValueError(f'Invalid mask_extension parameter {extension}') + n_extra_row = (self._frame_length) // 2 + 1 - self._F + extension = tf.tile(extension_row, [1, 1, n_extra_row, 1]) + return tf.concat([mask, extension], axis=2) + + def _build_manual_output_waveform(self, output_dict): + """ Perform ratio mask separation + + :param output_dict: dictionary of estimated spectrogram (key: instrument + name, value: estimated spectrogram of the instrument) + :returns: dictionary of separated waveforms (key: instrument name, + value: estimated waveform of the instrument) + """ + separation_exponent = self._params['separation_exponent'] + output_sum = tf.reduce_sum( + [e ** separation_exponent for e in output_dict.values()], + axis=0 + ) + self.EPSILON + output_waveform = {} + for instrument in self._instruments: + output = output_dict[f'{instrument}_spectrogram'] + # Compute mask with the model. + instrument_mask = ( + output ** separation_exponent + + (self.EPSILON / len(output_dict))) / output_sum + # Extend mask; + instrument_mask = self._extend_mask(instrument_mask) + # Stack back mask. + old_shape = tf.shape(instrument_mask) + new_shape = tf.concat( + [[old_shape[0] * old_shape[1]], old_shape[2:]], + axis=0) + instrument_mask = tf.reshape(instrument_mask, new_shape) + # Remove padded part (for mask having the same size as STFT); + stft_feature = self._features[f'{self._mix_name}_stft'] + instrument_mask = instrument_mask[ + :tf.shape(stft_feature)[0], ...] + # Compute masked STFT and normalize it. + output_waveform[instrument] = self._inverse_stft( + tf.cast(instrument_mask, dtype=tf.complex64) * stft_feature) + return output_waveform + + def _build_output_waveform(self, output_dict): + """ Build output waveform from given output dict in order to be used in + prediction context. Regarding of the configuration building method will + be using MWF. + + :param output_dict: Output dict to build output waveform from. + :returns: Built output waveform. + """ + if self._params.get('MWF', False): + output_waveform = self._build_mwf_output_waveform(output_dict) + else: + output_waveform = self._build_manual_output_waveform(output_dict) + if 'audio_id' in self._features: + output_waveform['audio_id'] = self._features['audio_id'] + return output_waveform + + def build_predict_model(self): + """ Builder interface for creating model instance that aims to perform + prediction / inference over given track. The output of such estimator + will be a dictionary with a "" key per separated instrument + , associated to the estimated separated waveform of the instrument. + + :returns: An estimator for performing prediction. + """ + self._build_stft_feature() + output_dict = self._build_output_dict() + output_waveform = self._build_output_waveform(output_dict) + return tf.estimator.EstimatorSpec( + tf.estimator.ModeKeys.PREDICT, + predictions=output_waveform) + + def build_evaluation_model(self, labels): + """ Builder interface for creating model instance that aims to perform + model evaluation. The output of such estimator will be a dictionary + with a key "_spectrogram" per separated instrument, + associated to the estimated separated instrument magnitude spectrogram. + + :param labels: Model labels. + :returns: An estimator for performing model evaluation. + """ + output_dict = self._build_output_dict() + loss, metrics = self._build_loss(output_dict, labels) + return tf.estimator.EstimatorSpec( + tf.estimator.ModeKeys.EVAL, + loss=loss, + eval_metric_ops=metrics) + + def build_train_model(self, labels): + """ Builder interface for creating model instance that aims to perform + model training. The output of such estimator will be a dictionary + with a key "_spectrogram" per separated instrument, + associated to the estimated separated instrument magnitude spectrogram. + + :param labels: Model labels. + :returns: An estimator for performing model training. + """ + output_dict = self._build_output_dict() + loss, metrics = self._build_loss(output_dict, labels) + optimizer = self._build_optimizer() + train_operation = optimizer.minimize( + loss=loss, + global_step=tf.compat.v1.train.get_global_step()) + return tf.estimator.EstimatorSpec( + mode=tf.estimator.ModeKeys.TRAIN, + loss=loss, + train_op=train_operation, + eval_metric_ops=metrics, + ) + + +def model_fn(features, labels, mode, params, config): + """ + + :param features: + :param labels: + :param mode: Estimator mode. + :param params: + :param config: TF configuration (not used). + :returns: Built EstimatorSpec. + :raise ValueError: If estimator mode is not supported. + """ + builder = EstimatorSpecBuilder(features, params) + if mode == tf.estimator.ModeKeys.PREDICT: + return builder.build_predict_model() + elif mode == tf.estimator.ModeKeys.EVAL: + return builder.build_evaluation_model(labels) + elif mode == tf.estimator.ModeKeys.TRAIN: + return builder.build_train_model(labels) + raise ValueError(f'Unknown mode {mode}') diff --git a/spleeter/model/functions/__init__.py b/spleeter/model/functions/__init__.py new file mode 100644 index 00000000..abe52e9a --- /dev/null +++ b/spleeter/model/functions/__init__.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python +# coding: utf8 + +""" This package provide model functions. """ + +__email__ = 'research@deezer.com' +__author__ = 'Deezer Research' +__license__ = 'MIT License' + + +def apply(function, input_tensor, instruments, params={}): + """ Apply given function to the input tensor. + + :param function: Function to be applied to tensor. + :param input_tensor: Tensor to apply blstm to. + :param instruments: Iterable that provides a collection of instruments. + :param params: (Optional) dict of BLSTM parameters. + :returns: Created output tensor dict. + """ + output_dict = {} + for instrument in instruments: + out_name = f'{instrument}_spectrogram' + output_dict[out_name] = function( + input_tensor, + output_name=out_name, + params=params) + return output_dict diff --git a/spleeter/model/functions/blstm.py b/spleeter/model/functions/blstm.py new file mode 100644 index 00000000..ff7ce020 --- /dev/null +++ b/spleeter/model/functions/blstm.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python +# coding: utf8 + +""" + This system (UHL1) uses a bi-directional LSTM network as described in : + + `S. Uhlich, M. Porcu, F. Giron, M. Enenkl, T. Kemp, N. Takahashi and + Y. Mitsufuji. + + "Improving music source separation based on deep neural networks through + data augmentation and network blending", Proc. ICASSP, 2017.` + + It has three BLSTM layers, each having 500 cells. For each instrument, + a network is trained which predicts the target instrument amplitude from + the mixture amplitude in the STFT domain (frame size: 4096, hop size: + 1024). The raw output of each network is then combined by a multichannel + Wiener filter. The network is trained on musdb where we split train into + train_train and train_valid with 86 and 14 songs, respectively. The + validation set is used to perform early stopping and hyperparameter + selection (LSTM layer dropout rate, regularization strength). +""" + +# pylint: disable=import-error +from tensorflow.compat.v1.keras.initializers import he_uniform +from tensorflow.compat.v1.keras.layers import CuDNNLSTM +from tensorflow.keras.layers import ( + Bidirectional, + Dense, + Flatten, + Reshape, + TimeDistributed) +# pylint: enable=import-error + +from . import apply + +__email__ = 'research@deezer.com' +__author__ = 'Deezer Research' +__license__ = 'MIT License' + + +def apply_blstm(input_tensor, output_name='output', params={}): + """ Apply BLSTM to the given input_tensor. + + :param input_tensor: Input of the model. + :param output_name: (Optional) name of the output, default to 'output'. + :param params: (Optional) dict of BLSTM parameters. + :returns: Output tensor. + """ + units = params.get('lstm_units', 250) + kernel_initializer = he_uniform(seed=50) + flatten_input = TimeDistributed(Flatten())((input_tensor)) + + def create_bidirectional(): + return Bidirectional( + CuDNNLSTM( + units, + kernel_initializer=kernel_initializer, + return_sequences=True)) + + l1 = create_bidirectional()((flatten_input)) + l2 = create_bidirectional()((l1)) + l3 = create_bidirectional()((l2)) + dense = TimeDistributed( + Dense( + int(flatten_input.shape[2]), + activation='relu', + kernel_initializer=kernel_initializer))((l3)) + output = TimeDistributed( + Reshape(input_tensor.shape[2:]), + name=output_name)(dense) + return output + + +def blstm(input_tensor, output_name='output', params={}): + """ Model function applier. """ + return apply(apply_blstm, input_tensor, output_name, params) diff --git a/spleeter/model/functions/unet.py b/spleeter/model/functions/unet.py new file mode 100644 index 00000000..245a5e58 --- /dev/null +++ b/spleeter/model/functions/unet.py @@ -0,0 +1,201 @@ +#!/usr/bin/env python +# coding: utf8 + +""" +This module contains building functions for U-net source separation source +separation models. +Each instrument is modeled by a single U-net convolutional/deconvolutional +network that take a mix spectrogram as input and the estimated sound spectrogram +as output. +""" + +from functools import partial + +# pylint: disable=import-error +import tensorflow as tf + +from tensorflow.keras.layers import ( + BatchNormalization, + Concatenate, + Conv2D, + Conv2DTranspose, + Dropout, + ELU, + LeakyReLU, + Multiply, + ReLU, + Softmax) +from tensorflow.compat.v1 import logging +from tensorflow.compat.v1.keras.initializers import he_uniform +# pylint: enable=import-error + +from . import apply + +__email__ = 'research@deezer.com' +__author__ = 'Deezer Research' +__license__ = 'MIT License' + + +def _get_conv_activation_layer(params): + """ + + :param params: + :returns: Required Activation function. + """ + conv_activation = params.get('conv_activation') + if conv_activation == 'ReLU': + return ReLU() + elif conv_activation == 'ELU': + return ELU() + return LeakyReLU(0.2) + + +def _get_deconv_activation_layer(params): + """ + + :param params: + :returns: Required Activation function. + """ + deconv_activation = params.get('deconv_activation') + if deconv_activation == 'LeakyReLU': + return LeakyReLU(0.2) + elif deconv_activation == 'ELU': + return ELU() + return ReLU() + + +def apply_unet( + input_tensor, + output_name='output', + params={}, + output_mask_logit=False): + """ Apply a convolutionnal U-net to model a single instrument (one U-net + is used for each instrument). + + :param input_tensor: + :param output_name: (Optional) , default to 'output' + :param params: (Optional) , default to empty dict. + :param output_mask_logit: (Optional) , default to False. + """ + logging.info(f'Apply unet for {output_name}') + conv_n_filters = params.get('conv_n_filters', [16, 32, 64, 128, 256, 512]) + conv_activation_layer = _get_conv_activation_layer(params) + deconv_activation_layer = _get_deconv_activation_layer(params) + kernel_initializer = he_uniform(seed=50) + conv2d_factory = partial( + Conv2D, + strides=(2, 2), + padding='same', + kernel_initializer=kernel_initializer) + # First layer. + conv1 = conv2d_factory(conv_n_filters[0], (5, 5))(input_tensor) + batch1 = BatchNormalization(axis=-1)(conv1) + rel1 = conv_activation_layer(batch1) + # Second layer. + conv2 = conv2d_factory(conv_n_filters[1], (5, 5))(rel1) + batch2 = BatchNormalization(axis=-1)(conv2) + rel2 = conv_activation_layer(batch2) + # Third layer. + conv3 = conv2d_factory(conv_n_filters[2], (5, 5))(rel2) + batch3 = BatchNormalization(axis=-1)(conv3) + rel3 = conv_activation_layer(batch3) + # Fourth layer. + conv4 = conv2d_factory(conv_n_filters[3], (5, 5))(rel3) + batch4 = BatchNormalization(axis=-1)(conv4) + rel4 = conv_activation_layer(batch4) + # Fifth layer. + conv5 = conv2d_factory(conv_n_filters[4], (5, 5))(rel4) + batch5 = BatchNormalization(axis=-1)(conv5) + rel5 = conv_activation_layer(batch5) + # Sixth layer + conv6 = conv2d_factory(conv_n_filters[5], (5, 5))(rel5) + batch6 = BatchNormalization(axis=-1)(conv6) + _ = conv_activation_layer(batch6) + # + # + conv2d_transpose_factory = partial( + Conv2DTranspose, + strides=(2, 2), + padding='same', + kernel_initializer=kernel_initializer) + # + up1 = conv2d_transpose_factory(conv_n_filters[4], (5, 5))((conv6)) + up1 = deconv_activation_layer(up1) + batch7 = BatchNormalization(axis=-1)(up1) + drop1 = Dropout(0.5)(batch7) + merge1 = Concatenate(axis=-1)([conv5, drop1]) + # + up2 = conv2d_transpose_factory(conv_n_filters[3], (5, 5))((merge1)) + up2 = deconv_activation_layer(up2) + batch8 = BatchNormalization(axis=-1)(up2) + drop2 = Dropout(0.5)(batch8) + merge2 = Concatenate(axis=-1)([conv4, drop2]) + # + up3 = conv2d_transpose_factory(conv_n_filters[2], (5, 5))((merge2)) + up3 = deconv_activation_layer(up3) + batch9 = BatchNormalization(axis=-1)(up3) + drop3 = Dropout(0.5)(batch9) + merge3 = Concatenate(axis=-1)([conv3, drop3]) + # + up4 = conv2d_transpose_factory(conv_n_filters[1], (5, 5))((merge3)) + up4 = deconv_activation_layer(up4) + batch10 = BatchNormalization(axis=-1)(up4) + merge4 = Concatenate(axis=-1)([conv2, batch10]) + # + up5 = conv2d_transpose_factory(conv_n_filters[0], (5, 5))((merge4)) + up5 = deconv_activation_layer(up5) + batch11 = BatchNormalization(axis=-1)(up5) + merge5 = Concatenate(axis=-1)([conv1, batch11]) + # + up6 = conv2d_transpose_factory(1, (5, 5), strides=(2, 2))((merge5)) + up6 = deconv_activation_layer(up6) + batch12 = BatchNormalization(axis=-1)(up6) + # Last layer to ensure initial shape reconstruction. + if not output_mask_logit: + up7 = Conv2D( + 2, + (4, 4), + dilation_rate=(2, 2), + activation='sigmoid', + padding='same', + kernel_initializer=kernel_initializer)((batch12)) + output = Multiply(name=output_name)([up7, input_tensor]) + return output + return Conv2D( + 2, + (4, 4), + dilation_rate=(2, 2), + padding='same', + kernel_initializer=kernel_initializer)((batch12)) + + +def unet(input_tensor, instruments, params={}): + """ Model function applier. """ + return apply(apply_unet, input_tensor, instruments, params) + + +def softmax_unet(input_tensor, instruments, params={}): + """ Apply softmax to multitrack unet in order to have mask suming to one. + + :param input_tensor: Tensor to apply blstm to. + :param instruments: Iterable that provides a collection of instruments. + :param params: (Optional) dict of BLSTM parameters. + :returns: Created output tensor dict. + """ + logit_mask_list = [] + for instrument in instruments: + out_name = f'{instrument}_spectrogram' + logit_mask_list.append( + apply_unet( + input_tensor, + output_name=out_name, + params=params, + output_mask_logit=True)) + masks = Softmax(axis=4)(tf.stack(logit_mask_list, axis=4)) + output_dict = {} + for i, instrument in enumerate(instruments): + out_name = f'{instrument}_spectrogram' + output_dict[out_name] = Multiply(name=out_name)([ + masks[..., i], + input_tensor]) + return output_dict diff --git a/spleeter/model/provider/__init__.py b/spleeter/model/provider/__init__.py new file mode 100644 index 00000000..854b065c --- /dev/null +++ b/spleeter/model/provider/__init__.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python +# coding: utf8 + +""" + This package provides tools for downloading model from network + using remote storage abstraction. + + :Example: + + >>> provider = MyProviderImplementation() + >>> provider.get('/path/to/local/storage', params) +""" + +from abc import ABC, abstractmethod +from os import environ, makedirs +from os.path import exists, isabs, join, sep + +__email__ = 'research@deezer.com' +__author__ = 'Deezer Research' +__license__ = 'MIT License' + + +class ModelProvider(ABC): + """ + A ModelProvider manages model files on disk and + file download is not available. + """ + + DEFAULT_MODEL_PATH = environ.get('MODEL_PATH', 'pretrained_models') + MODEL_PROBE_PATH = '.probe' + + @abstractmethod + def download(self, name, path): + """ Download model denoted by the given name to disk. + + :param name: Name of the model to download. + :param path: Path of the directory to save model into. + """ + pass + + def writeProbe(self, directory): + """ Write a model probe file into the given directory. + + :param directory: Directory to write probe into. + """ + with open(join(directory, self.MODEL_PROBE_PATH), 'w') as stream: + stream.write('OK') + + def get(self, model_directory): + """ Ensures required model is available at given location. + + :param model_directory: Expected model_directory to be available. + :raise IOError: If model can not be retrieved. + """ + # Expend model directory if needed. + if not isabs(model_directory): + model_directory = join(self.DEFAULT_MODEL_PATH, model_directory) + # Download it if not exists. + model_probe = join(model_directory, self.MODEL_PROBE_PATH) + if not exists(model_probe): + if not exists(model_directory): + makedirs(model_directory) + self.download( + model_directory.split(sep)[-1], + model_directory) + self.writeProbe(model_directory) + return model_directory + + +def get_default_model_provider(): + """ Builds and returns a default model provider. + + :returns: A default model provider instance to use. + """ + from .github import GithubModelProvider + host = environ.get('GITHUB_HOST', 'https://github.com') + repository = environ.get('GITHUB_REPOSITORY', 'deezer/spleeter') + release = environ.get('GITHUB_RELEASE', GithubModelProvider.LATEST_RELEASE) + return GithubModelProvider(host, repository, release) diff --git a/spleeter/model/provider/github.py b/spleeter/model/provider/github.py new file mode 100644 index 00000000..cc7028c8 --- /dev/null +++ b/spleeter/model/provider/github.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python +# coding: utf8 + +""" + A ModelProvider backed by Github Release feature. + + :Example: + + >>> from spleeter.model.provider import github + >>> provider = github.GithubModelProvider( + 'github.com', + 'Deezer/spleeter', + 'latest') + >>> provider.download('2stems', '/path/to/local/storage') +""" + +import tarfile + +from os import environ +from tempfile import TemporaryFile +from shutil import copyfileobj + +import requests + +from . import ModelProvider +from ...utils.logging import get_logger + +__email__ = 'research@deezer.com' +__author__ = 'Deezer Research' +__license__ = 'MIT License' + + +class GithubModelProvider(ModelProvider): + """ A ModelProvider implementation backed on Github for remote storage. """ + + LATEST_RELEASE = 'v1.4.0' + RELEASE_PATH = 'releases/download' + + def __init__(self, host, repository, release): + """ Default constructor. + + :param host: Host to the Github instance to reach. + :param repository: Repository path within target Github. + :param release: Release name to get models from. + """ + self._host = host + self._repository = repository + self._release = release + + def download(self, name, path): + """ Download model denoted by the given name to disk. + + :param name: Name of the model to download. + :param path: Path of the directory to save model into. + """ + url = '{}/{}/{}/{}/{}.tar.gz'.format( + self._host, + self._repository, + self.RELEASE_PATH, + self._release, + name) + get_logger().info('Downloading model archive %s', url) + response = requests.get(url, stream=True) + if response.status_code != 200: + raise IOError(f'Resource {url} not found') + with TemporaryFile() as stream: + copyfileobj(response.raw, stream) + get_logger().debug('Extracting downloaded archive') + stream.seek(0) + tar = tarfile.open(fileobj=stream) + tar.extractall(path=path) + tar.close() + get_logger().debug('Model file extracted') diff --git a/spleeter/resources/2stems.json b/spleeter/resources/2stems.json new file mode 100644 index 00000000..5f0f5fe2 --- /dev/null +++ b/spleeter/resources/2stems.json @@ -0,0 +1,28 @@ +{ + "train_csv": "path/to/train.csv", + "validation_csv": "path/to/test.csv", + "model_dir": "2stems", + "mix_name": "mix", + "instrument_list": ["vocals", "accompaniment"], + "sample_rate":44100, + "frame_length":4096, + "frame_step":1024, + "T":512, + "F":1024, + "n_channels":2, + "separation_exponent":2, + "mask_extension":"zeros", + "learning_rate": 1e-4, + "batch_size":4, + "training_cache":"training_cache", + "validation_cache":"validation_cache", + "train_max_steps": 1000000, + "throttle_secs":300, + "random_seed":0, + "save_checkpoints_steps":150, + "save_summary_steps":5, + "model":{ + "type":"unet.unet", + "params":{} + } +} diff --git a/spleeter/resources/4stems.json b/spleeter/resources/4stems.json new file mode 100644 index 00000000..a6461546 --- /dev/null +++ b/spleeter/resources/4stems.json @@ -0,0 +1,31 @@ +{ + "train_csv": "path/to/train.csv", + "validation_csv": "path/to/val.csv", + "model_dir": "4stems", + "mix_name": "mix", + "instrument_list": ["vocals", "drums", "bass", "other"], + "sample_rate":44100, + "frame_length":4096, + "frame_step":1024, + "T":512, + "F":1024, + "n_channels":2, + "separation_exponent":2, + "mask_extension":"zeros", + "learning_rate": 1e-4, + "batch_size":4, + "training_cache":"training_cache", + "validation_cache":"validation_cache", + "train_max_steps": 1500000, + "throttle_secs":600, + "random_seed":3, + "save_checkpoints_steps":300, + "save_summary_steps":5, + "model":{ + "type":"unet.unet", + "params":{ + "conv_activation":"ELU", + "deconv_activation":"ELU" + } + } +} diff --git a/spleeter/resources/5stems.json b/spleeter/resources/5stems.json new file mode 100644 index 00000000..aad63121 --- /dev/null +++ b/spleeter/resources/5stems.json @@ -0,0 +1,31 @@ +{ + "train_csv": "path/to/train.csv", + "validation_csv": "path/to/test.csv", + "model_dir": "5stems", + "mix_name": "mix", + "instrument_list": ["vocals", "piano", "drums", "bass", "other"], + "sample_rate":44100, + "frame_length":4096, + "frame_step":1024, + "T":512, + "F":1024, + "n_channels":2, + "separation_exponent":2, + "mask_extension":"zeros", + "learning_rate": 1e-4, + "batch_size":4, + "training_cache":"training_cache", + "validation_cache":"validation_cache", + "train_max_steps": 2500000, + "throttle_secs":600, + "random_seed":8, + "save_checkpoints_steps":300, + "save_summary_steps":5, + "model":{ + "type":"unet.softmax_unet", + "params":{ + "conv_activation":"ELU", + "deconv_activation":"ELU" + } + } +} diff --git a/spleeter/resources/__init__.py b/spleeter/resources/__init__.py new file mode 100644 index 00000000..41d2a651 --- /dev/null +++ b/spleeter/resources/__init__.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python +# coding: utf8 + +""" Packages that provides static resources file for the library. """ + +__email__ = 'research@deezer.com' +__author__ = 'Deezer Research' +__license__ = 'MIT License' diff --git a/spleeter/resources/musdb.json b/spleeter/resources/musdb.json new file mode 100644 index 00000000..0d447006 --- /dev/null +++ b/spleeter/resources/musdb.json @@ -0,0 +1,32 @@ +{ + "train_csv": "configs/musdb_train.csv", + "validation_csv": "configs/musdb_validation.csv", + "model_dir": "musdb_model", + "mix_name": "mix", + "instrument_list": ["vocals", "drums", "bass", "other"], + "sample_rate":44100, + "frame_length":4096, + "frame_step":1024, + "T":512, + "F":1024, + "n_channels":2, + "n_chunks_per_song":1, + "separation_exponent":2, + "mask_extension":"zeros", + "learning_rate": 1e-4, + "batch_size":4, + "training_cache":"training_cache", + "validation_cache":"validation_cache", + "train_max_steps": 100000, + "throttle_secs":600, + "random_seed":3, + "save_checkpoints_steps":300, + "save_summary_steps":5, + "model":{ + "type":"unet.unet", + "params":{ + "conv_activation":"ELU", + "deconv_activation":"ELU" + } + } +} diff --git a/spleeter/separator.py b/spleeter/separator.py new file mode 100644 index 00000000..a238037a --- /dev/null +++ b/spleeter/separator.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python +# coding: utf8 + +""" + Module that provides a class wrapper for source separation. + + :Example: + + >>> from spleeter.separator import Separator + >>> separator = Separator('spleeter:2stems') + >>> separator.separate(waveform, lambda instrument, data: ...) + >>> separator.separate_to_file(...) +""" + +import os +import json + +from functools import partial +from multiprocessing import Pool +from pathlib import Path +from os.path import join + +from .model import model_fn +from .utils.audio.adapter import get_default_audio_adapter +from .utils.audio.convertor import to_stereo +from .utils.configuration import load_configuration +from .utils.estimator import create_estimator, to_predictor + +__email__ = 'research@deezer.com' +__author__ = 'Deezer Research' +__license__ = 'MIT License' + + +class Separator(object): + """ A wrapper class for performing separation. """ + + def __init__(self, params_descriptor, MWF=False): + """ Default constructor. + + :param params_descriptor: Descriptor for TF params to be used. + :param MWF: (Optional) True if MWF should be used, False otherwise. + """ + self._params = load_configuration(params_descriptor) + self._sample_rate = self._params['sample_rate'] + self._MWF = MWF + self._predictor = None + self._pool = Pool() + self._tasks = [] + + def _get_predictor(self): + """ Lazy loading access method for internal predictor instance. + + :returns: Predictor to use for source separation. + """ + if self._predictor is None: + estimator = create_estimator(self._params, self._MWF) + self._predictor = to_predictor(estimator) + return self._predictor + + def join(self, timeout=20): + """ Wait for all pending tasks to be finished. + + :param timeout: (Optional) task waiting timeout. + """ + while len(self._tasks) > 0: + task = self._tasks.pop() + task.get() + task.wait(timeout=timeout) + + def separate(self, waveform): + """ Performs source separation over the given waveform. + + The separation is performed synchronously but the result + processing is done asynchronously, allowing for instance + to export audio in parallel (through multiprocessing). + + Given result is passed by to the given consumer, which will + be waited for task finishing if synchronous flag is True. + + :param waveform: Waveform to apply separation on. + :returns: Separated waveforms. + """ + if not waveform.shape[-1] == 2: + waveform = to_stereo(waveform) + predictor = self._get_predictor() + prediction = predictor({ + 'waveform': waveform, + 'audio_id': ''}) + prediction.pop('audio_id') + return prediction + + def separate_to_file( + self, audio_descriptor, destination, + audio_adapter=get_default_audio_adapter(), + offset=0, duration=600., codec='wav', bitrate='128k', + synchronous=True): + """ Performs source separation and export result to file using + given audio adapter. + + :param audio_descriptor: Describe song to separate, used by audio + adapter to retrieve and load audio data, + in case of file based audio adapter, such + descriptor would be a file path. + :param destination: Target directory to write output to. + :param audio_adapter: (Optional) Audio adapter to use for I/O. + :param offset: (Optional) Offset of loaded song. + :param duration: (Optional) Duration of loaded song. + :param codec: (Optional) Export codec. + :param bitrate: (Optional) Export bitrate. + :param synchronous: (Optional) True is should by synchronous. + """ + waveform, _ = audio_adapter.load( + audio_descriptor, + offset=offset, + duration=duration, + sample_rate=self._sample_rate) + sources = self.separate(waveform) + for instrument, data in sources.items(): + task = self._pool.apply_async(audio_adapter.save, ( + join(destination, f'{instrument}.{codec}'), + data, + self._sample_rate, + codec, + bitrate)) + self._tasks.append(task) + if synchronous: + self.join() diff --git a/spleeter/utils/__init__.py b/spleeter/utils/__init__.py new file mode 100644 index 00000000..a4ccb5bc --- /dev/null +++ b/spleeter/utils/__init__.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python +# coding: utf8 + +""" This package provides utility function and classes. """ + +__email__ = 'research@deezer.com' +__author__ = 'Deezer Research' +__license__ = 'MIT License' diff --git a/spleeter/utils/audio/__init__.py b/spleeter/utils/audio/__init__.py new file mode 100644 index 00000000..02f83c0f --- /dev/null +++ b/spleeter/utils/audio/__init__.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python +# coding: utf8 + +""" + `spleeter.utils.audio` package provides various + tools for manipulating audio content such as : + + - Audio adapter class for abstract interaction with audio file. + - FFMPEG implementation for audio adapter. + - Waveform convertion and transforming functions. +""" + +__email__ = 'research@deezer.com' +__author__ = 'Deezer Research' +__license__ = 'MIT License' diff --git a/spleeter/utils/audio/adapter.py b/spleeter/utils/audio/adapter.py new file mode 100644 index 00000000..b2d7cb1f --- /dev/null +++ b/spleeter/utils/audio/adapter.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python +# coding: utf8 + +""" AudioAdapter class defintion. """ + +import subprocess + +from abc import ABC, abstractmethod +from importlib import import_module +from os.path import exists + +# pylint: disable=import-error +import numpy as np +import tensorflow as tf + +from tensorflow.contrib.signal import stft, hann_window +# pylint: enable=import-error + +from ..logging import get_logger + +__email__ = 'research@deezer.com' +__author__ = 'Deezer Research' +__license__ = 'MIT License' + + +class AudioAdapter(ABC): + """ An abstract class for manipulating audio signal. """ + + # Default audio adapter singleton instance. + DEFAULT = None + + @abstractmethod + def load( + self, audio_descriptor, offset, duration, + sample_rate, dtype=np.float32): + """ Loads the audio file denoted by the given audio descriptor + and returns it data as a waveform. Aims to be implemented + by client. + + :param audio_descriptor: Describe song to load, in case of file + based audio adapter, such descriptor would + be a file path. + :param offset: Start offset to load from in seconds. + :param duration: Duration to load in seconds. + :param sample_rate: Sample rate to load audio with. + :param dtype: Numpy data type to use, default to float32. + :returns: Loaded data as (wf, sample_rate) tuple. + """ + pass + + def load_tf_waveform( + self, audio_descriptor, + offset=0.0, duration=1800., sample_rate=44100, + dtype=b'float32', waveform_name='waveform'): + """ Load the audio and convert it to a tensorflow waveform. + + :param audio_descriptor: Describe song to load, in case of file + based audio adapter, such descriptor would + be a file path. + :param offset: Start offset to load from in seconds. + :param duration: Duration to load in seconds. + :param sample_rate: Sample rate to load audio with. + :param dtype: Numpy data type to use, default to float32. + :param waveform_name: (Optional) Name of the key in output dict. + :returns: TF output dict with waveform as + (T x chan numpy array) and a boolean that + tells whether there were an error while + trying to load the waveform. + """ + # Cast parameters to TF format. + offset = tf.cast(offset, tf.float64) + duration = tf.cast(duration, tf.float64) + + # Defined safe loading function. + def safe_load(path, offset, duration, sample_rate, dtype): + get_logger().info( + f'Loading audio {path} from {offset} to {offset + duration}') + try: + (data, _) = self.load( + path.numpy(), + offset.numpy(), + duration.numpy(), + sample_rate.numpy(), + dtype=dtype.numpy()) + return (data, False) + except Exception as e: + get_logger().warning(e) + return (np.float32(-1.0), True) + + # Execute function and format results. + results = tf.py_function( + safe_load, + [audio_descriptor, offset, duration, sample_rate, dtype], + (tf.float32, tf.bool)), + waveform, error = results[0] + return { + waveform_name: waveform, + f'{waveform_name}_error': error + } + + @abstractmethod + def save( + self, path, data, sample_rate, + codec=None, bitrate=None): + """ Save the given audio data to the file denoted by + the given path. + + :param path: Path of the audio file to save data in. + :param data: Waveform data to write. + :param sample_rate: Sample rate to write file in. + :param codec: (Optional) Writing codec to use. + :param bitrate: (Optional) Bitrate of the written audio file. + """ + pass + + +def get_default_audio_adapter(): + """ Builds and returns a default audio adapter instance. + + :returns: An audio adapter instance. + """ + if AudioAdapter.DEFAULT is None: + from .ffmpeg import FFMPEGProcessAudioAdapter + AudioAdapter.DEFAULT = FFMPEGProcessAudioAdapter() + return AudioAdapter.DEFAULT + + +def get_audio_adapter(descriptor): + """ Load dynamically an AudioAdapter from given class descriptor. + + :param descriptor: Adapter class descriptor (module.Class) + :returns: Created adapter instance. + """ + if descriptor is None: + return get_default_audio_adapter() + module_path = descriptor.split('.') + adapter_class_name = module_path[-1] + module_path = '.'.join(module_path[:-1]) + adapter_module = import_module(module_path) + adapter_class = getattr(adapter_module, adapter_class_name) + if not isinstance(adapter_class, AudioAdapter): + raise ValueError( + f'{adapter_class_name} is not a valid AudioAdapter class') + return adapter_class() diff --git a/spleeter/utils/audio/convertor.py b/spleeter/utils/audio/convertor.py new file mode 100644 index 00000000..b6a79534 --- /dev/null +++ b/spleeter/utils/audio/convertor.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python +# coding: utf8 + +""" This module provides audio data convertion functions. """ + +# pylint: disable=import-error +import numpy as np +import tensorflow as tf +# pylint: enable=import-error + +from ..tensor import from_float32_to_uint8, from_uint8_to_float32 + +__email__ = 'research@deezer.com' +__author__ = 'Deezer Research' +__license__ = 'MIT License' + + +def to_n_channels(waveform, n_channels): + """ Convert a waveform to n_channels by removing or + duplicating channels if needed (in tensorflow). + + :param waveform: Waveform to transform. + :param n_channels: Number of channel to reshape waveform in. + :returns: Reshaped waveform. + """ + return tf.cond( + tf.shape(waveform)[1] >= n_channels, + true_fn=lambda: waveform[:, :n_channels], + false_fn=lambda: tf.tile(waveform, [1, n_channels])[:, :n_channels] + ) + + +def to_stereo(waveform): + """ Convert a waveform to stereo by duplicating if mono, + or truncating if too many channels. + + :param waveform: a (N, d) numpy array. + :returns: A stereo waveform as a (N, 1) numpy array. + """ + if waveform.shape[1] == 1: + return np.repeat(waveform, 2, axis=-1) + if waveform.shape[1] > 2: + return waveform[:, :2] + return waveform + + +def gain_to_db(tensor, espilon=10e-10): + """ Convert from gain to decibel in tensorflow. + + :param tensor: Tensor to convert. + :param epsilon: Operation constant. + :returns: Converted tensor. + """ + return 20. / np.log(10) * tf.math.log(tf.maximum(tensor, espilon)) + + +def db_to_gain(tensor): + """ Convert from decibel to gain in tensorflow. + + :param tensor_db: Tensor to convert. + :returns: Converted tensor. + """ + return tf.pow(10., (tensor / 20.)) + + +def spectrogram_to_db_uint(spectrogram, db_range=100., **kwargs): + """ Encodes given spectrogram into uint8 using decibel scale. + + :param spectrogram: Spectrogram to be encoded as TF float tensor. + :param db_range: Range in decibel for encoding. + :returns: Encoded decibel spectrogram as uint8 tensor. + """ + db_spectrogram = gain_to_db(spectrogram) + max_db_spectrogram = tf.reduce_max(db_spectrogram) + db_spectrogram = tf.maximum(db_spectrogram, max_db_spectrogram - db_range) + return from_float32_to_uint8(db_spectrogram, **kwargs) + + +def db_uint_spectrogram_to_gain(db_uint_spectrogram, min_db, max_db): + """ Decode spectrogram from uint8 decibel scale. + + :param db_uint_spectrogram: Decibel pectrogram to decode. + :param min_db: Lower bound limit for decoding. + :param max_db: Upper bound limit for decoding. + :returns: Decoded spectrogram as float2 tensor. + """ + db_spectrogram = from_uint8_to_float32(db_uint_spectrogram, min_db, max_db) + return db_to_gain(db_spectrogram) diff --git a/spleeter/utils/audio/ffmpeg.py b/spleeter/utils/audio/ffmpeg.py new file mode 100644 index 00000000..ad24e331 --- /dev/null +++ b/spleeter/utils/audio/ffmpeg.py @@ -0,0 +1,263 @@ +#!/usr/bin/env python +# coding: utf8 + +""" + This module provides an AudioAdapter implementation based on FFMPEG + process. Such implementation is POSIXish and depends on nothing except + standard Python libraries. Thus this implementation is the default one + used within this library. +""" + +import os +import os.path +import platform +import re +import subprocess + +import numpy as np # pylint: disable=import-error + +from .adapter import AudioAdapter +from ..logging import get_logger + +__email__ = 'research@deezer.com' +__author__ = 'Deezer Research' +__license__ = 'MIT License' + +# Default FFMPEG binary name. +_UNIX_BINARY = 'ffmpeg' +_WINDOWS_BINARY = 'ffmpeg.exe' + + +def _which(program): + """ A pure python implementation of `which`command + for retrieving absolute path from command name or path. + + @see https://stackoverflow.com/a/377028/1211342 + + :param program: Program name or path to expend. + :returns: Absolute path of program if any, None otherwise. + """ + def is_exe(fpath): + return os.path.isfile(fpath) and os.access(fpath, os.X_OK) + + fpath, _ = os.path.split(program) + if fpath: + if is_exe(program): + return program + else: + for path in os.environ['PATH'].split(os.pathsep): + exe_file = os.path.join(path, program) + if is_exe(exe_file): + return exe_file + return None + + +def _get_ffmpeg_path(): + """ Retrieves FFMPEG binary path using ENVVAR if defined + or default binary name (Windows or UNIX style). + + :returns: Absolute path of FFMPEG binary. + :raise IOError: If FFMPEG binary cannot be found. + """ + ffmpeg_path = os.environ.get('FFMPEG_PATH', None) + if ffmpeg_path is None: + # Note: try to infer standard binary name regarding of platform. + if platform.system() == 'Windows': + ffmpeg_path = _WINDOWS_BINARY + else: + ffmpeg_path = _UNIX_BINARY + expended = _which(ffmpeg_path) + if expended is None: + raise IOError(f'FFMPEG binary ({ffmpeg_path}) not found') + return expended + + +def _to_ffmpeg_time(n): + """ Format number of seconds to time expected by FFMPEG. + + :param n: Time in seconds to format. + :returns: Formatted time in FFMPEG format. + """ + m, s = divmod(n, 60) + h, m = divmod(m, 60) + return '%d:%02d:%09.6f' % (h, m, s) + + +def _parse_ffmpg_results(stderr): + """ Extract number of channels and sample rate from + the given FFMPEG STDERR output line. + + :param stderr: STDERR output line to parse. + :returns: Parsed n_channels and sample_rate values. + """ + # Setup default value. + n_channels = 0 + sample_rate = 0 + # Find samplerate + match = re.search(r'(\d+) hz', stderr) + if match: + sample_rate = int(match.group(1)) + # Channel count. + match = re.search(r'hz, ([^,]+),', stderr) + if match: + mode = match.group(1) + if mode == 'stereo': + n_channels = 2 + else: + match = re.match(r'(\d+) ', mode) + n_channels = match and int(match.group(1)) or 1 + return n_channels, sample_rate + + +class _CommandBuilder(object): + """ A simple builder pattern class for CLI string. """ + + def __init__(self, binary): + """ Default constructor. """ + self._command = [binary] + + def flag(self, flag): + """ Add flag or unlabelled opt. """ + self._command.append(flag) + return self + + def opt(self, short, value, formatter=str): + """ Add option if value not None. """ + if value is not None: + self._command.append(short) + self._command.append(formatter(value)) + return self + + def command(self): + """ Build string command. """ + return self._command + + +class FFMPEGProcessAudioAdapter(AudioAdapter): + """ An AudioAdapter implementation that use FFMPEG binary through + subprocess in order to perform I/O operation for audio processing. + + When created, FFMPEG binary path will be checked and expended, + raising exception if not found. Such path could be infered using + FFMPEG_PATH environment variable. + """ + + def __init__(self): + """ Default constructor. """ + self._ffmpeg_path = _get_ffmpeg_path() + + def _get_command_builder(self): + """ Creates and returns a command builder using FFMPEG path. + + :returns: Built command builder. + """ + return _CommandBuilder(self._ffmpeg_path) + + def load( + self, path, offset=None, duration=None, + sample_rate=None, dtype=np.float32): + """ Loads the audio file denoted by the given path + and returns it data as a waveform. + + :param path: Path of the audio file to load data from. + :param offset: (Optional) Start offset to load from in seconds. + :param duration: (Optional) Duration to load in seconds. + :param sample_rate: (Optional) Sample rate to load audio with. + :param dtype: (Optional) Numpy data type to use, default to float32. + :returns: Loaded data a (waveform, sample_rate) tuple. + """ + if not isinstance(path, str): + path = path.decode() + command = ( + self._get_command_builder() + .opt('-ss', offset, formatter=_to_ffmpeg_time) + .opt('-t', duration, formatter=_to_ffmpeg_time) + .opt('-i', path) + .opt('-ar', sample_rate) + .opt('-f', 'f32le') + .flag('-') + .command()) + process = subprocess.Popen( + command, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + buffer = process.stdout.read(-1) + # Read STDERR until end of the process detected. + while True: + status = process.stderr.readline() + if not status: + raise OSError('Stream info not found') + if isinstance(status, bytes): # Note: Python 3 compatibility. + status = status.decode('utf8', 'ignore') + status = status.strip().lower() + if 'no such file' in status: + raise IOError(f'File {path} not found') + elif 'invalid data found' in status: + raise IOError(f'FFMPEG error : {status}') + elif 'audio:' in status: + n_channels, ffmpeg_sample_rate = _parse_ffmpg_results(status) + if sample_rate is None: + sample_rate = ffmpeg_sample_rate + break + # Load waveform and clean process. + waveform = np.frombuffer(buffer, dtype='0, default to 1. + :param mehtod: (Optional) Interpolation method, default to BILINEAR. + :returns: Time stretched spectrogram as tensor with same shape. + """ + T = tf.shape(spectrogram)[0] + T_ts = tf.cast(tf.cast(T, tf.float32) * factor, tf.int32)[0] + F = tf.shape(spectrogram)[1] + ts_spec = tf.image.resize_images( + spectrogram, + [T_ts, F], + method=method, + align_corners=True) + return tf.image.resize_image_with_crop_or_pad(ts_spec, T, F) + + +def random_time_stretch(spectrogram, factor_min=0.9, factor_max=1.1, **kwargs): + """ Time stretch a spectrogram preserving shape with random ratio in + tensorflow. Applies time_stretch to spectrogram with a random ratio drawn + uniformly in [factor_min, factor_max]. + + :param spectrogram: Input spectrogram to be time stretched as tensor. + :param factor_min: (Optional) Min time stretch factor, default to 0.9. + :param factor_max: (Optional) Max time stretch factor, default to 1.1. + :returns: Randomly time stretched spectrogram as tensor with same shape. + """ + factor = tf.random_uniform( + shape=(1,), + seed=0) * (factor_max - factor_min) + factor_min + return time_stretch(spectrogram, factor=factor, **kwargs) + + +def pitch_shift( + spectrogram, + semitone_shift=0.0, + method=tf.image.ResizeMethod.BILINEAR): + """ Pitch shift a spectrogram preserving shape in tensorflow. Note that + this is an approximation in the frequency domain. + + :param spectrogram: Input spectrogram to be pitch shifted as tensor. + :param semitone_shift: (Optional) Pitch shift in semitone, default to 0.0. + :param mehtod: (Optional) Interpolation method, default to BILINEAR. + :returns: Pitch shifted spectrogram (same shape as spectrogram). + """ + factor = 2 ** (semitone_shift / 12.) + T = tf.shape(spectrogram)[0] + F = tf.shape(spectrogram)[1] + F_ps = tf.cast(tf.cast(F, tf.float32) * factor, tf.int32)[0] + ps_spec = tf.image.resize_images( + spectrogram, + [T, F_ps], + method=method, + align_corners=True) + paddings = [[0, 0], [0, tf.maximum(0, F - F_ps)], [0, 0]] + return tf.pad(ps_spec[:, :F, :], paddings, 'CONSTANT') + + +def random_pitch_shift(spectrogram, shift_min=-1., shift_max=1., **kwargs): + """ Pitch shift a spectrogram preserving shape with random ratio in + tensorflow. Applies pitch_shift to spectrogram with a random shift + amount (expressed in semitones) drawn uniformly in [shift_min, shift_max]. + + :param spectrogram: Input spectrogram to be pitch shifted as tensor. + + :param shift_min: (Optional) Min pitch shift in semitone, default to -1. + :param shift_max: (Optional) Max pitch shift in semitone, default to 1. + :returns: Randomly pitch shifted spectrogram (same shape as spectrogram). + """ + semitone_shift = tf.random_uniform( + shape=(1,), + seed=0) * (shift_max - shift_min) + shift_min + return pitch_shift(spectrogram, semitone_shift=semitone_shift, **kwargs) diff --git a/spleeter/utils/configuration.py b/spleeter/utils/configuration.py new file mode 100644 index 00000000..03db2009 --- /dev/null +++ b/spleeter/utils/configuration.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python +# coding: utf8 + +""" Module that provides configuration loading function. """ + +import json + +try: + import importlib.resources as loader +except ImportError: + # Try backported to PY<37 `importlib_resources`. + import importlib_resources as loader + +from os.path import exists + +from .. import resources + + +__email__ = 'research@deezer.com' +__author__ = 'Deezer Research' +__license__ = 'MIT License' + +_EMBEDDED_CONFIGURATION_PREFIX = 'spleeter:' + + +def load_configuration(descriptor): + """ Load configuration from the given descriptor. Could be + either a `spleeter:` prefixed embedded configuration name + or a file system path to read configuration from. + + :param descriptor: Configuration descriptor to use for lookup. + :returns: Loaded description as dict. + :raise ValueError: If required embedded configuration does not exists. + :raise IOError: If required configuration file does not exists. + """ + # Embedded configuration reading. + if descriptor.startswith(_EMBEDDED_CONFIGURATION_PREFIX): + name = descriptor[len(_EMBEDDED_CONFIGURATION_PREFIX):] + if not loader.is_resource(resources, f'{name}.json'): + raise ValueError(f'No embedded configuration {name} found') + with loader.open_text(resources, f'{name}.json') as stream: + return json.load(stream) + # Standard file reading. + if not exists(descriptor): + raise IOError(f'Configuration file {descriptor} not found') + with open(descriptor, 'r') as stream: + return json.load(stream) diff --git a/spleeter/utils/estimator.py b/spleeter/utils/estimator.py new file mode 100644 index 00000000..a908886f --- /dev/null +++ b/spleeter/utils/estimator.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python +# coding: utf8 + +""" Utility functions for creating estimator. """ + +from pathlib import Path + +# pylint: disable=import-error +import tensorflow as tf + +from tensorflow.contrib import predictor +# pylint: enable=import-error + +from ..model import model_fn +from ..model.provider import get_default_model_provider + +# Default exporting directory for predictor. +DEFAULT_EXPORT_DIRECTORY = '/tmp/serving' + + +def create_estimator(params, MWF): + """ + Initialize tensorflow estimator that will perform separation + + Params: + - params: a dictionnary of parameters for building the model + + Returns: + a tensorflow estimator + """ + # Load model. + model_directory = params['model_dir'] + model_provider = get_default_model_provider() + params['model_dir'] = model_provider.get(model_directory) + params['MWF'] = MWF + # Setup config + session_config = tf.compat.v1.ConfigProto() + session_config.gpu_options.per_process_gpu_memory_fraction = 0.7 + config = tf.estimator.RunConfig(session_config=session_config) + # Setup estimator + estimator = tf.estimator.Estimator( + model_fn=model_fn, + model_dir=params['model_dir'], + params=params, + config=config + ) + return estimator + + +def to_predictor(estimator, directory=DEFAULT_EXPORT_DIRECTORY): + """ Exports given estimator as predictor into the given directory + and returns associated tf.predictor instance. + + :param estimator: Estimator to export. + :param directory: (Optional) path to write exported model into. + """ + def receiver(): + shape = (None, estimator.params['n_channels']) + features = { + 'waveform': tf.compat.v1.placeholder(tf.float32, shape=shape), + 'audio_id': tf.compat.v1.placeholder(tf.string)} + return tf.estimator.export.ServingInputReceiver(features, features) + + estimator.export_saved_model(directory, receiver) + versions = [ + model for model in Path(directory).iterdir() + if model.is_dir() and 'temp' not in str(model)] + latest = str(sorted(versions)[-1]) + return predictor.from_saved_model(latest) diff --git a/spleeter/utils/logging.py b/spleeter/utils/logging.py new file mode 100644 index 00000000..031e0c34 --- /dev/null +++ b/spleeter/utils/logging.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python +# coding: utf8 + +""" Centralized logging facilities for Spleeter. """ + +from os import environ + +__email__ = 'research@deezer.com' +__author__ = 'Deezer Research' +__license__ = 'MIT License' + + +class _LoggerHolder(object): + """ Logger singleton instance holder. """ + + INSTANCE = None + + +def get_logger(): + """ Returns library scoped logger. + + :returns: Library logger. + """ + if _LoggerHolder.INSTANCE is None: + # pylint: disable=import-error + from tensorflow.compat.v1 import logging + # pylint: enable=import-error + _LoggerHolder.INSTANCE = logging + _LoggerHolder.INSTANCE.set_verbosity(_LoggerHolder.INSTANCE.ERROR) + environ['TF_CPP_MIN_LOG_LEVEL'] = '3' + return _LoggerHolder.INSTANCE + + +def enable_logging(): + """ Enable INFO level logging. """ + environ['TF_CPP_MIN_LOG_LEVEL'] = '1' + logger = get_logger() + logger.set_verbosity(logger.INFO) + + +def enable_verbose_logging(): + """ Enable DEBUG level logging. """ + environ['TF_CPP_MIN_LOG_LEVEL'] = '0' + logger = get_logger() + logger.set_verbosity(logger.DEBUG) diff --git a/spleeter/utils/tensor.py b/spleeter/utils/tensor.py new file mode 100644 index 00000000..402548c2 --- /dev/null +++ b/spleeter/utils/tensor.py @@ -0,0 +1,191 @@ +#!/usr/bin/env python +# coding: utf8 + +""" Utility function for tensorflow. """ + +# pylint: disable=import-error +import tensorflow as tf +import pandas as pd +# pylint: enable=import-error + +__email__ = 'research@deezer.com' +__author__ = 'Deezer Research' +__license__ = 'MIT License' + + +def sync_apply(tensor_dict, func, concat_axis=1): + """ Return a function that applies synchronously the provided func on the + provided dictionnary of tensor. This means that func is applied to the + concatenation of the tensors in tensor_dict. This is useful for performing + random operation that needs the same drawn value on multiple tensor, such + as a random time-crop on both input data and label (the same crop should be + applied to both input data and label, so random crop cannot be applied + separately on each of them). + + IMPORTANT NOTE: all tensor are assumed to be the same shape. + + Params: + - tensor_dict: dictionary (key: strings, values: tf.tensor) + a dictionary of tensor. + - func: function + function to be applied to the concatenation of the tensors in + tensor_dict + - concat_axis: int + The axis on which to perform the concatenation. + + Returns: + processed tensors dictionary with the same name (keys) as input + tensor_dict. + """ + if concat_axis not in {0, 1}: + raise NotImplementedError( + 'Function only implemented for concat_axis equal to 0 or 1') + tensor_list = list(tensor_dict.values()) + concat_tensor = tf.concat(tensor_list, concat_axis) + processed_concat_tensor = func(concat_tensor) + tensor_shape = tf.shape(list(tensor_dict.values())[0]) + D = tensor_shape[concat_axis] + if concat_axis == 0: + return { + name: processed_concat_tensor[index * D:(index + 1) * D, :, :] + for index, name in enumerate(tensor_dict) + } + return { + name: processed_concat_tensor[:, index * D:(index + 1) * D, :] + for index, name in enumerate(tensor_dict) + } + + +def from_float32_to_uint8( + tensor, + tensor_key='tensor', + min_key='min', + max_key='max'): + """ + + :param tensor: + :param tensor_key: + :param min_key: + :param max_key: + :returns: + """ + tensor_min = tf.reduce_min(tensor) + tensor_max = tf.reduce_max(tensor) + return { + tensor_key: tf.cast( + (tensor - tensor_min) / (tensor_max - tensor_min + 1e-16) + * 255.9999, dtype=tf.uint8), + min_key: tensor_min, + max_key: tensor_max + } + + +def from_uint8_to_float32(tensor, tensor_min, tensor_max): + """ + + :param tensor: + :param tensor_min: + :param tensor_max: + :returns: + """ + return ( + tf.cast(tensor, tf.float32) + * (tensor_max - tensor_min) + / 255.9999 + tensor_min) + + +def pad_and_partition(tensor, segment_len): + """ Pad and partition a tensor into segment of len segment_len + along the first dimension. The tensor is padded with 0 in order + to ensure that the first dimension is a multiple of segment_len. + + Tensor must be of known fixed rank + + :Example: + + >>> tensor = [[1, 2, 3], [4, 5, 6]] + >>> segment_len = 2 + >>> pad_and_partition(tensor, segment_len) + [[[1, 2], [4, 5]], [[3, 0], [6, 0]]] + + :param tensor: + :param segment_len: + :returns: + """ + tensor_size = tf.math.floormod(tf.shape(tensor)[0], segment_len) + pad_size = tf.math.floormod(segment_len - tensor_size, segment_len) + padded = tf.pad( + tensor, + [[0, pad_size]] + [[0, 0]] * (len(tensor.shape)-1)) + split = (tf.shape(padded)[0] + segment_len - 1) // segment_len + return tf.reshape( + padded, + tf.concat( + [[split, segment_len], tf.shape(padded)[1:]], + axis=0)) + + +def pad_and_reshape(instr_spec, frame_length, F): + """ + :param instr_spec: + :param frame_length: + :param F: + :returns: + """ + spec_shape = tf.shape(instr_spec) + extension_row = tf.zeros((spec_shape[0], spec_shape[1], 1, spec_shape[-1])) + n_extra_row = (frame_length) // 2 + 1 - F + extension = tf.tile(extension_row, [1, 1, n_extra_row, 1]) + extended_spec = tf.concat([instr_spec, extension], axis=2) + old_shape = tf.shape(extended_spec) + new_shape = tf.concat([ + [old_shape[0] * old_shape[1]], + old_shape[2:]], + axis=0) + processed_instr_spec = tf.reshape(extended_spec, new_shape) + return processed_instr_spec + + +def dataset_from_csv(csv_path, **kwargs): + """ Load dataset from a CSV file using Pandas. kwargs if any are + forwarded to the `pandas.read_csv` function. + + :param csv_path: Path of the CSV file to load dataset from. + :returns: Loaded dataset. + """ + df = pd.read_csv(csv_path, **kwargs) + dataset = ( + tf.data.Dataset.from_tensor_slices( + {key: df[key].values for key in df}) + ) + return dataset + + +def check_tensor_shape(tensor_tf, target_shape): + """ Return a Tensorflow boolean graph that indicates whether + sample[features_key] has the specified target shape. Only check + not None entries of target_shape. + + :param tensor_tf: Tensor to check shape for. + :param target_shape: Target shape to compare tensor to. + :returns: True if shape is valid, False otherwise (as TF boolean). + """ + result = tf.constant(True) + for i, target_length in enumerate(target_shape): + if target_length: + result = tf.logical_and( + result, + tf.equal(tf.constant(target_length), tf.shape(tensor_tf)[i])) + return result + + +def set_tensor_shape(tensor, tensor_shape): + """ Set shape for a tensor (not in place, as opposed to tf.set_shape) + + :param tensor: Tensor to reshape. + :param tensor_shape: Shape to apply to the tensor. + :returns: A reshaped tensor. + """ + # NOTE: That SOUND LIKE IN PLACE HERE ? + tensor.set_shape(tensor_shape) + return tensor