From 3d1527989ebb6cd1211dd9302b7eca34a5a78db7 Mon Sep 17 00:00:00 2001 From: Frederic Font Date: Mon, 4 May 2026 14:08:12 +0200 Subject: [PATCH 01/19] Remove silence check in FreesoundExtractor Removed check for completely silent audio in FreesoundExtractor. There are files in Freesound which will be complete silence or almost silence, so it is fine to provide results for them as well. Also, this happens before descriptors have been computed, so it should not make things fail? I have to test that, for now making this PR and see how tests behave... --- src/algorithms/extractor/freesoundextractor.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/algorithms/extractor/freesoundextractor.cpp b/src/algorithms/extractor/freesoundextractor.cpp index 03d564285..df7137015 100644 --- a/src/algorithms/extractor/freesoundextractor.cpp +++ b/src/algorithms/extractor/freesoundextractor.cpp @@ -253,11 +253,6 @@ void FreesoundExtractor::compute() { E_INFO("FreesoundExtractor: Compute aggregation"); stats = computeAggregation(results); - // Check if whole audio is silence and raise exception if that is the case - if(stats.value("lowlevel.silence_rate_90dB.mean") == 1.0){ - throw EssentiaException("File looks like a completely silent file... Aborting..."); - } - if (options.value("highlevel.compute")) { #if HAVE_GAIA2 E_INFO("FreesoundExtractor: SVM models"); From d328c0b3f18f187b123733590b49304d2259aa8d Mon Sep 17 00:00:00 2001 From: Pablo Alonso Date: Tue, 5 May 2026 10:02:27 +0200 Subject: [PATCH 02/19] Use system's Python3 to build Essentia Before it was hardcoded to use python3.6, which is no longer installed in our manylinux images. --- cibuildwheel.toml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cibuildwheel.toml b/cibuildwheel.toml index 6c2c28791..ac2701b7d 100644 --- a/cibuildwheel.toml +++ b/cibuildwheel.toml @@ -8,11 +8,11 @@ skip = ["pp*", "*-musllinux*", "*i686", "*cp36*", "*cp37*", "*cp38*"] environment = { PROJECT_NAME="essentia", ESSENTIA_PROJECT_NAME="${PROJECT_NAME}", ESSENTIA_WHEEL_SKIP_3RDPARTY=1, ESSENTIA_WHEEL_ONLY_PYTHON=1 } +# Use system's Python3 to build Essentia. before-all = [ - "PYBIN=/opt/python/cp36-cp36m/bin/", - "\"${PYBIN}/python\" waf configure --with-gaia --build-static --static-dependencies --pkg-config-path=\"${PKG_CONFIG_PATH}\"", - "\"${PYBIN}/python\" waf", - "\"${PYBIN}/python\" waf install" + "python3 waf configure --with-gaia --build-static --static-dependencies --pkg-config-path=\"${PKG_CONFIG_PATH}\"", + "python3 waf", + "python3 waf install", ] test-command = "python -c 'import essentia; import essentia.standard; import essentia.streaming; from essentia.standard import MonoLoader, MetadataReader, YamlInput, Chromaprinter'" From 88e9098e2c6c0a0b758de8d1e8fe81dd122ac4e2 Mon Sep 17 00:00:00 2001 From: Pablo Alonso Date: Tue, 5 May 2026 10:09:28 +0200 Subject: [PATCH 03/19] Use system's py3 version in TensorFlow's cibuildwheel --- cibuildwheel-tensorflow.toml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cibuildwheel-tensorflow.toml b/cibuildwheel-tensorflow.toml index 1fc9bff57..0e2917b70 100644 --- a/cibuildwheel-tensorflow.toml +++ b/cibuildwheel-tensorflow.toml @@ -9,11 +9,11 @@ skip = ["pp*", "*-musllinux*", "*i686", "*cp36*", "*cp37*", "*cp38*"] environment = { PROJECT_NAME="essentia-tensorflow", ESSENTIA_PROJECT_NAME="${PROJECT_NAME}", ESSENTIA_WHEEL_SKIP_3RDPARTY=1, ESSENTIA_WHEEL_ONLY_PYTHON=1 } +# Use system's Python3 to build Essentia. before-all = [ - "PYBIN=/opt/python/cp36-cp36m/bin/", - "\"${PYBIN}/python\" waf configure --with-gaia --with-tensorflow --build-static --static-dependencies --pkg-config-path=\"${PKG_CONFIG_PATH}\"", - "\"${PYBIN}/python\" waf", - "\"${PYBIN}/python\" waf install", + "python3 waf configure --with-gaia --build-static --static-dependencies --pkg-config-path=\"${PKG_CONFIG_PATH}\"", + "python3 waf", + "python3 waf install", # Monkey-patch package name. # We could have a separate pyproject.toml configuration, but the build backend does not accept custom configuration filepaths. "sed 's/^name *= *\"essentia\"$/name = \"essentia-tensorflow\"/' pyproject.toml > pyproject.toml.patched && mv pyproject.toml.patched pyproject.toml" From 2707095df0f4d3bf1890cb331ec55a9932ad755e Mon Sep 17 00:00:00 2001 From: Pablo Alonso Date: Tue, 5 May 2026 11:07:10 +0200 Subject: [PATCH 04/19] Unpin brew's FFmpeg formula We don't need to use FFmpeg 2.8 as since #1494 we support FFmpeg 5+ --- cibuildwheel-tensorflow.toml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/cibuildwheel-tensorflow.toml b/cibuildwheel-tensorflow.toml index 0e2917b70..50287790c 100644 --- a/cibuildwheel-tensorflow.toml +++ b/cibuildwheel-tensorflow.toml @@ -30,10 +30,8 @@ environment = { PROJECT_NAME="essentia-tensorflow", ESSENTIA_PROJECT_NAME="${PRO before-all = [ "brew install pkg-config gcc readline sqlite gdbm freetype libpng", - "brew install eigen libyaml fftw ffmpeg@2.8 libsamplerate libtag", - "brew link --force ffmpeg@2.8", + "brew install eigen libyaml fftw ffmpeg libsamplerate libtag", "brew install chromaprint", - "brew link --overwrite ffmpeg@2.8", # Delocate checks for the min OS version (LC_BUILD_VERSION or C_VERSION_MIN_MACOSX). # Tensorflow bottle a has minimum target of 14.2 which is too new. # We could build from source as a workaround, however, it takes too much time on the CI worker. @@ -67,10 +65,8 @@ environment = { PROJECT_NAME="essentia-tensorflow", ESSENTIA_PROJECT_NAME="${PRO before-all = [ "brew install pkg-config gcc readline sqlite gdbm libpng", - "brew install eigen libyaml fftw ffmpeg@2.8 libsamplerate libtag", - "brew link --force ffmpeg@2.8", + "brew install eigen libyaml fftw ffmpeg libsamplerate libtag", "brew install chromaprint", - "brew link --overwrite ffmpeg@2.8", # Delocate checks for the min OS version (LC_BUILD_VERSION or C_VERSION_MIN_MACOSX). # Tensorflow bottle a has minimum target of 15.2 which is too new. # We could build from source as a workaround, however, it takes too much time on the CI worker. From 62e87d222cf127b1680bf67190e837c50624a220 Mon Sep 17 00:00:00 2001 From: Pablo Alonso Date: Tue, 5 May 2026 11:08:34 +0200 Subject: [PATCH 05/19] Bump c++11 -> c++14 Eigen 5.x (current Homebrew formula) requires C++14 features (std::enable_if_t, std::integer_sequence, etc.), causing build failures with the previous C++11 default. --- wscript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wscript b/wscript index a48d304c8..5cb65d590 100644 --- a/wscript +++ b/wscript @@ -47,7 +47,7 @@ def options(ctx): help='debug, release or default') ctx.add_option('--std', action='store', - dest='STD', default='c++11', + dest='STD', default='c++14', help='C++ standard to compile for [c++11 c++14 c++17 ...]') ctx.add_option('--arch', action='store', From e832aed83a432c4df4636080596478e27589373f Mon Sep 17 00:00:00 2001 From: Pablo Alonso Date: Tue, 5 May 2026 11:19:47 +0200 Subject: [PATCH 06/19] Unpin ffmpeg from the main cibuildwheel script --- cibuildwheel.toml | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/cibuildwheel.toml b/cibuildwheel.toml index ac2701b7d..227e246da 100644 --- a/cibuildwheel.toml +++ b/cibuildwheel.toml @@ -26,10 +26,7 @@ environment = { PROJECT_NAME="essentia", ESSENTIA_PROJECT_NAME="${PROJECT_NAME}" before-all = [ "brew install pkg-config gcc readline sqlite gdbm freetype libpng", - "brew install eigen libyaml fftw ffmpeg@2.8 libsamplerate libtag", - "brew link --force ffmpeg@2.8", - "brew install chromaprint", - "brew link --overwrite ffmpeg@2.8", + "brew install eigen libyaml fftw ffmpeg libsamplerate libtag chromaprint", #"brew tap MTG/essentia", #"brew install gaia --HEAD", # Override VIRTUAL_ENV set by cibuildwheel to ensure global install @@ -49,10 +46,7 @@ environment = { PROJECT_NAME="essentia", ESSENTIA_PROJECT_NAME="${PROJECT_NAME}" before-all = [ "brew install pkg-config gcc readline sqlite gdbm libpng", - "brew install eigen libyaml fftw ffmpeg@2.8 libsamplerate libtag", - "brew link --force ffmpeg@2.8", - "brew install chromaprint", - "brew link --overwrite ffmpeg@2.8", + "brew install eigen libyaml fftw ffmpeg libsamplerate libtag chromaprint", # Override VIRTUAL_ENV set by cibuildwheel to ensure global install "VIRTUAL_ENV=/usr/local python waf configure --pkg-config-path=\"${PKG_CONFIG_PATH}\" --arch arm64 --no-msse", "python waf", From f1cd09b9d5685865f6f708110efe4b5573d68d2b Mon Sep 17 00:00:00 2001 From: Pablo Alonso Date: Tue, 5 May 2026 11:32:06 +0200 Subject: [PATCH 07/19] Fix missing --with-tensorflow flag --- cibuildwheel-tensorflow.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cibuildwheel-tensorflow.toml b/cibuildwheel-tensorflow.toml index 50287790c..50c1b309c 100644 --- a/cibuildwheel-tensorflow.toml +++ b/cibuildwheel-tensorflow.toml @@ -11,7 +11,7 @@ environment = { PROJECT_NAME="essentia-tensorflow", ESSENTIA_PROJECT_NAME="${PRO # Use system's Python3 to build Essentia. before-all = [ - "python3 waf configure --with-gaia --build-static --static-dependencies --pkg-config-path=\"${PKG_CONFIG_PATH}\"", + "python3 waf configure --with-gaia --with-tensorflow --build-static --static-dependencies --pkg-config-path=\"${PKG_CONFIG_PATH}\"", "python3 waf", "python3 waf install", # Monkey-patch package name. From 9099c00fd77b8e9fe933ba5978f100ce0922c79e Mon Sep 17 00:00:00 2001 From: Pablo Alonso Date: Tue, 5 May 2026 14:28:39 +0200 Subject: [PATCH 08/19] =?UTF-8?q?Update=20MACOSX=5FDEPLOYMENT=5FTARGET=201?= =?UTF-8?q?5.2=20=E2=86=92=2015.4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update cibuildwheel-tensorflow.toml arm64 override: MACOSX_DEPLOYMENT_TARGET 15.2 → 15.4 (matching the current libtensorflow 2.20.0 bottle's minimum) --- cibuildwheel-tensorflow.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cibuildwheel-tensorflow.toml b/cibuildwheel-tensorflow.toml index 50c1b309c..9611e09e8 100644 --- a/cibuildwheel-tensorflow.toml +++ b/cibuildwheel-tensorflow.toml @@ -61,14 +61,14 @@ select = "*macosx_arm64*" skip = ["pp*", "*cp36*", "*cp37*", "*cp38*"] -environment = { PROJECT_NAME="essentia-tensorflow", ESSENTIA_PROJECT_NAME="${PROJECT_NAME}", ESSENTIA_WHEEL_SKIP_3RDPARTY=1, ESSENTIA_WHEEL_ONLY_PYTHON=1, ESSENTIA_MACOSX_ARM64=1, MACOSX_DEPLOYMENT_TARGET=15.2 } +environment = { PROJECT_NAME="essentia-tensorflow", ESSENTIA_PROJECT_NAME="${PROJECT_NAME}", ESSENTIA_WHEEL_SKIP_3RDPARTY=1, ESSENTIA_WHEEL_ONLY_PYTHON=1, ESSENTIA_MACOSX_ARM64=1, MACOSX_DEPLOYMENT_TARGET=15.4 } before-all = [ "brew install pkg-config gcc readline sqlite gdbm libpng", "brew install eigen libyaml fftw ffmpeg libsamplerate libtag", "brew install chromaprint", # Delocate checks for the min OS version (LC_BUILD_VERSION or C_VERSION_MIN_MACOSX). - # Tensorflow bottle a has minimum target of 15.2 which is too new. + # Tensorflow bottle has a minimum target of 15.4 which is too new. # We could build from source as a workaround, however, it takes too much time on the CI worker. # To keep it simple, just use the bottles available for tensorflow. "brew install tensorflow", From 7af5ca3ec2e2932b131f245aae7c19c9e8b16c2f Mon Sep 17 00:00:00 2001 From: Pablo Alonso Date: Tue, 5 May 2026 14:55:02 +0200 Subject: [PATCH 09/19] Use manylinux to build docs (experimental) Let's use the same pipeline in both workflows so that we don't have to fix deps individually everytime we change something. --- .github/workflows/build-docs.yml | 35 ++++++++++++++------------------ 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 903cafc8e..d7900ca5b 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -9,40 +9,35 @@ on: jobs: build-docs: runs-on: ubuntu-22.04 + container: + image: mtgupf/essentia-builds:manylinux2014_x86_64 steps: - uses: actions/checkout@v4 with: fetch-depth: 0 + - name: Fetch release tags from GitHub # Workaround for https://github.com/actions/checkout/issues/290 run: git fetch --tags --force - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get install -y build-essential libeigen3-dev libyaml-dev libfftw3-dev libavcodec-dev libavformat-dev libavutil-dev libswresample-dev libsamplerate0-dev libtag1-dev libchromaprint-dev python3-dev python3-numpy-dev python3-numpy python3-yaml python3-six - sudo apt-get install -y doxygen python3-pip pandoc - pip3 install sphinx pyparsing sphinxcontrib-doxylink docutils jupyter sphinx-toolbox nbformat gitpython sphinx-copybutton - # Install TensorFlow - sudo sh src/3rdparty/tensorflow/setup_from_libtensorflow.sh - # Install Gaia dependencies - sudo apt-get install qtbase5-dev swig pkg-config - - name: Build Gaia + + - name: Install documentation dependencies run: | - git clone https://github.com/MTG/gaia.git - cd gaia - python3 waf configure --with-python-bindings - python3 waf - sudo python3 waf install + python3 -m pip install --upgrade pip + python3 -m pip install sphinx pyparsing sphinxcontrib-doxylink docutils jupyter sphinx-toolbox nbformat gitpython sphinx-copybutton + yum install -y doxygen pandoc - name: Build Essentia - run: | - python3 waf configure --with-python --with-gaia --with-tensorflow + # Mirror the Linux before-all from cibuildwheel-tensorflow.toml so the + # docs build matches what the published wheels are built against. + run: | + python3 waf configure --with-python --with-gaia --with-tensorflow --build-static --static-dependencies --pkg-config-path="${PKG_CONFIG_PATH}" python3 waf + python3 waf install - name: Build documentation - run: | - python3 waf doc + run: python3 waf doc + - name: Upload built documentation uses: actions/upload-artifact@v4 with: From 1465097bd2ab36b0068bc0751f4861e6b1863bcf Mon Sep 17 00:00:00 2001 From: Pablo Alonso Date: Tue, 5 May 2026 16:17:34 +0200 Subject: [PATCH 10/19] Run doc workflow inside Ubuntu instead of ManyLinix This avoids running checkout@v4, which depends on Node 20 on Centos7 as it is not supported. Build doc inside docker to mimic the cibuildwheel behaviour. --- .github/workflows/build-docs.yml | 35 +++++++++++++++++--------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index d7900ca5b..a17567681 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -9,8 +9,6 @@ on: jobs: build-docs: runs-on: ubuntu-22.04 - container: - image: mtgupf/essentia-builds:manylinux2014_x86_64 steps: - uses: actions/checkout@v4 @@ -21,22 +19,27 @@ jobs: # Workaround for https://github.com/actions/checkout/issues/290 run: git fetch --tags --force - - name: Install documentation dependencies + - name: Build Essentia and documentation + # Run inside the same image used by cibuildwheel.toml so the + # docs are generated against the same toolchain and static deps as the + # published wheels. We invoke Docker manually (rather than via the job's + # `container:`) because manylinux2014 ships glibc 2.17, which is too old + # for the Node 20 runtime that GitHub Actions injects into containers. run: | - python3 -m pip install --upgrade pip - python3 -m pip install sphinx pyparsing sphinxcontrib-doxylink docutils jupyter sphinx-toolbox nbformat gitpython sphinx-copybutton - yum install -y doxygen pandoc + docker run --rm \ + -v "${PWD}:/project" \ + -w /project \ + mtgupf/essentia-builds:manylinux2014_x86_64 \ + bash -euxc ' + python3 -m pip install --upgrade pip + python3 -m pip install sphinx pyparsing sphinxcontrib-doxylink docutils jupyter sphinx-toolbox nbformat gitpython sphinx-copybutton + yum install -y doxygen pandoc - - name: Build Essentia - # Mirror the Linux before-all from cibuildwheel-tensorflow.toml so the - # docs build matches what the published wheels are built against. - run: | - python3 waf configure --with-python --with-gaia --with-tensorflow --build-static --static-dependencies --pkg-config-path="${PKG_CONFIG_PATH}" - python3 waf - python3 waf install - - - name: Build documentation - run: python3 waf doc + python3 waf configure --with-python --with-gaia --with-tensorflow --build-static --static-dependencies --pkg-config-path="${PKG_CONFIG_PATH}" + python3 waf + python3 waf install + python3 waf doc + ' - name: Upload built documentation uses: actions/upload-artifact@v4 From 9dc0d4192e69f5451e6557815ee24a1e09e6973a Mon Sep 17 00:00:00 2001 From: Pablo Alonso Date: Tue, 5 May 2026 16:30:25 +0200 Subject: [PATCH 11/19] Mark project/ as safe for git to prevent exception --- .github/workflows/build-docs.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index a17567681..8f553b818 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -31,6 +31,10 @@ jobs: -w /project \ mtgupf/essentia-builds:manylinux2014_x86_64 \ bash -euxc ' + # Repo is bind-mounted from the host runner; container runs as + # root, so git refuses to touch it without this exception. + git config --global --add safe.directory /project + python3 -m pip install --upgrade pip python3 -m pip install sphinx pyparsing sphinxcontrib-doxylink docutils jupyter sphinx-toolbox nbformat gitpython sphinx-copybutton yum install -y doxygen pandoc From 0716f5dcb423409717ffd2ee754841e1e0a2b654 Mon Sep 17 00:00:00 2001 From: Pablo Alonso Date: Tue, 5 May 2026 17:39:23 +0200 Subject: [PATCH 12/19] Bump macos intel runner version mac-13 --> mac-15-intel. mac-13 is deprecated. https://github.com/actions/runner-images/blob/main/images/macos/macos-15-Readme.md --- .github/workflows/build-wheels-cibuildwheel.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-wheels-cibuildwheel.yml b/.github/workflows/build-wheels-cibuildwheel.yml index 117c88364..3317faa05 100644 --- a/.github/workflows/build-wheels-cibuildwheel.yml +++ b/.github/workflows/build-wheels-cibuildwheel.yml @@ -8,7 +8,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [ubuntu-22.04, macos-13, macos-15] + os: [ubuntu-22.04, macos-15-intel, macos-15] config: [cibuildwheel, cibuildwheel-tensorflow] steps: From d391ccbfb82ff3547a812851cb48b97c5fc5ff71 Mon Sep 17 00:00:00 2001 From: Pablo Alonso Date: Tue, 5 May 2026 17:49:57 +0200 Subject: [PATCH 13/19] Bump MACOSX_DEPLOYMENT_TARGET for the intel wheels - 15.0 for the normal wheels as required by libcrypto.3.dylib and libssl.3.dylib - 15.2 for the tensorflow wheels as required by libtensorflow --- cibuildwheel-tensorflow.toml | 2 +- cibuildwheel.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cibuildwheel-tensorflow.toml b/cibuildwheel-tensorflow.toml index 9611e09e8..8efc2ac68 100644 --- a/cibuildwheel-tensorflow.toml +++ b/cibuildwheel-tensorflow.toml @@ -26,7 +26,7 @@ test-command = "python -c 'import essentia; import essentia.standard; import ess skip = ["pp*", "*cp36*", "*cp37*", "*cp38*"] -environment = { PROJECT_NAME="essentia-tensorflow", ESSENTIA_PROJECT_NAME="${PROJECT_NAME}", ESSENTIA_WHEEL_SKIP_3RDPARTY=1, ESSENTIA_WHEEL_ONLY_PYTHON=1, MACOSX_DEPLOYMENT_TARGET=14.2 } +environment = { PROJECT_NAME="essentia-tensorflow", ESSENTIA_PROJECT_NAME="${PROJECT_NAME}", ESSENTIA_WHEEL_SKIP_3RDPARTY=1, ESSENTIA_WHEEL_ONLY_PYTHON=1, MACOSX_DEPLOYMENT_TARGET=15.2 } before-all = [ "brew install pkg-config gcc readline sqlite gdbm freetype libpng", diff --git a/cibuildwheel.toml b/cibuildwheel.toml index 227e246da..f4af3563b 100644 --- a/cibuildwheel.toml +++ b/cibuildwheel.toml @@ -22,7 +22,7 @@ test-command = "python -c 'import essentia; import essentia.standard; import ess skip = ["pp*", "*cp36*", "*cp37*", "*cp38*"] -environment = { PROJECT_NAME="essentia", ESSENTIA_PROJECT_NAME="${PROJECT_NAME}", ESSENTIA_WHEEL_SKIP_3RDPARTY=1, ESSENTIA_WHEEL_ONLY_PYTHON=1, MACOSX_DEPLOYMENT_TARGET=13.0 } +environment = { PROJECT_NAME="essentia", ESSENTIA_PROJECT_NAME="${PROJECT_NAME}", ESSENTIA_WHEEL_SKIP_3RDPARTY=1, ESSENTIA_WHEEL_ONLY_PYTHON=1, MACOSX_DEPLOYMENT_TARGET=15.0 } before-all = [ "brew install pkg-config gcc readline sqlite gdbm freetype libpng", From eb4a059f6e8eb0b38f2f7c49958a073a46709548 Mon Sep 17 00:00:00 2001 From: Pablo Alonso Date: Tue, 5 May 2026 18:08:27 +0200 Subject: [PATCH 14/19] Fix comment --- cibuildwheel-tensorflow.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cibuildwheel-tensorflow.toml b/cibuildwheel-tensorflow.toml index 8efc2ac68..09c7149cf 100644 --- a/cibuildwheel-tensorflow.toml +++ b/cibuildwheel-tensorflow.toml @@ -33,7 +33,7 @@ before-all = [ "brew install eigen libyaml fftw ffmpeg libsamplerate libtag", "brew install chromaprint", # Delocate checks for the min OS version (LC_BUILD_VERSION or C_VERSION_MIN_MACOSX). - # Tensorflow bottle a has minimum target of 14.2 which is too new. + # Tensorflow bottle has a minimum target of 15.2 which is too new. # We could build from source as a workaround, however, it takes too much time on the CI worker. # To keep it simple, just use the bottles available for tensorflow. "brew install tensorflow", From 72af688503b02997a94ad613984d436da1d08c66 Mon Sep 17 00:00:00 2001 From: Pablo Alonso Date: Tue, 5 May 2026 18:17:31 +0200 Subject: [PATCH 15/19] Bump workflow versions Let's take the opportunity to bump our tooling: - ubuntu22.04 --> ubuntu24.04 - checkout v4 --> v6 - cibuildwheel v2.23 -> v3.2 - upload-artifact v4 -> v5 --- .github/workflows/build-docs.yml | 4 ++-- .github/workflows/build-wheels-cibuildwheel.yml | 8 ++++---- .github/workflows/build-wheels.yml | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 8f553b818..221bc120b 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -8,10 +8,10 @@ on: - master jobs: build-docs: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: fetch-depth: 0 diff --git a/.github/workflows/build-wheels-cibuildwheel.yml b/.github/workflows/build-wheels-cibuildwheel.yml index 3317faa05..62f8f942e 100644 --- a/.github/workflows/build-wheels-cibuildwheel.yml +++ b/.github/workflows/build-wheels-cibuildwheel.yml @@ -8,11 +8,11 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [ubuntu-22.04, macos-15-intel, macos-15] + os: [ubuntu-24.04, macos-15-intel, macos-15] config: [cibuildwheel, cibuildwheel-tensorflow] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: fetch-depth: 0 @@ -21,11 +21,11 @@ jobs: run: git fetch --tags --force - name: Build wheels - uses: pypa/cibuildwheel@v2.23.2 + uses: pypa/cibuildwheel@v3.2.1 with: config-file: ${{ matrix.config }}.toml - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v5 with: path: ./wheelhouse/*.whl name: artifact-${{ matrix.os }}-${{ matrix.config }} diff --git a/.github/workflows/build-wheels.yml b/.github/workflows/build-wheels.yml index 6f7ddbe57..1702bfaa6 100644 --- a/.github/workflows/build-wheels.yml +++ b/.github/workflows/build-wheels.yml @@ -32,16 +32,16 @@ jobs: PRE_CMD: ${{ matrix.PRE_CMD }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: fetch-depth: 0 - name: Fetch release tags from GitHub # Workaround for https://github.com/actions/checkout/issues/290 run: git fetch --tags --force - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v6 with: - python-version: 3.8 + python-version: '3.12' - name: Build wheels in a Docker image run: | docker pull $DOCKER_IMAGE > /dev/null @@ -51,7 +51,7 @@ jobs: ls wheelhouse/ sudo python setup.py sdist - name: Upload wheels and sdist - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: essentia-python-wheels path: | From 49239c0de2f3c92a946c1c475d397d1bcde0b0d5 Mon Sep 17 00:00:00 2001 From: Pablo Alonso Date: Tue, 5 May 2026 18:44:45 +0200 Subject: [PATCH 16/19] Update build skip selectors - cp38: project does not target Python 3.8. - *t-*: free-threaded (no-GIL) builds. The Essentia C bindings rely on legacy PyTypeObject definitions that fail to instantiate under cp313t/cp314t ("Type does not define the tp_name field"). Re-enable once the bindings are audited for free-threading compatibility. - *-musllinux*, *i686: not supported by our manylinux2014 build images. --- cibuildwheel-tensorflow.toml | 15 ++++++++++++--- cibuildwheel.toml | 15 ++++++++++++--- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/cibuildwheel-tensorflow.toml b/cibuildwheel-tensorflow.toml index 09c7149cf..c58176cf8 100644 --- a/cibuildwheel-tensorflow.toml +++ b/cibuildwheel-tensorflow.toml @@ -5,7 +5,14 @@ manylinux-x86_64-image = "mtgupf/essentia-builds:manylinux2014_x86_64" # Only support x86_64 for essentia-tensorflow. build = "cp**-manylinux_x86_64" -skip = ["pp*", "*-musllinux*", "*i686", "*cp36*", "*cp37*", "*cp38*"] +# Skip selectors: +# - cp38: project does not target Python 3.8. +# - *t-*: free-threaded (no-GIL) builds. The Essentia C bindings rely on +# legacy PyTypeObject definitions that fail to instantiate under +# cp313t/cp314t ("Type does not define the tp_name field"). Re-enable +# once the bindings are audited for free-threading compatibility. +# - *-musllinux*, *i686: not supported by our manylinux2014 build images. +skip = ["*cp38*", "*t-*", "*-musllinux*", "*i686"] environment = { PROJECT_NAME="essentia-tensorflow", ESSENTIA_PROJECT_NAME="${PROJECT_NAME}", ESSENTIA_WHEEL_SKIP_3RDPARTY=1, ESSENTIA_WHEEL_ONLY_PYTHON=1 } @@ -24,7 +31,8 @@ test-command = "python -c 'import essentia; import essentia.standard; import ess [tool.cibuildwheel.macos] -skip = ["pp*", "*cp36*", "*cp37*", "*cp38*"] +# See linux section for skip rationale. +skip = ["*cp38*", "*t-*"] environment = { PROJECT_NAME="essentia-tensorflow", ESSENTIA_PROJECT_NAME="${PROJECT_NAME}", ESSENTIA_WHEEL_SKIP_3RDPARTY=1, ESSENTIA_WHEEL_ONLY_PYTHON=1, MACOSX_DEPLOYMENT_TARGET=15.2 } @@ -59,7 +67,8 @@ before-all = [ [[tool.cibuildwheel.overrides]] select = "*macosx_arm64*" -skip = ["pp*", "*cp36*", "*cp37*", "*cp38*"] +# See linux section for skip rationale. +skip = ["*cp38*", "*t-*"] environment = { PROJECT_NAME="essentia-tensorflow", ESSENTIA_PROJECT_NAME="${PROJECT_NAME}", ESSENTIA_WHEEL_SKIP_3RDPARTY=1, ESSENTIA_WHEEL_ONLY_PYTHON=1, ESSENTIA_MACOSX_ARM64=1, MACOSX_DEPLOYMENT_TARGET=15.4 } diff --git a/cibuildwheel.toml b/cibuildwheel.toml index f4af3563b..b51717c56 100644 --- a/cibuildwheel.toml +++ b/cibuildwheel.toml @@ -4,7 +4,14 @@ manylinux-x86_64-image = "mtgupf/essentia-builds:manylinux2014_x86_64" manylinux-i686-image = "mtgupf/essentia-builds:manylinux2014_i686" -skip = ["pp*", "*-musllinux*", "*i686", "*cp36*", "*cp37*", "*cp38*"] +# Skip selectors: +# - cp38: project does not target Python 3.8. +# - *t-*: free-threaded (no-GIL) builds. The Essentia C bindings rely on +# legacy PyTypeObject definitions that fail to instantiate under +# cp313t/cp314t ("Type does not define the tp_name field"). Re-enable +# once the bindings are audited for free-threading compatibility. +# - *-musllinux*, *i686: not supported by our manylinux2014 build images. +skip = ["*cp38*", "*t-*", "*-musllinux*", "*i686"] environment = { PROJECT_NAME="essentia", ESSENTIA_PROJECT_NAME="${PROJECT_NAME}", ESSENTIA_WHEEL_SKIP_3RDPARTY=1, ESSENTIA_WHEEL_ONLY_PYTHON=1 } @@ -20,7 +27,8 @@ test-command = "python -c 'import essentia; import essentia.standard; import ess [tool.cibuildwheel.macos] -skip = ["pp*", "*cp36*", "*cp37*", "*cp38*"] +# See linux section for skip rationale. +skip = ["*cp38*", "*t-*"] environment = { PROJECT_NAME="essentia", ESSENTIA_PROJECT_NAME="${PROJECT_NAME}", ESSENTIA_WHEEL_SKIP_3RDPARTY=1, ESSENTIA_WHEEL_ONLY_PYTHON=1, MACOSX_DEPLOYMENT_TARGET=15.0 } @@ -40,7 +48,8 @@ test-command = "python -c 'import essentia; import essentia.standard; import ess [[tool.cibuildwheel.overrides]] select = "*macosx_arm64*" -skip = ["pp*", "*cp36*", "*cp37*", "*cp38*"] +# See linux section for skip rationale. +skip = ["*cp38*", "*t-*"] environment = { PROJECT_NAME="essentia", ESSENTIA_PROJECT_NAME="${PROJECT_NAME}", ESSENTIA_WHEEL_SKIP_3RDPARTY=1, ESSENTIA_WHEEL_ONLY_PYTHON=1, ESSENTIA_MACOSX_ARM64=1, MACOSX_DEPLOYMENT_TARGET=15.0 } From 42c5a6fb77e4b9e0f24621ea6f0d4668a4efd592 Mon Sep 17 00:00:00 2001 From: Pablo Alonso Date: Tue, 5 May 2026 19:06:32 +0200 Subject: [PATCH 17/19] Bump upload-artifact to v6 Since Node.js 20 actions are deprecated --- .github/workflows/build-docs.yml | 2 +- .github/workflows/build-wheels-cibuildwheel.yml | 2 +- .github/workflows/build-wheels.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 221bc120b..e2a0748af 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -46,7 +46,7 @@ jobs: ' - name: Upload built documentation - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: essentia-docs path: | diff --git a/.github/workflows/build-wheels-cibuildwheel.yml b/.github/workflows/build-wheels-cibuildwheel.yml index 62f8f942e..88327885c 100644 --- a/.github/workflows/build-wheels-cibuildwheel.yml +++ b/.github/workflows/build-wheels-cibuildwheel.yml @@ -25,7 +25,7 @@ jobs: with: config-file: ${{ matrix.config }}.toml - - uses: actions/upload-artifact@v5 + - uses: actions/upload-artifact@v6 with: path: ./wheelhouse/*.whl name: artifact-${{ matrix.os }}-${{ matrix.config }} diff --git a/.github/workflows/build-wheels.yml b/.github/workflows/build-wheels.yml index 1702bfaa6..438d0c9e6 100644 --- a/.github/workflows/build-wheels.yml +++ b/.github/workflows/build-wheels.yml @@ -51,7 +51,7 @@ jobs: ls wheelhouse/ sudo python setup.py sdist - name: Upload wheels and sdist - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: essentia-python-wheels path: | From 63eb43b4f895e6ebab87ac41812cfdca4a89f0b0 Mon Sep 17 00:00:00 2001 From: ffont Date: Thu, 7 May 2026 17:32:14 +0200 Subject: [PATCH 18/19] Proper implementation of sim vector computation --- src/algorithms/extractor/freesoundextractor.cpp | 9 +++++++-- .../FreesoundSimSpaceDescriptorsData.h | 14 ++++---------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/algorithms/extractor/freesoundextractor.cpp b/src/algorithms/extractor/freesoundextractor.cpp index d202b737b..9abea4e3a 100644 --- a/src/algorithms/extractor/freesoundextractor.cpp +++ b/src/algorithms/extractor/freesoundextractor.cpp @@ -582,8 +582,13 @@ void FreesoundExtractor::computeSimilarityVector(Pool& results) { const string& descName = simSpaceDescriptorNames[i]; int expectedDim = simSpaceDescriptorDimensions[i]; - if (results.contains >(descName)) { - vector descValues = results.value >(descName); + if (results.contains >(descName) || results.contains(descName)) { + vector descValues; + if (results.contains >(descName)) { + descValues = results.value >(descName); + } else { + descValues.push_back(results.value(descName)); + } // check if this is a "barkbands" descriptor and if it has one dimension less than expected, in which case we repeat the penultimate value at the end if (descName.find("barkbands") != string::npos && (int)descValues.size() == expectedDim - 1) { descValues.push_back(descValues[descValues.size() - 1]); diff --git a/src/essentia/utils/extractor_freesound/FreesoundSimSpaceDescriptorsData.h b/src/essentia/utils/extractor_freesound/FreesoundSimSpaceDescriptorsData.h index 3211f7c65..2d9616219 100644 --- a/src/essentia/utils/extractor_freesound/FreesoundSimSpaceDescriptorsData.h +++ b/src/essentia/utils/extractor_freesound/FreesoundSimSpaceDescriptorsData.h @@ -55,16 +55,10 @@ inline const std::vector kSimSpaceDescriptorNames = { }; inline const std::vector kSimSpaceDescriptorDimensions = { - 27, 27, 27, 27, 27, 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 18, 18, 18, 18, 18, 18, 28, 28, 28, 28, 28, 28, 13, 13, 13, - 13, 13, 13, 1, 1, 1, 1, 1, 1, 13, 13, 13, 13, 13, 13, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, - 6, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1 + 27, 27, 27, 27, 27, 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 18, 18, 18, 18, 18, 28, 28, 28, 28, 28, 28, 13, 13, 13, 13, 13, 13, 1, 1, 1, 1, 1, 1, + 13, 13, 13, 13, 13, 13, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 6, 6, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; inline const std::vector> kSimSpaceDescriptorACoefficients = { From 1fd392939ed955c1f77badf10c2c3ae2e6e32477 Mon Sep 17 00:00:00 2001 From: ffont Date: Fri, 8 May 2026 11:09:23 +0200 Subject: [PATCH 19/19] Add post-processing of results in fs extractor --- .../extractor/freesoundextractor.cpp | 70 ++++++++++++++++++- src/algorithms/extractor/freesoundextractor.h | 1 + 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/src/algorithms/extractor/freesoundextractor.cpp b/src/algorithms/extractor/freesoundextractor.cpp index 9abea4e3a..f959480f9 100644 --- a/src/algorithms/extractor/freesoundextractor.cpp +++ b/src/algorithms/extractor/freesoundextractor.cpp @@ -273,6 +273,8 @@ void FreesoundExtractor::compute() { computeSimilarityVector(stats); } + postProcessResultsPool(stats); + if (options.value("highlevel.compute")) { #if HAVE_GAIA2 E_INFO("FreesoundExtractor: SVM models"); @@ -572,6 +574,10 @@ void FreesoundExtractor::computeReplayGain(const string& audioFilename, Pool& re void FreesoundExtractor::computeSimilarityVector(Pool& results) { + // This methods takes as input the pool of results including aggregated descriptors and computes a 100-dimensional vector representation + // by projecting a specific set of descriptors onto a PCA space. The resulting embedding space is the one used in the Freesound for + // "classic" similarity search. + // 1) Iterate over all descriptor names from simSpaceDescriptorNames, retrieve their values from the pool, and concatenate them in a single vector // For compatibility with the legacy Freesound classic space computed with older extractors, there's a modification we need to make for the "barkbands" descriptors: we need // to repeat the penultimate value at the very end of each barkband vector, so they get 1 more dimension @@ -609,7 +615,7 @@ void FreesoundExtractor::computeSimilarityVector(Pool& results) { } } - // Project raw descriptor vector (N=843) onto PCA space (N x 100) to get a 100-D sim vector. + // 2) Project raw descriptor vector (N=843) onto PCA space (N x 100) to get a 100-D sim vector. vector simVectorProjected; if (simSpacePCAMatrix.empty()) { simVectorProjected.assign(100, 0.0); @@ -630,6 +636,68 @@ void FreesoundExtractor::computeSimilarityVector(Pool& results) { results.set("sim_vector", simVectorProjected); } +void FreesoundExtractor::postProcessResultsPool(Pool& results) { + // This method takes as input the pool of results with aggregated descriptors and does some minor post-processing to make descriptors + // ready for indexing in Freesound. + + // Create a new lowlevel.sound_start_time descriptor based on lowlevel.sound_start_frame by converting from frames to seconds using the + // analysis hop size and sample rate. This is needed for Freesound indexing. + if (results.contains("lowlevel.sound_start_frame")) { + Real startFrame = results.value("lowlevel.sound_start_frame"); + Real startTime = startFrame * lowlevelHopSize / analysisSampleRate; + results.set("lowlevel.sound_start_time", startTime); + } + + // Create a new lowlevel.sound_stop_time descriptor based on lowlevel.sound_stop_frame + if (results.contains("lowlevel.sound_stop_frame")) { + Real stopFrame = results.value("lowlevel.sound_stop_frame"); + Real stopTime = stopFrame * lowlevelHopSize / analysisSampleRate; + results.set("lowlevel.sound_stop_time", stopTime); + } + + // Add post-processed tempo-related descriptors + if (results.contains("rhythm.bpm_loop_confidence")) { + bool isLoop = results.value("rhythm.bpm_loop_confidence") > 0.95; + results.set("fs.loopable", isLoop); + if (isLoop) { + // We use bpm_loop descriptors to set tempo and tempo confidence + int tempo = static_cast(round(results.value("rhythm.bpm_loop"))); + results.set("fs.bpm", tempo); + results.set("fs.bpm_confidence", results.value("rhythm.bpm_loop_confidence")); + } else { + // We use bpm descriptors to set tempo and tempo confidence + // Tempo confidence requires some extra normalisation as vale goes typically from 0 to 5.0 + // Also make sure confidence is between 0 and 1 + int tempo = static_cast(round(results.value("rhythm.bpm"))); + results.set("fs.bpm", tempo); + float confidence = results.value("rhythm.bpm_confidence") / 5.0; + confidence = std::min(std::max(confidence, 0.0f), 1.0f); + results.set("fs.bpm_confidence", confidence); + } + } + + // Add post-processed note-related descriptors + if (results.contains("lowlevel.pitch.median")) { + // Convert pitch from Hz to MIDI + Real pitchHz = results.value("lowlevel.pitch.median"); + results.set("fs.note_frequency", pitchHz); + int pitchMidi = 69 + 12 * log2(pitchHz / 440.0); + results.set("fs.note_midi", pitchMidi); + int note_number = pitchMidi % 12; + int octave = pitchMidi / 12; + static const char* noteNames[] = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"}; + string noteName = noteNames[note_number] + to_string(octave - 1); + results.set("fs.note_name", noteName); + results.set("fs.note_confidence", results.value("lowlevel.pitch_instantaneous_confidence.median")); + } + + // Add post-processed tonality-related descriptors + if (results.contains("tonal.key_key")) { + results.set("fs.tonality", results.value("tonal.key_key") + " " + results.value("tonal.key_scale")); + results.set("fs.tonality_confidence", results.value("tonal.key_strength")); + } +} + void FreesoundExtractor::setExtractorOptions(const std::string& filename) { diff --git a/src/algorithms/extractor/freesoundextractor.h b/src/algorithms/extractor/freesoundextractor.h index febd0159d..dbbfcfa44 100644 --- a/src/algorithms/extractor/freesoundextractor.h +++ b/src/algorithms/extractor/freesoundextractor.h @@ -91,6 +91,7 @@ class FreesoundExtractor : public Algorithm { void computeAudioMetadata(const std::string& audioFilename, Pool& results); void computeReplayGain(const std::string& audioFilename, Pool& results); void computeSimilarityVector(Pool& results); + void postProcessResultsPool(Pool& results); Pool computeAggregation(Pool& pool);