Giter VIP home page Giter VIP logo

Comments (8)

psobot avatar psobot commented on August 23, 2024 1

Hi @dschiller!

AUv3 support is not tested at the moment - the documentation does not explicitly list AUv3 anywhere (although the usage of the generic "Audio Unit" name may suggest that all Audio Units are supported). The JUCE framework that Pedalboard is built on does have support for hosting AUv3 plugins, so enabling support may just be a matter of adding a test plugin to the test suite and changing the code in AudioUnitParser.mm to properly support opening AUv3 bundles.

from pedalboard.

psobot avatar psobot commented on August 23, 2024 1

@dschiller Releases are ad-hoc when there are new features to release; this change is now available in v0.9.5. Thanks for the report!

from pedalboard.

dschiller avatar dschiller commented on August 23, 2024

Hey Peter, it looks like that the AU Parser already is aware of .appex AUv3 Apple App Extension format at https://github.com/spotify/pedalboard/blob/master/pedalboard/AudioUnitParser.mm#L81

from pedalboard.

dschiller avatar dschiller commented on August 23, 2024

I created a feature branch and try to build pedalboard locally

git clone https://github.com/spotify/pedalboard.git .
git checkout -b feature/add-auv3
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
pip install -r test-requirements.txt

I needed to download and install JUCE via

curl -LJO https://github.com/juce-framework/JUCE/releases/download/7.0.11/juce-7.0.11-osx.zip
tar -xf juce-7.0.11-osx.zip -o JUCE
rm juce-7.0.11-osx.zip

Other dependencies like Flac also missing:

rm -rf build; python setup.py develop

...
In file included from /Volumes/K2TB/Work/Coding/Python/Pedalboard/feature.add-auv3/pedalboard/juce_overrides/juce_PatchedFLACAudioFormat.cpp:139:
/Volumes/K2TB/Work/Coding/Python/Pedalboard/feature.add-auv3/pedalboard/juce_overrides/../../JUCE/modules/juce_audio_formats/codecs/flac/libFLAC/format.c:57:45: error: use of undeclared identifier 'PACKAGE_VERSION'
FLAC_API const char *FLAC__VERSION_STRING = PACKAGE_VERSION;
                                            ^
/Volumes/K2TB/Work/Coding/Python/Pedalboard/feature.add-auv3/pedalboard/juce_overrides/../../JUCE/modules/juce_audio_formats/codecs/flac/libFLAC/format.c:58:64: error: expected ';' after top level declarator
FLAC_API const char *FLAC__VENDOR_STRING = "reference libFLAC " PACKAGE_VERSION " 20230623";
                                                               ^
                                                               ;
In file included from /Volumes/K2TB/Work/Coding/Python/Pedalboard/feature.add-auv3/pedalboard/juce_overrides/juce_PatchedFLACAudioFormat.cpp:147:
/Volumes/K2TB/Work/Coding/Python/Pedalboard/feature.add-auv3/pedalboard/juce_overrides/../../vendors/libFLAC/metadata_object.c:41:10: fatal error: '../../JUCE/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/metadata.h' file not found
#include "../../JUCE/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/metadata.h"
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3 errors generated.
error: command '/usr/bin/clang' failed with exit code 1

How do you install the necessary dependencies ?

I checked the .github/workflows/all.yml file but couldn't find anything that installs Flac for example.

Possibly i am using the wrong JUCE version as there is no metadata.h header file in JUCE 7.0.11:

image

from pedalboard.

dschiller avatar dschiller commented on August 23, 2024

git submodule did the trick.

rm -rf JUCE
git submodule init
git submodule update
Submodule path 'JUCE': checked out 'ddaa09110392a4419fecbb6d3022bede89b7e841'
Submodule path 'vendors/lame': checked out '1f5cc9487284d5950343aa5d4f70de433468070a'
Submodule path 'vendors/libgsm': checked out '98f1708fb5e06a0dfebd58a3b40d610823db9715'
Submodule path 'vendors/pybind11': checked out '19a6b9f4efb569129c878b7f8db09132248fbaa1'
Submodule path 'vendors/rubberband': checked out '2be46b0dffb13273a67396c77bc9278736bb03d2'

from pedalboard.

dschiller avatar dschiller commented on August 23, 2024

In pedalboard/ExternalPlugin.h it seems typesFound stays empty when using .appex AUv3 with JUCE's findAllTypesForFile():

...
#if JUCE_PLUGINHOST_AU && JUCE_MAC
    if constexpr (std::is_same<ExternalPluginType,
                               juce::AudioUnitPluginFormat>::value) {
      auto identifiers = getAudioUnitIdentifiersFromFile(pluginFileStripped);
      // For each plugin in the identified bundle, scan using its AU identifier:
      for (int i = 0; i < identifiers.size(); i++) {
        std::cout << identifiers[i] << std::endl;
        format.findAllTypesForFile(typesFound, identifiers[i]);
      }
    } else {
      std::cout << pluginFileStripped << std::endl;
      format.findAllTypesForFile(typesFound, pluginFileStripped);
    }
#else
    std::cout << pluginFileStripped << std::endl;
    std::cout << typesFound << std::endl;
    format.findAllTypesForFile(typesFound, pluginFileStripped);
    std::cout << typesFound << std::endl;
#endif

    if (!typesFound.isEmpty()) {
      if (typesFound.size() == 1) {
        foundPluginDescription = *typesFound[0];
      } else if (typesFound.size() > 1) {
        std::string errorMessage =
            "Plugin file " + pathToPluginFile.toStdString() + " contains " +
            std::to_string(typesFound.size()) + " plugins";

        // Use the provided plugin name to disambiguate:
        if (pluginName) {
          for (int i = 0; i < typesFound.size(); i++) {
            if (typesFound[i]->name.toStdString() == *pluginName) {
              foundPluginDescription = *typesFound[i];
              break;
            }
          }

          if (foundPluginDescription.name.isEmpty()) {
            errorMessage += ", and the provided plugin_name \"" + *pluginName +
                            "\" matched no plugins. ";
          }
        } else {
          errorMessage += ". ";
        }

        if (foundPluginDescription.name.isEmpty()) {
          juce::StringArray pluginNames;
          for (int i = 0; i < typesFound.size(); i++) {
            pluginNames.add(typesFound[i]->name);
          }

          errorMessage +=
              ("To open a specific plugin within this file, pass a "
               "\"plugin_name\" parameter with one of the following "
               "values:\n\t\"" +
               pluginNames.joinIntoString("\"\n\t\"").toStdString() + "\"");
          throw std::domain_error(errorMessage);
        }
      }

      reinstantiatePlugin();
    } else {
      std::string errorMessage = "Unable to load plugin " +
                                 pathToPluginFile.toStdString() +
                                 ": unsupported plugin format or load failure.";
...

Do i need to use pluginkit in order to register my AUv3 Plug-In for macOS in order to load it via Pedalboard ?

pluginkit -a /Library/Audio/Plug-Ins/Components/auv3.appex
pluginkit -mv | grep -i modal
   F com.Native.ModalTests.ModalTestsAUv3(0.0.1)	00E61720-45F1-4929-9C98-D5D49D6BF989	2024-05-01 12:47:30 +0000	/Volumes/K2TB/Work/Coding/JUCE/ModalTests/Builds/ModalTests_artefacts/Release/Standalone/ModalTests.app/Contents/PlugIns/ModalTests.appex

Tried that but still typesFound is empty.

from pedalboard.

dschiller avatar dschiller commented on August 23, 2024

Also added tests at tests/test_external_plugins.py:

...
@pytest.mark.parametrize("plugin_filename", ONE_AVAILABLE_TEST_PLUGIN)
def test_get_plugin_name_from_regular_plugin(plugin_filename: str):
    plugin_path = find_plugin_path(plugin_filename)
    if ".vst3" in plugin_filename:
        names = pedalboard.VST3Plugin.get_plugin_names_for_file(plugin_path)
    elif ".component" in plugin_filename:
        names = pedalboard.AudioUnitPlugin.get_plugin_names_for_file(plugin_path)
    elif ".appex" in plugin_filename:
        names = pedalboard.AudioUnitPlugin.get_plugin_names_for_file(plugin_path)
    else:
        raise ValueError("Plugin does not seem to be a .vst3, .component or .appex.")

    assert len(names) == 1
    assert load_test_plugin(plugin_filename).name == names[0]

@pytest.mark.skipif(
    not AVAILABLE_CONTAINER_EFFECT_PLUGINS_IN_TEST_ENVIRONMENT,
    reason="No plugin containers installed in test environment!",
)
@pytest.mark.parametrize("plugin_filename", AVAILABLE_CONTAINER_EFFECT_PLUGINS_IN_TEST_ENVIRONMENT)
def test_get_plugin_names_from_container(plugin_filename: str):
    plugin_path = find_plugin_path(plugin_filename)
    if ".vst3" in plugin_filename:
        names = pedalboard.VST3Plugin.get_plugin_names_for_file(plugin_path)
    elif ".component" in plugin_filename:
        names = pedalboard.AudioUnitPlugin.get_plugin_names_for_file(plugin_path)
    elif ".appex" in plugin_filename:
        names = pedalboard.AudioUnitPlugin.get_plugin_names_for_file(plugin_path)
    else:
        raise ValueError("Plugin does not seem to be a .vst3, .component or .appex.")

    assert len(names) > 1
...

Of course AUv3 Plug-Ins need to be added to tests/plugins/effect/Darwin and tests/plugins/instrument/Darwin. -> Done

As expected those tests fail now:

pytest tests/test_external_plugins.py                     
================================================================= test session starts =================================================================
platform darwin -- Python 3.12.2, pytest-8.2.0, pluggy-1.5.0
rootdir: /Volumes/K2TB/Work/Coding/Python/Pedalboard/feature.add-auv3
configfile: tox.ini
plugins: cov-5.0.0, mock-3.14.0
collected 0 items / 1 error                                                                                                                           

======================================================================= ERRORS ========================================================================
___________________________________________________ ERROR collecting tests/test_external_plugins.py ___________________________________________________
ImportError while importing test module '/Volumes/K2TB/Work/Coding/Python/Pedalboard/feature.add-auv3/tests/test_external_plugins.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/opt/homebrew/Cellar/[email protected]/3.12.2_1/Frameworks/Python.framework/Versions/3.12/lib/python3.12/importlib/__init__.py:90: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
tests/test_external_plugins.py:334: in <module>
    for parameter in [k for k, v in get_parameters(path).items() if v.type == float]
tests/test_external_plugins.py:126: in get_parameters
    return load_test_plugin(plugin_filename).parameters
tests/test_external_plugins.py:182: in load_test_plugin
    raise exception
tests/test_external_plugins.py:176: in load_test_plugin
    plugin = pedalboard.load_plugin(plugin_path, *args, **kwargs)
pedalboard/_pedalboard.py:823: in load_plugin
    raise ImportError(
E   ImportError: Failed to load plugin as VST3Plugin or AudioUnitPlugin. Errors were:
E   	VST3Plugin: Unable to load plugin /Volumes/K2TB/Work/Coding/Python/Pedalboard/feature.add-auv3/tests/plugins/effect/Darwin/ModalTests.appex: unsupported plugin format or load failure.
E   	AudioUnitPlugin: Unable to load plugin /Volumes/K2TB/Work/Coding/Python/Pedalboard/feature.add-auv3/tests/plugins/effect/Darwin/ModalTests.appex: unsupported plugin format or load failure. macOS requires plugin files to be moved to /Library/Audio/Plug-Ins/Components/ or ~/Library/Audio/Plug-Ins/Components/ before loading.
------------------------------------------------------------------- Captured stdout -------------------------------------------------------------------
/Volumes/K2TB/Work/Coding/Python/Pedalboard/feature.add-auv3/tests/plugins/effect/Darwin/ModalTests.appex
/Volumes/K2TB/Work/Coding/Python/Pedalboard/feature.add-auv3/tests/plugins/effect/Darwin/ModalTests.appex
/Volumes/K2TB/Work/Coding/Python/Pedalboard/feature.add-auv3/tests/plugins/effect/Darwin/ModalTests.appex
/Volumes/K2TB/Work/Coding/Python/Pedalboard/feature.add-auv3/tests/plugins/effect/Darwin/ModalTests.appex
/Volumes/K2TB/Work/Coding/Python/Pedalboard/feature.add-auv3/tests/plugins/effect/Darwin/ModalTests.appex
=============================================================== short test summary info ===============================================================
ERROR tests/test_external_plugins.py
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
================================================================== 1 error in 10.50s ==================================================================

from pedalboard.

dschiller avatar dschiller commented on August 23, 2024

Thank you, Peter, for the fix! When do you regularly create releases?

from pedalboard.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.