PedalPi / PluginsManager

Pythonic management of LV2 audio plugins with mod-host
http://pedalpi-pluginsmanager.readthedocs.io/
Apache License 2.0
12 stars 5 forks source link

[Carla] Add carla support #91

Open SrMouraSilva opened 6 years ago

SrMouraSilva commented 6 years ago

Continues #64.

Carla informations

@srmourasilva

Possuo uma dúvida sobre o seu projeto Carla. Observei na página do projeto que possui suporte à diversas APIs de plugins de áudio, fato muito interessante. Gostaria de saber se Carla possui alguma forma de uso similar ao mod-host, de modo que seja possível enviar comandos para carregar plugins, adicionar conexões e alterar parâmetros sem a necessidade de exibir uma interface gráfica.

mod-host oferece uma abertura para seu controle através de socket, como você bem sabe. Pensei que Carla tivesse uma API em python para este fim, entretanto não consegui localizar no código fonte (o mais próximo que encontrei aparenta ser o suporte à OSC (https://github.com/falkTX/Carla/blob/e07f144bdcd11d95c8d3fa125d9c4f7e55022c77/source/carla_control.py#L140)).

Se possível, você poderia comentar sobre?


Response:

@falktx

Ola.

O carla tem acesso à backend via ctypes. Ta aqui https://github.com/falkTX/Carla/blob/master/source/carla_backend.py

O que implementa a parte em C do carla que esta definida em https://github.com/falkTX/Carla/blob/master/source/backend/CarlaBackend.h e https://github.com/falkTX/Carla/blob/master/source/backend/CarlaHost.h

Um exemplo que carrega um plugin via python esta aqui: https://github.com/falkTX/Carla/blob/master/source/tests/carla-uhe-test.py

Installation

https://github.com/falkTX/Carla/blob/master/INSTALL.md

(make features to find out which dependencies are missing)

Example scripts

Tasks

Add Effect: https://gist.github.com/SrMouraSilva/ca944c89e577df26ae0f813fa886f475#file-carla-host-py-L41 See Rest: https://github.com/falkTX/Carla/blob/2e368e0acaa98d592b0e223eb5283039357d335c/source/rest/rest-server.cpp

SrMouraSilva commented 6 years ago

More messages

Obrigado pelas respostas! Foram de grande ajuda. Poderei assim começar os trabalhos para PluginsManager - uma biblioteca na qual estou desenvolvendo - possa dar suporte à Carla.

Boa! O Carla ta em constante desenvolvimento, mas a API base the backend nao deve mudar mesmo que muitas coisas internas mudem. A parte que nao está finalizada neste momento é transport, isso vai mudar ainda.

Por enquanto, fiquei sem entender como conectar os plugins de áudio. Também não possuo ideia de como obter informações de um plugin de áudio (metadata) sem ter que carregá-lo em Carla. Com lv2, utilizo lilvlib.

Ah sim, esqueci dessa parte. Para plugins internos, LV2 e AU (AU so para MacOS), podes usar carla-utils. API python: https://github.com/falkTX/Carla/blob/master/source/carla_utils.py API em C:https://github.com/falkTX/Carla/blob/master/source/backend/CarlaUtils.h

Para plugins LADSPA, DSSI e VST so mesmo chamando carla-discovery manualmete. É o que o carla faz, por enquanto essa parte é toda manual.

PS: é mais rapido falar por IRC ;)

Está bem! Farei um próximo contato com IRC

Alright! Tenho user sempre online, mas posso tar ocupado. Falar por ingles pela internet sff ;)

Uma boa semana

Igualmente!

Code

./carla-discovery-native LV2 /usr/lib/lv2/gx_hornet.lv2/
SrMouraSilva commented 5 years ago

Docker (doesn't work)

sudo docker run --rm -it -v /dev/snd:/dev/snd:rw -v /dev/shm:/dev/shm:rw --privileged debian:9-slim bash

Maybe in PC

apt-get update && apt-get install -y --no-install-recommends \
# https
    ca-certificates \
# clone
    git \
# build
    make g++ pkg-config \
# Execute python scripts
    python3 \
# Audio dependencies
    jackd2 libjack-jackd2-dev lv2-dev lilv-utils

cd /tmp
git clone https://github.com/falkTX/Carla.git --depth 1
cd Carla
make features
HAVE_HYLIA=false make
#make install
#./source/frontend/carla
cd source/frontend/
python3
from carla_backend import *
from sys import exit

host = CarlaHostDLL("/tmp/Carla/bin/libcarla_standalone2.so", False)
host.set_engine_option(ENGINE_OPTION_PATH_BINARIES, 0, '/tmp/Carla/bin')

if not host.engine_init("JACK", "Carla-uhe-test"):
    print("Engine failed to initialize, possible reasons:\n%s" % host.get_last_error())
    exit(1)

host.add_plugin(BINARY_NATIVE, PLUGIN_LV2, "/usr/lib/lv2/gx_echo.lv2/gx_echo.so", "effect_1", "http://guitarix.sourceforge.net/plugins/gx_echo_stereo#_echo_stereo", 7, None, 0)
SrMouraSilva commented 5 years ago

All the data is based in the callback.

from carla_backend import *
from sys import exit

class CarlaCallbackResponseBase:
    def __init__(self, identifier, name):
        self.identifier = identifier
        self.name = name

    def __repr__(self):
        return {
            'identifier': self.identifier,
            'name': self.name
        }.__repr__()

class CarlaClient(CarlaCallbackResponseBase):
    def __init__(self, client_id, port_id, port_hints, port_name):
        super(CarlaClient, self).__init__(client_id, port_name)
        self.port_id = port_id
        self.port_hints = port_hints

    def __repr__(self):
        return {
            'identifier': self.identifier,
            'port_id': self.port_id,
            'port_hints': self.port_hints,
            'name': self.name,
        }.__repr__()

class CarlaPort(CarlaCallbackResponseBase):
    def __init__(self, client_id, port_id, port_hints, port_name):
        super(CarlaClient, self).__init__(client_id, port_name)
        self.port_id = port_id
        self.port_hints = port_hints

    def __repr__(self):
        return {
            'identifier': self.identifier,
            'port_id': self.port_id,
            'port_hints': self.port_hints,
            'name': self.name,
        }.__repr__()

def callback(*args):
    #https://github.com/falkTX/Carla/blob/d15e3396457cc3e47511091110a7f9be34a7044a/source/frontend/carla_backend.py#L500-L707
    print('Args:', args)
    none, callback_opcode, plugin_id, value1, value2, value3, value_str = args

    if callback_opcode == ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED:
        element = CarlaClient(plugin_id, value1, value2, value_str)
    elif callback_opcode == ENGINE_CALLBACK_PATCHBAY_PORT_ADDED:
        element = CarlaClient(plugin_id, value1, value2, value_str)
    else:
        return
    print(element)
    #elements[element.identifier] = element

host = CarlaHostDLL("/tmp/Carla/bin/libcarla_standalone2.so", False)
host.set_engine_callback(callback)

host.set_engine_option(ENGINE_OPTION_PATH_BINARIES, 0, '/tmp/Carla/bin')

if not host.engine_init("JACK", "Pedal Pi"):
    print("Engine failed to initialize, possible reasons:\n%s" % host.get_last_error())
    exit(1)

import time
time.sleep(1)

host.add_plugin(BINARY_NATIVE, PLUGIN_LV2, "/usr/lib/lv2/gx_echo.lv2/gx_echo.so", "effect_1", "http://guitarix.sourceforge.net/plugins/gx_echo_stereo#_echo_stereo", 7, None, 
0)

time.sleep(1)

host.engine_close()
exit(0)

host.add_plugin(BINARY_NATIVE, PLUGIN_LV2, "/usr/lib/lv2/gx_echo.lv2/gx_echo.so", "effect_2", "http://guitarix.sourceforge.net/plugins/gx_echo_stereo#_echo_stereo", 8, None, 0)

host.add_plugin(BINARY_NATIVE, PLUGIN_LV2, "/usr/lib/lv2/gx_echo.lv2/gx_echo.so", "effect_10", "http://guitarix.sourceforge.net/plugins/gx_fuzzface_#_fuzzface_", 10, None, 0)
SrMouraSilva commented 5 years ago
import time
from pathlib import Path
from pluginsmanager.banks_manager import BanksManager
from pluginsmanager.observer.carla.carla import Carla
from pluginsmanager.observer.mod_host.mod_host import ModHost

from pluginsmanager.model.bank import Bank
from pluginsmanager.model.pedalboard import Pedalboard
from pluginsmanager.model.connection import Connection

from pluginsmanager.model.lv2.lv2_effect_builder import Lv2EffectBuilder

from pluginsmanager.model.system.system_effect import SystemEffect

sys_effect = SystemEffect('system', ['capture_1', 'capture_2'], ['playback_1', 'playback_2'])

manager = BanksManager()

bank = Bank('Bank 1')
manager.append(bank)

path = Path('/home/paulo/git/pedalpi/Carla')
carla = Carla(path)
#carla.connect()
carla.start()

manager.register(carla)

pedalboard = Pedalboard('Rocksmith')
bank.append(pedalboard)

carla.pedalboard = pedalboard

builder = Lv2EffectBuilder()

delay = builder.build('http://guitarix.sourceforge.net/plugins/gx_echo_stereo#_echo_stereo')
fuzz = builder.build('http://guitarix.sourceforge.net/plugins/gx_fuzz_#fuzz_')

pedalboard.append(delay)
pedalboard.append(fuzz)

time.sleep(.25)

pedalboard.connect(delay.outputs[0], fuzz.inputs[0])
pedalboard.connect(sys_effect.outputs[0], delay.inputs[0])

time.sleep(.25)

fuzz.toggle()
fuzz.params[0].value = fuzz.params[0].maximum

# Removing
pedalboard.disconnect(delay.outputs[0], fuzz.inputs[0])
del pedalboard.effects[1]
del pedalboard.effects[0]

time.sleep(3)
del carla