diff --git a/.build.yml b/.build.yml index 903c7c3..4ff9083 100644 --- a/.build.yml +++ b/.build.yml @@ -5,6 +5,7 @@ packages: - libsndfile1-dev - libfftw3-dev - ladspa-sdk + - lv2 - vamp-plugin-sdk - meson - ninja-build diff --git a/ladspa/RubberBandPitchShifter.cpp b/ladspa-lv2/RubberBandPitchShifter.cpp similarity index 80% rename from ladspa/RubberBandPitchShifter.cpp rename to ladspa-lv2/RubberBandPitchShifter.cpp index 8ea24e1..f9c5fd5 100644 --- a/ladspa/RubberBandPitchShifter.cpp +++ b/ladspa-lv2/RubberBandPitchShifter.cpp @@ -35,6 +35,8 @@ using std::cerr; using std::endl; using std::min; +#ifdef RB_PLUGIN_LADSPA + const char *const RubberBandPitchShifter::portNamesMono[PortCountMono] = { @@ -185,13 +187,13 @@ RubberBandPitchShifter::ladspaDescriptorMono = portsMono, portNamesMono, hintsMono, - 0, // Implementation data + nullptr, // Implementation data instantiate, connectPort, activate, run, - 0, // Run adding - 0, // Set run adding gain + nullptr, // Run adding + nullptr, // Set run adding gain deactivate, cleanup }; @@ -209,13 +211,13 @@ RubberBandPitchShifter::ladspaDescriptorStereo = portsStereo, portNamesStereo, hintsStereo, - 0, // Implementation data + nullptr, // Implementation data instantiate, connectPort, activate, run, - 0, // Run adding - 0, // Set run adding gain + nullptr, // Run adding + nullptr, // Set run adding gain deactivate, cleanup }; @@ -228,14 +230,52 @@ RubberBandPitchShifter::getDescriptor(unsigned long index) else return 0; } +#else + +const LV2_Descriptor +RubberBandPitchShifter::lv2DescriptorMono = +{ + "http://breakfastquay.com/rdf/lv2-rubberband#mono", + instantiate, + connectPort, + activate, + run, + deactivate, + cleanup, + nullptr +}; + +const LV2_Descriptor +RubberBandPitchShifter::lv2DescriptorStereo = +{ + "http://breakfastquay.com/rdf/lv2-rubberband#stereo", + instantiate, + connectPort, + activate, + run, + deactivate, + cleanup, + nullptr +}; + +const LV2_Descriptor * +RubberBandPitchShifter::getDescriptor(uint32_t index) +{ + if (index == 0) return &lv2DescriptorMono; + if (index == 1) return &lv2DescriptorStereo; + else return 0; +} + +#endif + RubberBandPitchShifter::RubberBandPitchShifter(int sampleRate, size_t channels) : - m_latency(0), - m_cents(0), - m_semitones(0), - m_octaves(0), - m_crispness(0), - m_formant(0), - m_wetDry(0), + m_latency(nullptr), + m_cents(nullptr), + m_semitones(nullptr), + m_octaves(nullptr), + m_crispness(nullptr), + m_formant(nullptr), + m_wetDry(nullptr), m_ratio(1.0), m_prevRatio(1.0), m_currentCrispness(-1), @@ -257,6 +297,7 @@ RubberBandPitchShifter::RubberBandPitchShifter(int sampleRate, size_t channels) m_outputBuffer = new RingBuffer *[m_channels]; m_delayMixBuffer = new RingBuffer *[m_channels]; m_scratch = new float *[m_channels]; + m_inptrs = new float *[m_channels]; m_bufsize = m_blockSize + m_reserve + 8192; @@ -272,6 +313,8 @@ RubberBandPitchShifter::RubberBandPitchShifter(int sampleRate, size_t channels) for (size_t i = 0; i < m_bufsize; ++i) { m_scratch[c][i] = 0.f; } + + m_inptrs[c] = 0; } activateImpl(); @@ -287,11 +330,14 @@ RubberBandPitchShifter::~RubberBandPitchShifter() } delete[] m_outputBuffer; delete[] m_delayMixBuffer; + delete[] m_inptrs; delete[] m_scratch; delete[] m_output; delete[] m_input; } - + +#ifdef RB_PLUGIN_LADSPA + LADSPA_Handle RubberBandPitchShifter::instantiate(const LADSPA_Descriptor *desc, unsigned long rate) { @@ -300,12 +346,43 @@ RubberBandPitchShifter::instantiate(const LADSPA_Descriptor *desc, unsigned long } else if (desc->PortCount == ladspaDescriptorStereo.PortCount) { return new RubberBandPitchShifter(rate, 2); } - return 0; + return nullptr; } +#else + +LV2_Handle +RubberBandPitchShifter::instantiate(const LV2_Descriptor *desc, double rate, + const char *, const LV2_Feature *const *) +{ + if (rate < 1.0) { + std::cerr << "RubberBandPitchShifter::instantiate: invalid sample rate " + << rate << " provided" << std::endl; + return nullptr; + } + size_t srate = size_t(round(rate)); + if (std::string(desc->URI) == lv2DescriptorMono.URI) { + return new RubberBandPitchShifter(srate, 1); + } else if (std::string(desc->URI) == lv2DescriptorStereo.URI) { + return new RubberBandPitchShifter(srate, 2); + } else { + std::cerr << "RubberBandPitchShifter::instantiate: unrecognised URI " + << desc->URI << " requested" << std::endl; + return nullptr; + } +} + +#endif + +#ifdef RB_PLUGIN_LADSPA void RubberBandPitchShifter::connectPort(LADSPA_Handle handle, unsigned long port, LADSPA_Data *location) +#else +void +RubberBandPitchShifter::connectPort(LV2_Handle handle, + uint32_t port, void *location) +#endif { RubberBandPitchShifter *shifter = (RubberBandPitchShifter *)handle; @@ -336,19 +413,58 @@ RubberBandPitchShifter::connectPort(LADSPA_Handle handle, } } +#ifdef RB_PLUGIN_LADSPA +void +RubberBandPitchShifter::activate(LADSPA_Handle handle) +#else +void +RubberBandPitchShifter::activate(LV2_Handle handle) +#endif +{ + RubberBandPitchShifter *shifter = (RubberBandPitchShifter *)handle; + shifter->activateImpl(); +} + +#ifdef RB_PLUGIN_LADSPA +void +RubberBandPitchShifter::run(LADSPA_Handle handle, unsigned long samples) +#else +void +RubberBandPitchShifter::run(LV2_Handle handle, uint32_t samples) +#endif +{ + RubberBandPitchShifter *shifter = (RubberBandPitchShifter *)handle; + shifter->runImpl(samples); +} + +#ifdef RB_PLUGIN_LADSPA +void +RubberBandPitchShifter::deactivate(LADSPA_Handle handle) +#else +void +RubberBandPitchShifter::deactivate(LV2_Handle handle) +#endif +{ + activate(handle); // both functions just reset the plugin +} + +#ifdef RB_PLUGIN_LADSPA +void +RubberBandPitchShifter::cleanup(LADSPA_Handle handle) +#else +void +RubberBandPitchShifter::cleanup(LV2_Handle handle) +#endif +{ + delete (RubberBandPitchShifter *)handle; +} + int RubberBandPitchShifter::getLatency() const { return m_reserve; } -void -RubberBandPitchShifter::activate(LADSPA_Handle handle) -{ - RubberBandPitchShifter *shifter = (RubberBandPitchShifter *)handle; - shifter->activateImpl(); -} - void RubberBandPitchShifter::activateImpl() { @@ -377,13 +493,6 @@ RubberBandPitchShifter::activateImpl() m_stretcher->process(m_scratch, m_reserve, false); } -void -RubberBandPitchShifter::run(LADSPA_Handle handle, unsigned long samples) -{ - RubberBandPitchShifter *shifter = (RubberBandPitchShifter *)handle; - shifter->runImpl(samples); -} - void RubberBandPitchShifter::updateRatio() { @@ -443,9 +552,9 @@ RubberBandPitchShifter::updateFormant() } void -RubberBandPitchShifter::runImpl(unsigned long insamples) +RubberBandPitchShifter::runImpl(uint32_t insamples) { - unsigned long offset = 0; + size_t offset = 0; // We have to break up the input into chunks like this because // insamples could be arbitrarily large and our output buffer is @@ -453,35 +562,36 @@ RubberBandPitchShifter::runImpl(unsigned long insamples) while (offset < insamples) { - unsigned long block = (unsigned long)m_blockSize; - if (block + offset > insamples) block = insamples - offset; + size_t block = m_blockSize; + if (offset + block > insamples) { + block = insamples - offset; + } runImpl(block, offset); offset += block; } - if (m_wetDry) { - for (size_t c = 0; c < m_channels; ++c) { - m_delayMixBuffer[c]->write(m_input[c], insamples); - } - float mix = *m_wetDry; - for (size_t c = 0; c < m_channels; ++c) { - if (mix > 0.0) { - for (unsigned long i = 0; i < insamples; ++i) { - float dry = m_delayMixBuffer[c]->readOne(); - m_output[c][i] *= (1.0 - mix); - m_output[c][i] += dry * mix; - } - } else { - m_delayMixBuffer[c]->skip(insamples); + for (size_t c = 0; c < m_channels; ++c) { + m_delayMixBuffer[c]->write(m_input[c], insamples); + } + float mix = 0.0; + if (m_wetDry) mix = *m_wetDry; + for (size_t c = 0; c < m_channels; ++c) { + if (mix > 0.0) { + for (size_t i = 0; i < insamples; ++i) { + float dry = m_delayMixBuffer[c]->readOne(); + m_output[c][i] *= (1.0 - mix); + m_output[c][i] += dry * mix; } + } else { + m_delayMixBuffer[c]->skip(insamples); } } } void -RubberBandPitchShifter::runImpl(unsigned long insamples, unsigned long offset) +RubberBandPitchShifter::runImpl(uint32_t insamples, uint32_t offset) { updateRatio(); if (m_ratio != m_prevRatio) { @@ -500,8 +610,6 @@ RubberBandPitchShifter::runImpl(unsigned long insamples, unsigned long offset) int processed = 0; size_t outTotal = 0; - float *ptrs[2]; - while (processed < samples) { // never feed more than the minimum necessary number of @@ -510,10 +618,13 @@ RubberBandPitchShifter::runImpl(unsigned long insamples, unsigned long offset) int toCauseProcessing = m_stretcher->getSamplesRequired(); int inchunk = min(samples - processed, toCauseProcessing); + for (size_t c = 0; c < m_channels; ++c) { - ptrs[c] = &(m_input[c][offset + processed]); + m_inptrs[c] = &(m_input[c][offset + processed]); } - m_stretcher->process(ptrs, inchunk, false); + + m_stretcher->process(m_inptrs, inchunk, false); + processed += inchunk; int avail = m_stretcher->available(); @@ -549,15 +660,3 @@ RubberBandPitchShifter::runImpl(unsigned long insamples, unsigned long offset) } } -void -RubberBandPitchShifter::deactivate(LADSPA_Handle handle) -{ - activate(handle); // both functions just reset the plugin -} - -void -RubberBandPitchShifter::cleanup(LADSPA_Handle handle) -{ - delete (RubberBandPitchShifter *)handle; -} - diff --git a/ladspa/RubberBandPitchShifter.h b/ladspa-lv2/RubberBandPitchShifter.h similarity index 75% rename from ladspa/RubberBandPitchShifter.h rename to ladspa-lv2/RubberBandPitchShifter.h index f6a8702..15678e1 100644 --- a/ladspa/RubberBandPitchShifter.h +++ b/ladspa-lv2/RubberBandPitchShifter.h @@ -24,7 +24,21 @@ #ifndef RUBBERBAND_PITCH_SHIFTER_H #define RUBBERBAND_PITCH_SHIFTER_H +#ifdef RB_PLUGIN_LADSPA +#ifdef RB_PLUGIN_LV2 +#error "Only one of RB_PLUGIN_LADSPA and RB_PLUGIN_LV2 may be defined at once" +#endif +#else +#ifndef RB_PLUGIN_LV2 +#error "Including code must define either RB_PLUGIN_LADSPA or RB_PLUGIN_LV2" +#endif +#endif + +#ifdef RB_PLUGIN_LADSPA #include +#else +#include +#endif #include "base/RingBuffer.h" @@ -35,7 +49,11 @@ class RubberBandStretcher; class RubberBandPitchShifter { public: +#ifdef RB_PLUGIN_LADSPA static const LADSPA_Descriptor *getDescriptor(unsigned long index); +#else + static const LV2_Descriptor *getDescriptor(uint32_t index); +#endif protected: RubberBandPitchShifter(int sampleRate, size_t channels); @@ -43,9 +61,9 @@ protected: enum { LatencyPort = 0, - OctavesPort = 1, + CentsPort = 1, SemitonesPort = 2, - CentsPort = 3, + OctavesPort = 3, CrispnessPort = 4, FormantPort = 5, WetDryPort = 6, @@ -57,6 +75,7 @@ protected: PortCountStereo = OutputPort2 + 1 }; +#ifdef RB_PLUGIN_LADSPA static const char *const portNamesMono[PortCountMono]; static const LADSPA_PortDescriptor portsMono[PortCountMono]; static const LADSPA_PortRangeHint hintsMono[PortCountMono]; @@ -77,9 +96,24 @@ protected: static void deactivate(LADSPA_Handle); static void cleanup(LADSPA_Handle); +#else + + static const LV2_Descriptor lv2DescriptorMono; + static const LV2_Descriptor lv2DescriptorStereo; + + static LV2_Handle instantiate(const LV2_Descriptor *, double, + const char *, const LV2_Feature *const *); + static void connectPort(LV2_Handle, uint32_t, void *); + static void activate(LV2_Handle); + static void run(LV2_Handle, uint32_t); + static void deactivate(LV2_Handle); + static void cleanup(LV2_Handle); + +#endif + void activateImpl(); - void runImpl(unsigned long); - void runImpl(unsigned long, unsigned long offset); + void runImpl(uint32_t count); + void runImpl(uint32_t count, uint32_t offset); void updateRatio(); void updateCrispness(); void updateFormant(); @@ -109,6 +143,7 @@ protected: RubberBand::RingBuffer **m_outputBuffer; RubberBand::RingBuffer **m_delayMixBuffer; float **m_scratch; + float **m_inptrs; int m_sampleRate; size_t m_channels; diff --git a/ladspa/ladspa-plugin.list b/ladspa-lv2/ladspa-plugin.list similarity index 100% rename from ladspa/ladspa-plugin.list rename to ladspa-lv2/ladspa-plugin.list diff --git a/ladspa/ladspa-plugin.map b/ladspa-lv2/ladspa-plugin.map similarity index 100% rename from ladspa/ladspa-plugin.map rename to ladspa-lv2/ladspa-plugin.map diff --git a/ladspa/ladspa-rubberband.cat b/ladspa-lv2/ladspa-rubberband.cat similarity index 100% rename from ladspa/ladspa-rubberband.cat rename to ladspa-lv2/ladspa-rubberband.cat diff --git a/ladspa/ladspa-rubberband.rdf b/ladspa-lv2/ladspa-rubberband.rdf similarity index 100% rename from ladspa/ladspa-rubberband.rdf rename to ladspa-lv2/ladspa-rubberband.rdf diff --git a/ladspa/libmain.cpp b/ladspa-lv2/libmain-ladspa.cpp similarity index 93% rename from ladspa/libmain.cpp rename to ladspa-lv2/libmain-ladspa.cpp index dcdee1b..3d22289 100644 --- a/ladspa/libmain.cpp +++ b/ladspa-lv2/libmain-ladspa.cpp @@ -21,7 +21,9 @@ you must obtain a valid commercial licence before doing so. */ -#include "RubberBandPitchShifter.h" +#define RB_PLUGIN_LADSPA 1 +#undef RB_PLUGIN_LV2 +#include "RubberBandPitchShifter.cpp" #include diff --git a/ladspa-lv2/libmain-lv2.cpp b/ladspa-lv2/libmain-lv2.cpp new file mode 100644 index 0000000..f4a948e --- /dev/null +++ b/ladspa-lv2/libmain-lv2.cpp @@ -0,0 +1,37 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rubber Band Library + An audio time-stretching and pitch-shifting library. + Copyright 2007-2022 Particular Programs Ltd. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. + + Alternatively, if you have a valid commercial licence for the + Rubber Band Library obtained by agreement with the copyright + holders, you may redistribute and/or modify it under the terms + described in that licence. + + If you wish to distribute code using the Rubber Band Library + under terms other than those of the GNU General Public License, + you must obtain a valid commercial licence before doing so. +*/ + +#define RB_PLUGIN_LV2 1 +#undef RB_PLUGIN_LADSPA +#include "RubberBandPitchShifter.cpp" + +#include + +extern "C" { + +const LV2_Descriptor *lv2_descriptor(uint32_t index) +{ + return RubberBandPitchShifter::getDescriptor(index); +} + +} diff --git a/ladspa-lv2/lv2-plugin.list b/ladspa-lv2/lv2-plugin.list new file mode 100644 index 0000000..0071ce3 --- /dev/null +++ b/ladspa-lv2/lv2-plugin.list @@ -0,0 +1 @@ +_lv2_descriptor diff --git a/ladspa-lv2/lv2-plugin.map b/ladspa-lv2/lv2-plugin.map new file mode 100644 index 0000000..fe1dc96 --- /dev/null +++ b/ladspa-lv2/lv2-plugin.map @@ -0,0 +1,4 @@ +{ + global: lv2_descriptor; + local: *; +}; diff --git a/ladspa-lv2/rubberband.lv2/lv2-rubberband.ttl b/ladspa-lv2/rubberband.lv2/lv2-rubberband.ttl new file mode 100644 index 0000000..e450698 --- /dev/null +++ b/ladspa-lv2/rubberband.lv2/lv2-rubberband.ttl @@ -0,0 +1,200 @@ +@prefix rdf: . +@prefix rdfs: . +@prefix dc: . +@prefix doap: . +@prefix foaf: . +@prefix lv2: . +@prefix pg: . +@prefix rubberband: . +@prefix : <#> . + +:maker + a foaf:Agent, foaf:Person ; + foaf:name "Breakfast Quay" ; + foaf:homepage ; + foaf:mbox . + +:latencyPort + a lv2:ControlPort, lv2:OutputPort ; + lv2:index 0 ; + lv2:symbol "latency" ; + lv2:name "Latency" ; + lv2:designation lv2:latency ; + lv2:portProperty lv2:integer, lv2:reportsLatency . + +:centsPort + a lv2:ControlPort, lv2:InputPort ; + lv2:index 1 ; + lv2:symbol "cents" ; + lv2:name "Cents" ; + lv2:default 0 ; + lv2:minimum -100 ; + lv2:maximum 100 ; + lv2:portProperty lv2:integer . + +:semitonesPort + a lv2:ControlPort, lv2:InputPort ; + lv2:index 2 ; + lv2:symbol "semitones" ; + lv2:name "Semitones" ; + lv2:default 0 ; + lv2:minimum -12 ; + lv2:maximum 12 ; + lv2:portProperty lv2:integer . + +:octavesPort + a lv2:ControlPort, lv2:InputPort ; + lv2:index 3 ; + lv2:symbol "octaves" ; + lv2:name "Octaves" ; + lv2:default 0 ; + lv2:minimum -2 ; + lv2:maximum 2 ; + lv2:portProperty lv2:integer . + +:crispnessPort + a lv2:ControlPort, lv2:InputPort ; + lv2:index 4 ; + lv2:symbol "crispness" ; + lv2:name "Crispness" ; + lv2:default 3 ; + lv2:minimum 0 ; + lv2:maximum 3 ; + lv2:portProperty lv2:integer, lv2:enumeration ; + lv2:scalePoint [ rdfs:label "Smooth"; rdf:value 0 ] ; + lv2:scalePoint [ rdfs:label "Multitimbral"; rdf:value 1 ] ; + lv2:scalePoint [ rdfs:label "Two sources"; rdf:value 2 ] ; + lv2:scalePoint [ rdfs:label "Standard"; rdf:value 3 ] . + +:formantPort + a lv2:ControlPort, lv2:InputPort ; + lv2:index 5 ; + lv2:symbol "formant" ; + lv2:name "Formant Preserving" ; + lv2:default 0 ; + lv2:minimum 0 ; + lv2:maximum 1 ; + lv2:portProperty lv2:integer, lv2:toggled . + +:wetDryPort + a lv2:ControlPort, lv2:InputPort ; + lv2:index 6 ; + lv2:symbol "wetdry" ; + lv2:name "Wet-Dry Mix" ; + lv2:default 0 ; + lv2:minimum 0 ; + lv2:maximum 1 . + +rubberband:mono_in_group + a pg:MonoGroup, pg:InputGroup ; + lv2:symbol "mono_in" ; + rdfs:label "Mono Input" . + +rubberband:mono_out_group + a pg:MonoGroup, pg:OutputGroup ; + lv2:symbol "mono_out" ; + rdfs:label "Mono Output" . + +rubberband:stereo_in_group + a pg:StereoGroup, pg:InputGroup ; + lv2:symbol "stereo_in" ; + rdfs:label "Stereo Input" . + +rubberband:stereo_out_group + a pg:StereoGroup, pg:OutputGroup ; + lv2:symbol "stereo_out" ; + rdfs:label "Stereo Output" . + +rubberband:mono + a doap:Project, lv2:Plugin, lv2:PitchPlugin ; + doap:name "Rubber Band Mono Pitch Shifter" ; + doap:license ; + foaf:maker :maker ; + doap:developer :maker ; + doap:maintainer :maker ; + # Minor version will be 2x the Rubber Band API minor version, + # but this is an initial test release, so 0 + lv2:minorVersion 0 ; + lv2:microVersion 0 ; + lv2:optionalFeature lv2:hardRTCapable ; + pg:mainInput rubberband:mono_in_group ; + pg:mainOutput rubberband:mono_out_group ; + dc:replaces ; + lv2:port :latencyPort , + :centsPort , + :semitonesPort , + :octavesPort , + :crispnessPort , + :formantPort , + :wetDryPort , + [ a lv2:AudioPort, lv2:InputPort ; + lv2:index 7 ; + lv2:symbol "input" ; + lv2:name "Input" ; + lv2:shortName "Input" ; + pg:group rubberband:mono_in_group ; + lv2:designation pg:center ; + ], [ + a lv2:AudioPort, lv2:OutputPort ; + lv2:index 8 ; + lv2:symbol "output" ; + lv2:name "Output" ; + lv2:shortName "Output" ; + pg:group rubberband:mono_out_group ; + lv2:designation pg:center ; + ] . + +rubberband:stereo + a doap:Project, lv2:Plugin, lv2:PitchPlugin ; + doap:name "Rubber Band Stereo Pitch Shifter" ; + doap:license ; + foaf:maker :maker ; + doap:developer :maker ; + doap:maintainer :maker ; + # Minor version will be 2x the Rubber Band API minor version, + # but this is an initial test release, so 0 + lv2:minorVersion 0 ; + lv2:microVersion 0 ; + lv2:optionalFeature lv2:hardRTCapable ; + pg:mainInput rubberband:stereo_in_group ; + pg:mainOutput rubberband:stereo_out_group ; + dc:replaces ; + lv2:port :latencyPort , + :centsPort , + :semitonesPort , + :octavesPort , + :crispnessPort , + :formantPort , + :wetDryPort , + [ a lv2:AudioPort, lv2:InputPort ; + lv2:index 7 ; + lv2:symbol "input_l" ; + lv2:name "Input L" ; + lv2:shortName "Input L" ; + pg:group rubberband:stereo_in_group ; + lv2:designation pg:left ; + ], [ + a lv2:AudioPort, lv2:OutputPort ; + lv2:index 8 ; + lv2:symbol "output_l" ; + lv2:name "Output L" ; + lv2:shortName "Output L" ; + pg:group rubberband:stereo_out_group ; + lv2:designation pg:left ; + ], [ a lv2:AudioPort, lv2:InputPort ; + lv2:index 9 ; + lv2:symbol "input_r" ; + lv2:name "Input R" ; + lv2:shortName "Input R" ; + pg:group rubberband:stereo_in_group ; + lv2:designation pg:right ; + ], [ + a lv2:AudioPort, lv2:OutputPort ; + lv2:index 10 ; + lv2:symbol "output_r" ; + lv2:name "Output R" ; + lv2:shortName "Output R" ; + pg:group rubberband:stereo_out_group ; + lv2:designation pg:right ; + ] . + diff --git a/ladspa-lv2/rubberband.lv2/manifest.ttl b/ladspa-lv2/rubberband.lv2/manifest.ttl new file mode 100644 index 0000000..5931138 --- /dev/null +++ b/ladspa-lv2/rubberband.lv2/manifest.ttl @@ -0,0 +1,14 @@ +@prefix lv2: . +@prefix rdfs: . +@prefix rubberband: . + +rubberband:mono + a lv2:Plugin ; + lv2:binary ; + rdfs:seeAlso . + +rubberband:stereo + a lv2:Plugin ; + lv2:binary ; + rdfs:seeAlso . + diff --git a/meson.build b/meson.build index f7611eb..d05ba5d 100644 --- a/meson.build +++ b/meson.build @@ -77,8 +77,11 @@ vamp_sources = [ ] ladspa_sources = [ - 'ladspa/RubberBandPitchShifter.cpp', - 'ladspa/libmain.cpp', + 'ladspa-lv2/libmain-ladspa.cpp', +] + +lv2_sources = [ + 'ladspa-lv2/libmain-lv2.cpp', ] general_include_dirs = [ @@ -100,6 +103,7 @@ sndfile_dep = dependency('sndfile', version: '>= 1.0.16', required: false) vamp_dep = dependency('vamp-sdk', version: '>= 2.9', required: false) thread_dep = dependency('threads') have_ladspa = cpp.has_header('ladspa.h', args: extra_include_args) +have_lv2 = cpp.has_header('lv2.h', args: extra_include_args) have_sincos = cpp.has_function('sincos', prefix: '#define _GNU_SOURCE\n#include ', args: '-lm') @@ -314,6 +318,7 @@ have_sndfile = sndfile_dep.found() # General platform and compiler expectations ladspa_symbol_args = [] +lv2_symbol_args = [] vamp_symbol_args = [] if get_option('buildtype').startswith('release') @@ -326,7 +331,10 @@ endif if system == 'darwin' feature_defines += ['-DUSE_PTHREADS', '-DMALLOC_IS_ALIGNED'] ladspa_symbol_args += [ - '-exported_symbols_list', meson.current_source_dir() / 'ladspa/ladspa-plugin.list' + '-exported_symbols_list', meson.current_source_dir() / 'ladspa-lv2/ladspa-plugin.list' + ] + lv2_symbol_args += [ + '-exported_symbols_list', meson.current_source_dir() / 'ladspa-lv2/lv2-plugin.list' ] vamp_symbol_args += [ '-exported_symbols_list', meson.current_source_dir() / 'vamp/vamp-plugin.list' @@ -373,13 +381,17 @@ elif system == 'windows' feature_defines += ['-D_WIN32', '-DNOMINMAX', '-D_USE_MATH_DEFINES', '-DGETOPT_API='] if cpp.get_id() == 'msvc' ladspa_symbol_args += ['-EXPORT:ladspa_descriptor'] + lv2_symbol_args += ['-EXPORT:lv2_descriptor'] vamp_symbol_args += ['-EXPORT:vampGetPluginDescriptor'] endif else # system not darwin or windows feature_defines += ['-DUSE_PTHREADS', '-DHAVE_POSIX_MEMALIGN'] ladspa_symbol_args += [ - '-Wl,--version-script=' + meson.current_source_dir() / 'ladspa/ladspa-plugin.map' + '-Wl,--version-script=' + meson.current_source_dir() / 'ladspa-lv2/ladspa-plugin.map' + ] + lv2_symbol_args += [ + '-Wl,--version-script=' + meson.current_source_dir() / 'ladspa-lv2/lv2-plugin.map' ] vamp_symbol_args += [ '-Wl,--version-script=' + meson.current_source_dir() / 'vamp/vamp-plugin.map' @@ -417,6 +429,7 @@ if cpp.get_id() == 'msvc' rubberband_library_name = 'rubberband' rubberband_program_name = 'rubberband-program' rubberband_ladspa_name = 'ladspa-rubberband' + rubberband_lv2_name = 'lv2-rubberband' rubberband_vamp_name = 'vamp-rubberband' rubberband_jni_name = 'rubberband-jni' else @@ -424,6 +437,7 @@ else rubberband_dynamic_name = 'rubberband' rubberband_program_name = 'rubberband' rubberband_ladspa_name = 'ladspa-rubberband' + rubberband_lv2_name = 'lv2-rubberband' rubberband_vamp_name = 'vamp-rubberband' rubberband_jni_name = 'rubberband-jni' endif @@ -446,7 +460,7 @@ rubberband_objlib_dep = declare_dependency( # And the build targets: Static and dynamic libraries, command-line -# utility, LADSPA plugin, Vamp plugin, JNI library +# utility, LADSPA and LV2 plugins, Vamp plugin, JNI library if get_option('default_library') == 'shared' message('Not building Rubber Band Library static library: default_library option is set to shared') @@ -573,11 +587,11 @@ if have_ladspa install_dir: get_option('libdir') / 'ladspa', ) install_data( - 'ladspa/ladspa-rubberband.cat', + 'ladspa-lv2/ladspa-rubberband.cat', install_dir: get_option('libdir') / 'ladspa', ) install_data( - 'ladspa/ladspa-rubberband.rdf', + 'ladspa-lv2/ladspa-rubberband.rdf', install_dir: get_option('datadir') / 'ladspa/rdf', ) else @@ -585,6 +599,33 @@ else message('Not building LADSPA plugin: ladspa.h header not found') endif +if have_lv2 + target_summary += { 'LV2 plugin': [ true, 'Name: ' + rubberband_lv2_name ] } + message('Will build LV2 plugin') + rubberband_lv2 = shared_library( + rubberband_lv2_name, + lv2_sources, + include_directories: general_include_dirs, + cpp_args: general_compile_args, + c_args: general_compile_args, + link_args: [ + arch_flags, + feature_libraries, + lv2_symbol_args, + ], + dependencies: [ + rubberband_objlib_dep, + general_dependencies, + ], + name_prefix: '', + install: true, + install_dir: get_option('libdir') / 'lv2', + ) +else + target_summary += { 'LV2 plugin': false } + message('Not building LV2 plugin: lv2.h header not found') +endif + if have_vamp target_summary += { 'Vamp plugin': [ true, 'Name: ' + rubberband_vamp_name ] } message('Will build Vamp plugin') diff --git a/otherbuilds/deploy/source.sh b/otherbuilds/deploy/source.sh index 0278fed..bb3b18d 100755 --- a/otherbuilds/deploy/source.sh +++ b/otherbuilds/deploy/source.sh @@ -32,6 +32,12 @@ echo grep 'RUBBERBAND.*VERSION' rubberband/rubberband-c.h check "Are the above version and API versions (from the C header) correct?" echo +echo "The LV2 plugin RDF should contain 2x the API minor version for minorVersion" +echo "and an LV2-specific microVersion field, for the mono and stereo plugins." +echo +grep 'Version' ladspa-lv2/rubberband.lv2/rubberband.ttl +check "Are the above minor and micro versions (from the LV2 plugin RDF) correct?" +echo grep '^PROJECT_NUMBER' Doxyfile check "Is the above version (from Doxyfile) correct?"