From: IOhannes m zmölnig (Debian/GNU) Date: Thu, 16 May 2024 22:16:58 +0000 (+0200) Subject: New upstream version 2.3.0+ds X-Git-Tag: archive/raspbian/2.5.1+ds-1+rpi1~1^2~9^2 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=b434ea8c28387804c0e7f32f9bec9cc2bb390ffc;p=jacktrip.git New upstream version 2.3.0+ds --- diff --git a/Dockerfile b/Dockerfile index 9acd0ef..2fa1bc0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,20 +17,28 @@ ARG JACK_VERSION=latest FROM registry.fedoraproject.org/fedora:${FEDORA_VERSION} AS builder # install tools require to build jacktrip -RUN dnf install -y --nodocs gcc gcc-c++ meson python3-pyyaml python3-jinja2 qt5-qtbase-devel jack-audio-connection-kit-devel +RUN dnf install -y --nodocs gcc gcc-c++ meson git python3-pyyaml python3-jinja2 glib2-devel jack-audio-connection-kit-devel + +ENV QT_VERSION=6.5.3 +RUN if [ "$(uname -m)" = "x86_64" ]; then export ARCH=amd64; else export ARCH=arm64; fi \ + && curl -L -s -o /root/qt.tar.gz "https://files.jacktrip.org/contrib/qt/qt-${QT_VERSION}-static-linux-${ARCH}.tar.gz" \ + && tar -C /opt -xzf /root/qt.tar.gz \ + && rm -f /root/qt.tar.gz # copy files from repository to build container COPY . /root # configure and run the build RUN cd /root \ - && PKG_CONFIG_PATH=/usr/local/lib/pkgconfig meson setup -Ddefault_library=static -Dnogui=true --buildtype release builddir \ + && export QT_PATH=/opt/qt-${QT_VERSION}-static \ + && export PATH=${QT_PATH}/bin:${PATH} \ + && export LDFLAGS="-L${QT_PATH}/lib -L${QT_PATH}/plugins/tls" \ + && meson setup -Ddefault_library=static -Dnogui=true --buildtype release builddir \ && meson compile -C builddir # stage files in INSTALLDIR -ENV INSTALLDIR=/opt -RUN mkdir -p ${INSTALLDIR}/usr/local/bin/ ${INSTALLDIR}/usr/lib64/ ${INSTALLDIR}/etc/systemd/system/ \ - && cp /lib64/libQt5Core.so.5 /lib64/libQt5Network.so.5 ${INSTALLDIR}/usr/lib64/ \ +ENV INSTALLDIR=/artifacts +RUN mkdir -p ${INSTALLDIR}/usr/local/bin/ ${INSTALLDIR}/etc/systemd/system/ \ && cp /root/builddir/jacktrip ${INSTALLDIR}/usr/local/bin/ \ && strip ${INSTALLDIR}/usr/local/bin/jacktrip COPY linux/container/jacktrip.service ${INSTALLDIR}/etc/systemd/system/ @@ -42,9 +50,6 @@ COPY linux/container/jacktrip.service ${INSTALLDIR}/etc/systemd/system/ # use the jack ubi-init container FROM jacktrip/jack:${JACK_VERSION} -# install libraries that we need for things to run -RUN dnf install -y --nodocs libicu pcre libstdc++ compat-openssl11 pcre2-utf16 - # add jacktrip user, enable service and allow access to jackd RUN useradd -r -m -N -G audio -s /usr/sbin/nologin jacktrip \ && chown -R jacktrip.audio /home/jacktrip \ @@ -56,7 +61,7 @@ RUN useradd -r -m -N -G audio -s /usr/sbin/nologin jacktrip \ && echo 'echo "JACKTRIP_OPTS=\"$JACKTRIP_OPTS\"" > /etc/default/jacktrip' >> /usr/sbin/defaults.sh # copy the artifacts we built into the final container image -COPY --from=builder /opt / +COPY --from=builder /artifacts / # jacktrip hub server listens on 4464 and uses 61000+ for clients EXPOSE 4464/tcp diff --git a/docs/changelog.yml b/docs/changelog.yml index f51ab4c..4362431 100644 --- a/docs/changelog.yml +++ b/docs/changelog.yml @@ -1,3 +1,20 @@ +- Version: "2.3.0" + Date: 2024-05-15 + Description: + - (added) Static Qt 5.15.13 nogui (CLI) builds for all platforms + - (added) VS Mode learn more buttons and warning links + - (updated) Significant PLC performance and quality improvements + - (updated) Reduced amount of latency added for PLC strategy + - (updated) Merged PLC buffer strategies (3 is now identical to 4) + - (updated) Automatically start PLC worker for slower predictions + - (updated) Builds now use Qt 6.2.8 for OSX and 5.15.13 for Linux + - (updated) Linux containers now use static builds with Qt 6.5.3 + - (updated) VS Mode help links go to support.jacktrip.com + - (updated) VS Mode manage button goes to new studio dashboard + - (fixed) PLC degradation when peer != local buffer sizes + - (fixed) Port binding on machines that don't support IPv6 + - (fixed) Command line interface debug logging improvements + - (fixed) VS Mode truncation of invite copied tooltip message - Version: "2.2.5" Date: 2024-03-28 Description: diff --git a/meson.build b/meson.build index d79bd43..74ea661 100644 --- a/meson.build +++ b/meson.build @@ -31,9 +31,9 @@ defines = ['-DWAIRTOHUB'] c_defines = [] incdirs = [] -if get_option('buildtype') == 'release' - defines += ['-DNDEBUG'] - c_defines += ['-DNDEBUG'] +if get_option('debug') == false + defines += ['-DNDEBUG', '-DQT_NO_DEBUG'] + c_defines += ['-DNDEBUG', '-DQT_NO_DEBUG'] endif build_info = get_option('buildinfo') @@ -238,8 +238,52 @@ else endif endif -if qt_version == '6' and get_option('default_library') == 'static' - deps += dependency('qt6', modules: ['BundledLibpng', 'BundledPcre2', 'BundledHarfbuzz'], include_type: 'system') +if get_option('default_library') == 'static' + # use qmake to get paths for qt libraries and plugins + # seems like qt module should have a method for this, but it doesn't + qmake = find_program('qmake', required: true) + qt_libdir = run_command(qmake, '-query', 'QT_INSTALL_LIBS', check : true).stdout().strip() + qt_plugindir = run_command(qmake, '-query', 'QT_INSTALL_PLUGINS', check : true).stdout().strip() + if qt_version == '6' + # qt6 requires "Bundled*" modules for linking + deps += dependency('qt6', modules: ['BundledLibpng', 'BundledPcre2', 'BundledHarfbuzz', 'BundledZLIB'], include_type: 'system') + else + deps += compiler.find_library('qtpcre2', required : true, dirs : [qt_libdir]) + endif + if (host_machine.system() == 'linux') + # linux static + deps += compiler.find_library('ssl', required : true, dirs : [qt_libdir]) + deps += compiler.find_library('crypto', required : true, dirs : [qt_libdir]) + deps += compiler.find_library('dl', required : true) + deps += compiler.find_library('glib-2.0', required : true) + if qt_version == '6' + # we need a Q_IMPORT_LIBRARY for the openssl backend on linux + deps += compiler.find_library('qopensslbackend', required : true, dirs : [qt_plugindir+'/tls']) + src += ['src/QtStaticPlugins.cpp'] + endif + else + if (host_machine.system() == 'windows') + # windows static + deps += compiler.find_library('bcrypt', required : true) + deps += compiler.find_library('winmm', required : true) + deps += compiler.find_library('Crypt32', required : true) + if qt_version == '6' + deps += compiler.find_library('Authz', required : true) + endif + else + # mac static + # this approach fails for universal builds, so we have to just append to link_args + #deps += dependency('CoreServices', required : true) + link_args += ['-framework', 'CoreServices'] + link_args += ['-framework', 'CFNetwork'] + link_args += ['-framework', 'AppKit'] + link_args += ['-framework', 'IOKit'] + link_args += ['-framework', 'Security'] + link_args += ['-framework', 'GSS'] + link_args += ['-framework', 'SystemConfiguration'] + deps += dependency('zlib', required : true) + endif + endif endif # TODO: QT_OPENSOURCE should only be defined for open source Qt distribution @@ -320,4 +364,4 @@ summary({'JACK': jack_dep.found(), summary({'Application ID': application_id, 'GUI': not get_option('nogui'), 'WAIR': get_option('wair'), - 'Manpage': help2man.found()}, bool_yn: true, section: 'Configuration') \ No newline at end of file + 'Manpage': help2man.found()}, bool_yn: true, section: 'Configuration') diff --git a/releases/edge/mac-manifests.json b/releases/edge/mac-manifests.json index cbbd227..efc8137 100644 --- a/releases/edge/mac-manifests.json +++ b/releases/edge/mac-manifests.json @@ -1,6 +1,16 @@ { "app_name": "JackTrip", "releases": [ + { + "version": "2.2.5", + "changelog": "Full changelog at https://github.com/jacktrip/jacktrip/releases/tag/v2.2.5", + "download": { + "date": "2024-03-29T00:00:00Z", + "url": "https://files.jacktrip.org/app-builds/JackTrip-v2.2.5-macOS-x64-signed-installer.pkg", + "downloadSize": "177374940", + "sha256": "4e1ae62b5717141c27b3a569311b3c17f7daa3065ee7bb69c18faf5c28ba5e8e" + } + }, { "version": "2.2.4", "changelog": "Full changelog at https://github.com/jacktrip/jacktrip/releases/tag/v2.2.4", diff --git a/releases/edge/win-manifests.json b/releases/edge/win-manifests.json index ac56123..9a71d21 100644 --- a/releases/edge/win-manifests.json +++ b/releases/edge/win-manifests.json @@ -1,6 +1,16 @@ { "app_name": "JackTrip", "releases": [ + { + "version": "2.2.5", + "changelog": "Full changelog at https://github.com/jacktrip/jacktrip/releases/tag/v2.2.5", + "download": { + "date": "2024-03-29T00:00:00Z", + "url": "https://files.jacktrip.org/app-builds/JackTrip-v2.2.5-Windows-x64-signed-installer.msi", + "downloadSize": "116228096", + "sha256": "903343959992733001d4e7db30c83fc4ff8120903aeca0eb86b1601c9d21e15b" + } + }, { "version": "2.2.4", "changelog": "Full changelog at https://github.com/jacktrip/jacktrip/releases/tag/v2.2.4", diff --git a/releases/stable/linux-manifests.json b/releases/stable/linux-manifests.json index 48460ac..514ed82 100644 --- a/releases/stable/linux-manifests.json +++ b/releases/stable/linux-manifests.json @@ -1,6 +1,16 @@ { "app_name": "JackTrip", "releases": [ + { + "version": "2.2.5", + "changelog": "Full changelog at https://github.com/jacktrip/jacktrip/releases/tag/v2.2.5", + "download": { + "date": "2024-03-29T00:00:00Z", + "url": "https://files.jacktrip.org/app-builds/JackTrip-v2.2.5-Linux-x64-binary.zip", + "downloadSize": "1250262", + "sha256": "3995fb1c56983ee72f3a51c10ea1b94c635f3ee52308a376a0357a861b0a9e37" + } + }, { "version": "2.2.4", "changelog": "Full changelog at https://github.com/jacktrip/jacktrip/releases/tag/v2.2.4", diff --git a/releases/stable/mac-manifests.json b/releases/stable/mac-manifests.json index e5ddeef..7caef64 100644 --- a/releases/stable/mac-manifests.json +++ b/releases/stable/mac-manifests.json @@ -1,6 +1,16 @@ { "app_name": "JackTrip", "releases": [ + { + "version": "2.2.5", + "changelog": "Full changelog at https://github.com/jacktrip/jacktrip/releases/tag/v2.2.5", + "download": { + "date": "2024-03-29T00:00:00Z", + "url": "https://files.jacktrip.org/app-builds/JackTrip-v2.2.5-macOS-x64-signed-installer.pkg", + "downloadSize": "177374940", + "sha256": "4e1ae62b5717141c27b3a569311b3c17f7daa3065ee7bb69c18faf5c28ba5e8e" + } + }, { "version": "2.2.4", "changelog": "Full changelog at https://github.com/jacktrip/jacktrip/releases/tag/v2.2.4", diff --git a/releases/stable/win-manifests.json b/releases/stable/win-manifests.json index 5681cf1..e8451be 100644 --- a/releases/stable/win-manifests.json +++ b/releases/stable/win-manifests.json @@ -1,6 +1,16 @@ { "app_name": "JackTrip", "releases": [ + { + "version": "2.2.5", + "changelog": "Full changelog at https://github.com/jacktrip/jacktrip/releases/tag/v2.2.5", + "download": { + "date": "2024-03-29T00:00:00Z", + "url": "https://files.jacktrip.org/app-builds/JackTrip-v2.2.5-Windows-x64-signed-installer.msi", + "downloadSize": "116228096", + "sha256": "903343959992733001d4e7db30c83fc4ff8120903aeca0eb86b1601c9d21e15b" + } + }, { "version": "2.2.4", "changelog": "Full changelog at https://github.com/jacktrip/jacktrip/releases/tag/v2.2.4", diff --git a/src/AudioInterface.cpp b/src/AudioInterface.cpp index 0f684f1..918f696 100644 --- a/src/AudioInterface.cpp +++ b/src/AudioInterface.cpp @@ -375,7 +375,7 @@ void AudioInterface::audioOutputCallback(QVarLengthArray& out_buffer, out_buffer.data()); // compute ap2 into aob2 - //#define ADD_DIRECT + // #define ADD_DIRECT #ifdef ADD_DIRECT for (int i = 0; i < nChansIn; i++) { sample_t* mix_sample = out_buffer[i]; @@ -819,16 +819,17 @@ void AudioInterface::setDevicesWarningMsg(warningMessageT msg) mWarningMsg = "The buffer size setting for your audio device will cause high latency " "or audio delay. Use an audio device that supports small buffer sizes " - "to reduce audio delays."; - mWarningHelpUrl = ""; + "to reduce audio delays. Click for more info."; + mWarningHelpUrl = "https://support.jacktrip.com/recommended-audio-interfaces"; mHighLatencyFlag = true; break; case DEVICE_WARN_ASIO_LATENCY: mWarningMsg = "You audio device drivers may cause high latency or audio delay. Install " "and use ASIO drivers provided by your device's manufacturer to reduce " - "audio delays."; - mWarningHelpUrl = "https://help.jacktrip.org/hc/en-us/articles/4409919243155"; + "audio delays. Click for more info."; + mWarningHelpUrl = + "https://support.jacktrip.com/troubleshooting-windows-drivers-and-asio"; mHighLatencyFlag = true; break; case DEVICE_WARN_ALSA_LATENCY: @@ -856,7 +857,8 @@ void AudioInterface::setDevicesErrorMsg(errorMessageT msg) "The two devices you have selected are not compatible. Please select a " "different pair of devices."; #ifdef _WIN32 - mErrorHelpUrl = "https://help.jacktrip.org/hc/en-us/articles/4409919243155"; + mErrorHelpUrl = + "https://support.jacktrip.com/troubleshooting-windows-drivers-and-asio"; #else mErrorHelpUrl = ""; #endif @@ -877,7 +879,8 @@ void AudioInterface::setDevicesErrorMsg(errorMessageT msg) case DEVICE_ERR_SAME_ASIO: mErrorMsg = "When using ASIO, please select the same device for your input and output."; - mErrorHelpUrl = "https://help.jacktrip.org/hc/en-us/articles/4409919243155"; + mErrorHelpUrl = + "https://support.jacktrip.com/troubleshooting-windows-drivers-and-asio"; break; #endif default: diff --git a/src/AudioTester.h b/src/AudioTester.h index f8430a3..0d31be1 100644 --- a/src/AudioTester.h +++ b/src/AudioTester.h @@ -41,7 +41,7 @@ #include #include "jacktrip_types.h" // sample_t -//#include +// #include #include #include #include diff --git a/src/DataProtocol.h b/src/DataProtocol.h index c4c4032..5c5c1a8 100644 --- a/src/DataProtocol.h +++ b/src/DataProtocol.h @@ -47,7 +47,7 @@ #include //inet(3) functions #include #include //sockaddr_in{} and other Internet defns -//#include //for shared_ptr +// #include //for shared_ptr #endif #include diff --git a/src/JMess.cpp b/src/JMess.cpp index 8517334..2b967f2 100644 --- a/src/JMess.cpp +++ b/src/JMess.cpp @@ -98,10 +98,10 @@ JMess::~JMess() /////////////////////////////// // test NUC as server -//#define HARDWIRED_AUDIO_PROCESS_ON_SERVER "par20straightWire" -//#define ENUMERATE "" -//#define HARDWIRED_AUDIO_PROCESS_ON_SERVER_IN ":in_" -//#define HARDWIRED_AUDIO_PROCESS_ON_SERVER_OUT ":out_" +// #define HARDWIRED_AUDIO_PROCESS_ON_SERVER "par20straightWire" +// #define ENUMERATE "" +// #define HARDWIRED_AUDIO_PROCESS_ON_SERVER_IN ":in_" +// #define HARDWIRED_AUDIO_PROCESS_ON_SERVER_OUT ":out_" /////////////////////////////// // test Riviera as server diff --git a/src/JackAudioInterface.cpp b/src/JackAudioInterface.cpp index 7221827..b78b385 100644 --- a/src/JackAudioInterface.cpp +++ b/src/JackAudioInterface.cpp @@ -46,9 +46,9 @@ #include "jacktrip_globals.h" ///************PROTORYPE FOR CELT************************** -//#include -//#include -//#include +// #include +// #include +// #include ///******************************************************** #include @@ -125,12 +125,12 @@ void JackAudioInterface::setupClient() QMutexLocker locker(&sJackMutex); // TODO: this needs a timeout because it will hang indefinitely // if the Jack server is not running -//#ifndef WAIR // WAIR -// mClient = jack_client_open (client_name, options, &status, server_name); -//#else -// mClient = jack_client_open (client_name, JackUseExactName, &status, -// server_name); -//#endif // endwhere +// #ifndef WAIR // WAIR +// mClient = jack_client_open (client_name, options, &status, server_name); +// #else +// mClient = jack_client_open (client_name, JackUseExactName, &status, +// server_name); +// #endif // endwhere #ifndef WAIR // WAIR mClient = jack_client_open(clientName.constData(), options, &status); #else diff --git a/src/JackTrip.cpp b/src/JackTrip.cpp index 2e8b2b7..ad5bd5b 100644 --- a/src/JackTrip.cpp +++ b/src/JackTrip.cpp @@ -3,7 +3,7 @@ JackTrip: A System for High-Quality Audio Network Performance over the Internet - Copyright (c) 2008-2021 Juan-Pablo Caceres, Chris Chafe. + Copyright (c) 2008-2024 Juan-Pablo Caceres, Chris Chafe. SoundWIRE group at CCRMA, Stanford University. Permission is hereby granted, free of charge, to any person @@ -108,7 +108,6 @@ JackTrip::JackTrip(jacktripModeT JacktripMode, dataProtocolT DataProtocolType, #endif // endwhere , mBufferQueueLength(BufferQueueLength) , mBufferStrategy(1) - , mRegulatorThreadPtr(NULL) , mBroadcastQueueLength(0) , mSampleRate(gDefaultSampleRate) , mDeviceID(gDefaultDeviceID) @@ -423,21 +422,12 @@ void JackTrip::setupRingBuffers() new RingBuffer(audio_output_slot_size, mBufferQueueLength); mPacketHeader->setBufferRequiresSameSettings(true); } else if ((mBufferStrategy == 3) || (mBufferStrategy == 4)) { - bool use_worker_thread = (mBufferStrategy == 3); cout << "Using experimental buffer strategy " << mBufferStrategy - << "-- Regulator with PLC (worker=" - << (use_worker_thread ? "true" : "false") << ")" << endl; + << "-- Regulator with PLC" << endl; Regulator* regulator_ptr = new Regulator(mNumAudioChansOut, mAudioBitResolution, mAudioBufferSize, mBufferQueueLength, mBroadcastQueueLength, mSampleRate); mReceiveRingBuffer = regulator_ptr; - if (use_worker_thread) { -#ifdef REGULATOR_SHARED_WORKER_THREAD - regulator_ptr->enableWorkerThread(mRegulatorThreadPtr); -#else - regulator_ptr->enableWorkerThread(); -#endif - } // bufStrategy 3 or 4, mBufferQueueLength is in integer msec not packets mPacketHeader->setBufferRequiresSameSettings(false); // = asym is default @@ -779,7 +769,7 @@ void JackTrip::onStatTimer() // pkt_stat.lost << "/" // << pkt_stat.outOfOrder << "/" << pkt_stat.revived << " \n tot: " << pkt_stat.tot << " \t tol: " << setw(5) - << INVFLOATFACTOR * recv_io_stat.autoq_corr << " \t dsp (last): " << setw(5) + << INVFLOATFACTOR * recv_io_stat.autoq_corr << " \t dsp (max): " << setw(5) << INVFLOATFACTOR * recv_io_stat.autoq_rate // << " sync: " << recv_io_stat.level << "/" // << recv_io_stat.buf_inc_underrun << "/" @@ -1582,11 +1572,11 @@ bool JackTrip::checkIfPortIsBinded(int port) std::map::iterator it; for (it = interfaces.begin(); it != interfaces.end(); it++) { bool binded = UdpSockTemp.bind(it->second, port, QUdpSocket::DontShareAddress); - if (!binded) { - UdpSockTemp.close(); // close the socket + QUdpSocket::SocketError err = UdpSockTemp.error(); + UdpSockTemp.close(); + if (!binded && err != QUdpSocket::UnsupportedSocketOperationError) { return true; } - UdpSockTemp.close(); } return false; } diff --git a/src/JackTrip.h b/src/JackTrip.h index 49b78be..166106b 100644 --- a/src/JackTrip.h +++ b/src/JackTrip.h @@ -3,7 +3,7 @@ JackTrip: A System for High-Quality Audio Network Performance over the Internet - Copyright (c) 2008-2021 Juan-Pablo Caceres, Chris Chafe. + Copyright (c) 2008-2024 Juan-Pablo Caceres, Chris Chafe. SoundWIRE group at CCRMA, Stanford University. Permission is hereby granted, free of charge, to any person @@ -227,7 +227,6 @@ class JackTrip : public QObject { mBufferStrategy = BufferStrategy; } - void setRegulatorThread(QThread* ptr) { mRegulatorThreadPtr = ptr; } /// \brief Sets (override) Audio Bit Resolution after construction virtual void setAudioBitResolution( AudioInterface::audioBitResolutionT AudioBitResolution) @@ -665,7 +664,6 @@ class JackTrip : public QObject #endif // endwhere int mBufferQueueLength; ///< Audio Buffer from network queue length int mBufferStrategy; - QThread* mRegulatorThreadPtr; int mBroadcastQueueLength; uint32_t mSampleRate; ///< Sample Rate uint32_t mDeviceID; ///< RTAudio DeviceID diff --git a/src/JackTripWorker.cpp b/src/JackTripWorker.cpp index b632794..2c59173 100644 --- a/src/JackTripWorker.cpp +++ b/src/JackTripWorker.cpp @@ -45,7 +45,7 @@ #include "JackTrip.h" #include "UdpHubListener.h" -//#include "NetKS.h" +// #include "NetKS.h" #include "LoopBack.h" #include "Settings.h" #ifdef WAIR // wair @@ -194,7 +194,6 @@ void JackTripWorker::start() mJackTrip->setBindPorts(mServerPort); // jacktrip.setPeerPorts(mClientPort); mJackTrip->setBufferStrategy(mBufferStrategy); - mJackTrip->setRegulatorThread(mRegulatorThreadPtr); mJackTrip->setNetIssuesSimulation(mSimulatedLossRate, mSimulatedJitterRate, mSimulatedDelayRel); mJackTrip->setBroadcast(mBroadcastQueue); diff --git a/src/JackTripWorker.h b/src/JackTripWorker.h index 686e32d..dc31a15 100644 --- a/src/JackTripWorker.h +++ b/src/JackTripWorker.h @@ -104,7 +104,6 @@ class JackTripWorker : public QObject int getID() { return mID; } void setBufferStrategy(int BufferStrategy) { mBufferStrategy = BufferStrategy; } - void setRegulatorThread(QThread* ptr) { mRegulatorThreadPtr = ptr; } void setNetIssuesSimulation(double loss, double jitter, double delay_rel) { mSimulatedLossRate = loss; @@ -176,14 +175,13 @@ class JackTripWorker : public QObject int mID = 0; ///< ID thread number - int mBufferStrategy = 1; - int mBroadcastQueue = 0; - double mSimulatedLossRate = 0.0; - double mSimulatedJitterRate = 0.0; - double mSimulatedDelayRel = 0.0; - bool mUseRtUdpPriority = false; - int mIOStatTimeout = 0; - QThread* mRegulatorThreadPtr = NULL; + int mBufferStrategy = 1; + int mBroadcastQueue = 0; + double mSimulatedLossRate = 0.0; + double mSimulatedJitterRate = 0.0; + double mSimulatedDelayRel = 0.0; + bool mUseRtUdpPriority = false; + int mIOStatTimeout = 0; QSharedPointer mIOStatStream; #ifdef WAIR // wair diff --git a/src/Limiter.h b/src/Limiter.h index 165a5c8..e55a92d 100644 --- a/src/Limiter.h +++ b/src/Limiter.h @@ -42,7 +42,7 @@ #ifndef __LIMITER_H__ #define __LIMITER_H__ -//#define SINE_TEST +// #define SINE_TEST #ifdef SINE_TEST #include "limitertest.h" diff --git a/src/PacketHeader.cpp b/src/PacketHeader.cpp index 54f6e3f..5792456 100644 --- a/src/PacketHeader.cpp +++ b/src/PacketHeader.cpp @@ -71,9 +71,9 @@ inline int gettimeofday(struct timeval* p, [[maybe_unused]] void* tz) #endif #endif -//####################################################################### -//####################### PacketHeader ################################## -//####################################################################### +// ####################################################################### +// ####################### PacketHeader ################################## +// ####################################################################### //*********************************************************************** PacketHeader::PacketHeader(JackTrip* jacktrip) : mBufferRequiresSameSettings(false), mJackTrip(jacktrip), mSeqNumber(0) @@ -90,9 +90,9 @@ uint64_t PacketHeader::usecTime() (tv.tv_usec)); // plus the microseconds. Type suseconds_t, range [-1, 1000000] } -//####################################################################### -//####################### DefaultHeader ################################# -//####################################################################### +// ####################################################################### +// ####################### DefaultHeader ################################# +// ####################################################################### //*********************************************************************** DefaultHeader::DefaultHeader(JackTrip* jacktrip) : PacketHeader(jacktrip) { @@ -276,9 +276,9 @@ uint8_t DefaultHeader::getPeerNumOutgoingChannels(int8_t* full_packet) const return peer_header->NumOutgoingChannelsToNet; } -//####################################################################### -//####################### JamLinkHeader ################################# -//####################################################################### +// ####################################################################### +// ####################### JamLinkHeader ################################# +// ####################################################################### //*********************************************************************** JamLinkHeader::JamLinkHeader(JackTrip* jacktrip) : PacketHeader(jacktrip) { @@ -349,8 +349,8 @@ void JamLinkHeader::fillHeaderCommonFromAudio() } } -//####################################################################### -//####################### EmptyHeader ################################# -//####################################################################### +// ####################################################################### +// ####################### EmptyHeader ################################# +// ####################################################################### //*********************************************************************** EmptyHeader::EmptyHeader(JackTrip* jacktrip) : PacketHeader(jacktrip) {} diff --git a/src/PacketHeader.h b/src/PacketHeader.h index c31b4ba..84c0351 100644 --- a/src/PacketHeader.h +++ b/src/PacketHeader.h @@ -39,7 +39,7 @@ #define __PACKETHEADER_H__ #include -//#include // for shared_ptr +// #include // for shared_ptr #include #include #include @@ -101,9 +101,9 @@ struct JamLinkHeaderStuct : public HeaderStruct { uint32_t TimeStamp; ///< Time Stamp }; -//####################################################################### -//####################### PacketHeader ################################## -//####################################################################### +// ####################################################################### +// ####################### PacketHeader ################################## +// ####################################################################### /** \brief Base class for header type. Subclass this struct to * create a new header. */ @@ -171,9 +171,9 @@ class PacketHeader : public QObject uint16_t mSeqNumber; }; -//####################################################################### -//####################### DefaultHeader ################################# -//####################################################################### +// ####################################################################### +// ####################### DefaultHeader ################################# +// ####################################################################### /** \brief Default Header */ class DefaultHeader : public PacketHeader @@ -215,9 +215,9 @@ class DefaultHeader : public PacketHeader DefaultHeaderStruct mHeader; ///< Default Header Struct }; -//####################################################################### -//####################### JamLinkHeader ################################# -//####################################################################### +// ####################################################################### +// ####################### JamLinkHeader ################################# +// ####################################################################### /** \brief JamLink Header */ @@ -273,9 +273,9 @@ class JamLinkHeader : public PacketHeader JamLinkHeaderStuct mHeader; ///< JamLink Header Struct }; -//####################################################################### -//####################### EmptyHeader ################################# -//####################################################################### +// ####################################################################### +// ####################### EmptyHeader ################################# +// ####################################################################### /** \brief Empty Header to use with systems that don't include a header. */ diff --git a/src/ProcessPlugin.cpp b/src/ProcessPlugin.cpp index 6f708aa..4dcc4bd 100644 --- a/src/ProcessPlugin.cpp +++ b/src/ProcessPlugin.cpp @@ -1,4 +1,4 @@ -//#include "ProcessPlugin.h" +// #include "ProcessPlugin.h" /* //---------------------------------------------------------------------------- diff --git a/src/QtStaticPlugins.cpp b/src/QtStaticPlugins.cpp new file mode 100644 index 0000000..8e9e079 --- /dev/null +++ b/src/QtStaticPlugins.cpp @@ -0,0 +1,4 @@ +#include + +// used to load tls backend for linux static builds +Q_IMPORT_PLUGIN(QTlsBackendOpenSSL) diff --git a/src/Regulator.cpp b/src/Regulator.cpp index a636150..a92a724 100644 --- a/src/Regulator.cpp +++ b/src/Regulator.cpp @@ -3,7 +3,7 @@ JackTrip: A System for High-Quality Audio Network Performance over the Internet - Copyright (c) 2021 Juan-Pablo Caceres, Chris Chafe. + Copyright (c) 2024 Juan-Pablo Caceres, Chris Chafe. SoundWIRE group at CCRMA, Stanford University. Permission is hereby granted, free of charge, to any person @@ -32,7 +32,7 @@ /** * \file Regulator.cpp * \author Chris Chafe - * \date May-Sep 2021 + * \date May 2021 - May 2024 */ // EXPERIMENTAL for testing in JackTrip v1.5. @@ -81,68 +81,198 @@ #include "Regulator.h" +#include #include -#include -#include "JitterBuffer.h" -#include "jacktrip_globals.h" +#include "JitterBuffer.h" // for broadcast + using std::cout; using std::endl; using std::setw; // constants... -constexpr int HIST = 4; // for mono at FPP 16-128, see below for > mono, > 128 -constexpr int NumSlotsMax = 4096; // mNumSlots looped for recent arrivals -constexpr double AutoMax = 250.0; // msec bounds on insane IPI, like ethernet unplugged +constexpr bool PrintDirect = false; // print stats direct from -V not -I +constexpr int HIST = 2; // mPacketsInThePast setting for +constexpr int HISTFPP = 128; // default FPP when calibrating burg window + +constexpr int NumSlots = 4096; // NumSlots looped for recent arrivals +constexpr double AutoMax = 250.0; // msec bounds on insane IPI, like ethernet unplugged constexpr double AutoInitDur = 3000.0; // kick in auto after this many msec constexpr double AutoInitValFactor = 0.5; // scale for initial mMsecTolerance during init phase if unspecified // tweak -constexpr int WindowDivisor = 8; // for faster auto tracking -constexpr int MaxFPP = 1024; // tested up to this FPP -constexpr int MaxAutoHeadroom = 5; // maximum auto headroom in milliseconds +constexpr int WindowDivisor = 8; // for faster auto tracking constexpr double AutoHeadroomGlitchTolerance = - 0.007; // Acceptable rate of glitches before auto headroom is increased (0.7%) + 0.02; // Acceptable rate of skips before auto headroom is increased (2.0%) constexpr double AutoHistoryWindow = 60; // rolling window of time (in seconds) over which auto tolerance roughly adjusts constexpr double AutoSmoothingFactor = 1.0 / (WindowDivisor * AutoHistoryWindow); // EWMA smoothing factor for auto tolerance +BurgAlgorithm::BurgAlgorithm(int size) // mUpToNow = mPacketsInThePast * fpp +{ + // GET SIZE FROM INPUT VECTORS + m = N = size - 1; + this->size = size; + if (size < m) + cout << "time_series should have more elements than the AR order is" << endl; + Ak.resize(size); + for (int i = 0; i < size; i++) + Ak[i] = 0.0; + AkReset.resize(size); + AkReset = Ak; + AkReset[0] = 1.0; + + f.resize(size); + b.resize(size); +} + +void BurgAlgorithm::train(std::vector& coeffs, const std::vector& x, + int size) +{ + // INITIALIZE Ak + Ak = AkReset; + + // INITIALIZE f and b + for (int i = 0; i < size; i++) + f[i] = b[i] = x[i]; + + // INITIALIZE Dk + float Dk = 0.0; + + for (int j = 0; j <= N; j++) + Dk += 2.00002 * f[j] * f[j]; // needs more damping than orig 2.0 + + Dk -= f[0] * f[0] + b[N] * b[N]; + + // BURG RECURSION + for (int k = 0; k < m; k++) { + // COMPUTE MU + float mu = 0.0; + for (int n = 0; n <= N - k - 1; n++) { + mu += f[n + k + 1] * b[n]; + } + + if (Dk == 0.0) + Dk = FLT_EPSILON; // 0.0000001 from online testing when it was a double + mu *= -2.0 / Dk; + + // UPDATE Ak + for (int n = 0; n <= (k + 1) / 2; n++) { + float t1 = Ak[n] + mu * Ak[k + 1 - n]; + float t2 = Ak[k + 1 - n] + mu * Ak[n]; + Ak[n] = t1; + Ak[k + 1 - n] = t2; + } + + // UPDATE f and b + for (int n = 0; n <= N - k - 1; n++) { + float t1 = f[n + k + 1] + mu * b[n]; // were double + float t2 = b[n] + mu * f[n + k + 1]; + f[n + k + 1] = t1; + b[n] = t2; + } + + // UPDATE Dk + Dk = (1.0 - mu * mu) * Dk - f[k + 1] * f[k + 1] - b[N - k - 1] * b[N - k - 1]; + } + // ASSIGN COEFFICIENTS + coeffs.assign(++Ak.begin(), Ak.end()); +} + +void BurgAlgorithm::predict(std::vector& coeffs, std::vector& tail, + int size) +{ + for (int i = m; i < size; i++) { + tail[i] = 0.0; + for (int j = 0; j < m; j++) { + tail[i] -= coeffs[j] * tail[i - 1 - j]; + } + } +} + //******************************************************************************* -Regulator::Regulator(int rcvChannels, int bit_res, int FPP, int qLen, int bqLen, +Channel::Channel(int fpp, int upToNow, int packetsInThePast) // operates at peer FPP +{ + predictedNowPacket.resize(fpp); + realNowPacket.resize(fpp); + outputNowPacket.resize(fpp); + futurePredictedPacket.resize(fpp); + mTmpFloatBuf.resize(fpp); + mZeros.resize(fpp); + for (int i = 0; i < fpp; i++) + predictedNowPacket[i] = realNowPacket[i] = outputNowPacket[i] = + futurePredictedPacket[i] = mTmpFloatBuf[i] = mZeros[i] = 0.0; + + realPast.resize(upToNow); + for (int i = 0; i < upToNow; i++) + realPast[i] = 0.0; + zeroPast.resize(upToNow); + for (int i = 0; i < upToNow; i++) + zeroPast[i] = 1.0; + + for (int i = 0; i < packetsInThePast; i++) { // don't resize, using push_back + std::vector tmp(fpp); + for (int j = 0; j < fpp; j++) + tmp[j] = 0.0; + predictedPast.push_back(tmp); + } + + mCoeffsSize = upToNow - 1; + coeffs.resize(mCoeffsSize); + for (int i = 0; i < mCoeffsSize; i++) { + coeffs[i] = 0.0; + } + + mTailSize = upToNow + fpp * 2; + prediction.resize(mTailSize); + for (int i = 0; i < mTailSize; i++) { + prediction[i] = 0.0; + } + + // set up ring buffer + mRing = packetsInThePast; + mWptr = mRing / 2; + for (int i = 0; i < mRing; i++) { // don't resize, using push_back + std::vector tmp(fpp); + for (int j = 0; j < fpp; j++) + tmp[j] = 0.0; + mPacketRing.push_back(tmp); + } + lastWasGlitch = false; +} + +// push received packet to ring +void Channel::ringBufferPush() +{ + mPacketRing[mWptr % mRing] = mTmpFloatBuf; + mWptr++; + mWptr %= mRing; +} + +// pull numbered packet from ring +void Channel::ringBufferPull(int past) +{ + int pastPtr = mWptr - past; + if (pastPtr < 0) + pastPtr += mRing; + mTmpFloatBuf = mPacketRing[pastPtr]; +} + +//******************************************************************************* +Regulator::Regulator(int rcvChannels, int bit_res, int localFPP, int qLen, int bqLen, int sample_rate) : RingBuffer(0, 0) + , mInitialized(false) , mNumChannels(rcvChannels) , mAudioBitRes(bit_res) - , mFPP(FPP) + , mLocalFPP(localFPP) , mSampleRate(sample_rate) , mMsecTolerance((double)qLen) // handle non-auto mode, expects positive qLen - , pushStat(NULL) - , pullStat(NULL) - , mAuto(false) - , mSkipAutoHeadroom(true) - , mLastGlitches(0) - , mCurrentHeadroom(0) - , mUseWorkerThread(false) , m_b_BroadcastQueueLength(bqLen) - , mRegulatorThreadPtr(NULL) - , mRegulatorWorkerPtr(NULL) { - // catch settings that are compute bound using long HIST - // hub client rcvChannels is set from client's settings parameters - // hub server rcvChannels is set from connecting client, not from hub parameters - // if (mNumChannels > MaxChans) { - // std::cerr << "*** Regulator.cpp: receive channels = " << mNumChannels - // << " larger than max channels = " << MaxChans << "\n"; - // exit(1); - // } - if (mFPP > MaxFPP) { - std::cerr << "*** Regulator.cpp: local FPP = " << mFPP - << " larger than max FPP = " << MaxFPP << "\n"; - exit(1); - } switch (mAudioBitRes) { // int from JitterBuffer to AudioInterface enum case 1: mBitResolutionMode = AudioInterface::audioBitResolutionT::BIT8; @@ -157,299 +287,280 @@ Regulator::Regulator(int rcvChannels, int bit_res, int FPP, int qLen, int bqLen, mBitResolutionMode = AudioInterface::audioBitResolutionT::BIT32; break; } - mHist = HIST; // HIST (default) is 4 - // as FPP decreases the rate of PLC triggers potentially goes up - // and load increases so don't use an inverse relation + mScale = pow(2.0, (((mBitResolutionMode * 8) - 1.0))) - 1.0; + mInvScale = 1.0 / mScale; + + if (gVerboseFlag) + cout << "mBitResolutionMode = " << mBitResolutionMode << " scale = " << mScale + << endl; + + mIncomingTiming.resize(NumSlots); + for (int i = 0; i < NumSlots; i++) { + mIncomingTiming[i] = 0.0; + } - // crossfaded prediction is a full packet ahead of predicted - // packet, so the size of mPrediction needs to account for 2 full packets (2*FPP) - // but trainSamps = (HIST * FPP) and mPrediction.resize(trainSamps - 1, 0.0) so if - // hist = 2, then it exceeds the size + mLocalFPPdurMsec = 1000.0 * mLocalFPP / mSampleRate; + mLocalBytes = mLocalFPP * mNumChannels * mBitResolutionMode; - if (((mNumChannels > 1) && (mFPP > 64)) || (mFPP > 128)) - mHist = 3; // min packets for prediction, needs at least 3 + // mPhasor.resize(mNumChannels, 0.0); +} + +Regulator::~Regulator() +{ + delete[] mXfrBuffer; + delete[] mBroadcastBuffer; + delete[] mSlotBuf; + delete pushStat; + delete pullStat; + for (int i = 0; i < mNumChannels; i++) + delete mChanData[i]; + if (m_b_BroadcastRingBuffer) + delete m_b_BroadcastRingBuffer; + delete mTime; + delete ba; + if (mWorkerThreadPtr != nullptr) { + mWorkerThreadPtr->quit(); + mWorkerThreadPtr->wait(); + delete mWorkerThreadPtr; + } + if (mRegulatorWorkerPtr) + delete mRegulatorWorkerPtr; + if (mWorkerBuffer) + delete[] mWorkerBuffer; +} + +//******************************************************************************* +void Regulator::setFPPratio(int len) +{ + // only for first peer packet + if (mInitialized) { + return; + } + + mPeerBytes = len; + mPeerFPP = len / (mNumChannels * mBitResolutionMode); + mPeerFPPdurMsec = 1000.0 * mPeerFPP / mSampleRate; + mFPPratioNumerator = 1; + mFPPratioDenominator = 1; + + ////////////////////////////////////// + + mPacketsInThePast = HIST; // HIST is the setting for HISTFPP + + if (mPeerFPP < HISTFPP) + mPacketsInThePast *= (HISTFPP / mPeerFPP); // but don't go below 2 + else if (mPeerFPP > (HISTFPP * 2)) + mPacketsInThePast = 1; // 1 is enough history @ 512 or greater if (gVerboseFlag) - cout << "mHist = " << mHist << " at " << mFPP << "\n"; - mBytes = mFPP * mNumChannels * mBitResolutionMode; - mXfrBuffer = new int8_t[mBytes]; - mPacketCnt = 0; // burg initialization - mFadeUp.resize(mFPP, 0.0); - mFadeDown.resize(mFPP, 0.0); - for (int i = 0; i < mFPP; i++) { - mFadeUp[i] = (double)i / (double)mFPP; + cout << "mPacketsInThePast = " << mPacketsInThePast << " at " << mPeerFPP << " / " + << mLocalFPP << endl; + + mPcnt = 0; + mTime = new Time(); + mTime->start(); + mUpToNow = mPacketsInThePast * mPeerFPP; // duration + mBeyondNow = (mPacketsInThePast + 1) * mPeerFPP; // duration + + ba = new BurgAlgorithm(mUpToNow); + mPeerFPPdurMsec = 1000.0 * mPeerFPP / mSampleRate; + mPeerBytes = mPeerFPP * mNumChannels * mBitResolutionMode; + + ////////////////////////////////////// + + if (mPeerFPP != mLocalFPP) { + if (mPeerFPP > mLocalFPP) + mFPPratioDenominator = mPeerFPP / mLocalFPP; + else + mFPPratioNumerator = mLocalFPP / mPeerFPP; + } + + // bufstrategy 1 autoq mode overloads qLen with negative val + // creates this ugly code + if (mMsecTolerance <= 0) { // handle -q auto or, for example, -q auto10 + mAuto = true; + // default is -500 from bufstrategy 1 autoq mode + // use mMsecTolerance to set headroom + if (mMsecTolerance == -500.0) { + mAutoHeadroom = -1; + cout << "PLC is in auto mode and has been set with variable headroom" << endl; + } else { + mAutoHeadroom = std::abs(mMsecTolerance); + cout << "PLC is in auto mode and has been set with " << mAutoHeadroom + << "ms headroom" << endl; + if (mAutoHeadroom > 50.0) + cout << "That's a very large value and should be less than, " + "for example, 50ms" + << endl; + } + // found an interesting relationship between mPeerFPP and initial + // mMsecTolerance mPeerFPP*0.5 is pretty good though that's an oddball + // conversion of bufsize directly to msec + mMsecTolerance = (mPeerFPP * AutoInitValFactor); + } else { + cout << "PLC is using a fixed tolerance of " << mMsecTolerance << "ms" << endl; + } + + mXfrBuffer = new int8_t[mPeerBytes]; + memset(mXfrBuffer, 0, mPeerBytes); + mBroadcastBuffer = new int8_t[mPeerBytes]; + memset(mBroadcastBuffer, 0, mPeerBytes); + + mFadeUp.resize(mPeerFPP, 0.0); + mFadeDown.resize(mPeerFPP, 0.0); + for (int i = 0; i < mPeerFPP; i++) { + mFadeUp[i] = (double)i / (double)mPeerFPP; mFadeDown[i] = 1.0 - mFadeUp[i]; } - mLastWasGlitch = false; - mNumSlots = NumSlotsMax; - for (int i = 0; i < mNumSlots; i++) { - int8_t* tmp = new int8_t[mBytes]; - mSlots.push_back(tmp); + mSlots = new int8_t*[NumSlots]; + mSlotBuf = new int8_t[NumSlots * mPeerBytes]; + int8_t* tmp = mSlotBuf; + for (int i = 0; i < NumSlots; i++) { + mSlots[i] = tmp; + tmp += mPeerBytes; } + for (int i = 0; i < mNumChannels; i++) { - ChanData* tmp = new ChanData(i, mFPP, mHist); + Channel* tmp = new Channel(mPeerFPP, mUpToNow, mPacketsInThePast); mChanData.push_back(tmp); - for (int s = 0; s < mFPP; s++) - sampleToBits(0.0, i, s); // zero all channels in mXfrBuffer - } - mZeros = new int8_t[mBytes]; - memcpy(mZeros, mXfrBuffer, mBytes); - mAssembledPacket = new int8_t[mBytes]; // for asym - memcpy(mAssembledPacket, mXfrBuffer, mBytes); - mLastLostCount = 0; // for stats + } + mIncomingTimer.start(); mLastSeqNumIn.store(-1, std::memory_order_relaxed); - mLastSeqNumOut = -1; - mPhasor.resize(mNumChannels, 0.0); - mIncomingTiming.resize(NumSlotsMax); - mAssemblyCounts.resize(NumSlotsMax); - for (int i = 0; i < NumSlotsMax; i++) { - mIncomingTiming[i] = 0.0; - mAssemblyCounts[i] = 0; - } - mFPPratioNumerator = 1; - mFPPratioDenominator = 1; - mFPPratioIsSet = false; - mBytesPeerPacket = mBytes; - mPeerFPP = mFPP; // use local until first packet arrives - mAutoHeadroom = 3.0; - mFPPdurMsec = 1000.0 * mFPP / mSampleRate; - changeGlobal_2(NumSlotsMax); // need hg if running GUI if (m_b_BroadcastQueueLength) { m_b_BroadcastRingBuffer = - new JitterBuffer(mFPP, qLen, mSampleRate, 1, m_b_BroadcastQueueLength, + new JitterBuffer(mPeerFPP, 10, mSampleRate, 1, m_b_BroadcastQueueLength, mNumChannels, mAudioBitRes); - qDebug() << "Broadcast started in Regulator with packet queue of" - << m_b_BroadcastQueueLength; + cout << "Broadcast started in Regulator with packet queue of " + << m_b_BroadcastQueueLength << endl; // have not implemented the mJackTrip->queueLengthChanged functionality } -} -void Regulator::enableWorkerThread(QThread* thread_ptr) -{ - if (thread_ptr == nullptr) { - // create owned regulator thread (client mode) - if (mRegulatorThreadPtr == nullptr) { - mRegulatorThreadPtr = new QThread(); - mRegulatorThreadPtr->setObjectName("RegulatorThread"); - mRegulatorThreadPtr->start(); - } - thread_ptr = mRegulatorThreadPtr; - } - if (mRegulatorWorkerPtr != nullptr) { - delete mRegulatorWorkerPtr; - } - mRegulatorWorkerPtr = new RegulatorWorker(this); - mRegulatorWorkerPtr->moveToThread(thread_ptr); - mUseWorkerThread = true; -} + // number of stats tick calls per sec depends on FPP + pushStat = + new StdDev(1, &mIncomingTimer, (int)(floor(mSampleRate / (double)mPeerFPP))); + pullStat = + new StdDev(2, &mIncomingTimer, (int)(floor(mSampleRate / (double)mLocalFPP))); -void Regulator::changeGlobal(double x) -{ - mMsecTolerance = x; - printParams(); + mInitialized = true; } -void Regulator::changeGlobal_2(int x) -{ // mNumSlots - mNumSlots = x; - if (!mNumSlots) - mNumSlots = 1; - if (mNumSlots > NumSlotsMax) - mNumSlots = NumSlotsMax; - printParams(); -} - -void Regulator::printParams(){ - // qDebug() << "mMsecTolerance" << mMsecTolerance << "mNumSlots" << mNumSlots; -}; - -Regulator::~Regulator() +//******************************************************************************* +bool Regulator::enableWorker() { - if (mRegulatorThreadPtr != nullptr) { - // Stop the Regulator thread before deleting other things - mRegulatorThreadPtr->quit(); - mRegulatorThreadPtr->wait(); - delete mRegulatorThreadPtr; + // enable worker thread & queue if a prediction takes longer than + // our local audio callback interval (too slow to keep up) + const double maxPLCdspAllowed = mLocalFPPdurMsec * 0.7; // 70% + if (mStatsMaxPLCdspElapsed >= maxPLCdspAllowed && !isWorkerEnabled()) { + cout << "PLC dsp " << mStatsMaxPLCdspElapsed + << " is too slow (max=" << maxPLCdspAllowed << "), enabling worker" << endl; + mWorkerBuffer = new int8_t[mPeerBytes]; + memset(mWorkerBuffer, 0, mPeerBytes); + mWorkerThreadPtr = new QThread(); + mWorkerThreadPtr->setObjectName("RegulatorThread"); + mWorkerThreadPtr->start(); + mRegulatorWorkerPtr = new RegulatorWorker(this); + mRegulatorWorkerPtr->moveToThread(mWorkerThreadPtr); + mWorkerEnabled = true; } - if (mRegulatorWorkerPtr != nullptr) - delete mRegulatorWorkerPtr; - delete[] mXfrBuffer; - delete[] mZeros; - delete[] mAssembledPacket; - delete pushStat; - delete pullStat; - for (int i = 0; i < mNumChannels; i++) - delete mChanData[i]; - for (auto& slot : mSlots) { - delete[] slot; - }; - if (m_b_BroadcastQueueLength) - delete m_b_BroadcastRingBuffer; + return mWorkerEnabled; } //******************************************************************************* -void Regulator::updateTolerance() +void Regulator::updateTolerance(int glitches, int skipped) { - // pushes happen when we have new packets received from peer - // pulls happen when our audio interface triggers a callback - const double pushStatTol = pushStat->calcAuto(); - const double pullStatTol = pullStat->calcAuto(); + // update headroom if (mAutoHeadroom < 0) { - // auto headroom calculation: use value calculated by pullStats - // because that is where it counts glitches in the incoming peer stream - const int glitchesAllowed = + // variable headroom: automatically increase to minimize glitch counts + // only increase headroom if doing so would have reduced the number of + // glitches that occured over the past two seconds by 2% or more. + // prevent headroom from growing beyond rolling average of max. + const int skipsAllowed = static_cast(AutoHeadroomGlitchTolerance * mSampleRate / mPeerFPP); - const int totalGlitches = pullStat->plcUnderruns + pullStat->plcOverruns; - const int newGlitches = totalGlitches - mLastGlitches; - mLastGlitches = totalGlitches; - // require two consecutive periods of glitches exceeding allowed threshold - if (newGlitches > glitchesAllowed && mCurrentHeadroom < MaxAutoHeadroom) { + if (glitches > 0 && skipped > skipsAllowed + && mCurrentHeadroom + 1 <= pushStat->longTermMax) { if (mSkipAutoHeadroom) { mSkipAutoHeadroom = false; } else { mSkipAutoHeadroom = true; ++mCurrentHeadroom; - qDebug() << "PLC" << newGlitches << "glitches" - << ">" << glitchesAllowed << "allowed: Increasing headroom to " - << mCurrentHeadroom; + cout << "PLC glitches=" << glitches << " skipped=" << skipped << ">" + << skipsAllowed << ", increasing headroom to " << mCurrentHeadroom + << " (max=" << pushStat->longTermMax << ")" << endl; } } else { mSkipAutoHeadroom = true; } } else { + // fixed headroom mCurrentHeadroom = mAutoHeadroom; } - double tmp = std::max(pushStatTol + mCurrentHeadroom, pullStatTol); - if (tmp > AutoMax) - tmp = AutoMax; - if (tmp < mFPPdurMsec) - tmp = mFPPdurMsec; - if (tmp < mPeerFPPdurMsec) - tmp = mPeerFPPdurMsec; - mMsecTolerance = tmp; -} -//******************************************************************************* -void Regulator::setFPPratio() -{ - if (mPeerFPP != mFPP) { - if (mPeerFPP > mFPP) - mFPPratioDenominator = mPeerFPP / mFPP; - else - mFPPratioNumerator = mFPP / mPeerFPP; - // qDebug() << "peerBuffers / localBuffers" << mFPPratioNumerator << " / " - // << mFPPratioDenominator; - } + // pushes happen when we have new packets received from peer + // pulls happen when our audio interface triggers a callback + const double pushStatTol = pushStat->calcAuto(); + const double pullStatTol = pullStat->calcAuto(); + double newTolerance = std::max(pushStatTol + mCurrentHeadroom, pullStatTol); + if (newTolerance > AutoMax) + newTolerance = AutoMax; + if (newTolerance < mLocalFPPdurMsec) + newTolerance = mLocalFPPdurMsec; + if (newTolerance < mPeerFPPdurMsec) + newTolerance = mPeerFPPdurMsec; + mMsecTolerance = newTolerance; } //******************************************************************************* -void Regulator::shimFPP(const int8_t* buf, int len, int seq_num) +void Regulator::updatePushStats(int seq_num) { - if (seq_num != -1) { - if (!mFPPratioIsSet) { // first peer packet - mBytesPeerPacket = len; - mPeerFPP = len / (mNumChannels * mBitResolutionMode); - mPeerFPPdurMsec = 1000.0 * mPeerFPP / mSampleRate; - // bufstrategy 1 autoq mode overloads qLen with negative val - // creates this ugly code - if (mMsecTolerance <= 0) { // handle -q auto or, for example, -q auto10 - mAuto = true; - // default is -500 from bufstrategy 1 autoq mode - // use mMsecTolerance to set headroom - if (mMsecTolerance == -500.0) { - mAutoHeadroom = -1; - qDebug() - << "PLC is in auto mode and has been set with variable headroom"; - } else { - mAutoHeadroom = -mMsecTolerance; - qDebug() << "PLC is in auto mode and has been set with" - << mAutoHeadroom << "ms headroom"; - if (mAutoHeadroom > 50.0) - qDebug() << "That's a very large value and should be less than, " - "for example, 50ms"; - } - // found an interesting relationship between mPeerFPP and initial - // mMsecTolerance mPeerFPP*0.5 is pretty good though that's an oddball - // conversion of bufsize directly to msec - mMsecTolerance = (mPeerFPP * AutoInitValFactor); - }; - setFPPratio(); - // number of stats tick calls per sec depends on FPP - pushStat = new StdDev(1, &mIncomingTimer, - (int)(floor(mSampleRate / (double)mPeerFPP))); - pullStat = - new StdDev(2, &mIncomingTimer, (int)(floor(mSampleRate / (double)mFPP))); - mFPPratioIsSet = true; - } - if (mFPPratioNumerator == mFPPratioDenominator) { - // local FPP matches peer - pushPacket(buf, seq_num); - } else if (mFPPratioNumerator > 1) { - // 2/1, 4/1 peer FPP is lower, (local/peer)/1 - assemblePacket(buf, seq_num); - } else { - // 1/2, 1/4 peer FPP is higher, 1/(peer/local) - seq_num *= mFPPratioDenominator; - for (int i = 0; i < mFPPratioDenominator; i++) { - memcpy(mAssembledPacket, buf, mBytes); - pushPacket(mAssembledPacket, seq_num); - buf += mBytes; - seq_num++; - } - } - bool pushStatsUpdated = pushStat->tick(); - if (mAuto && pushStatsUpdated && (pushStat->lastTime > AutoInitDur) - && pushStat->longTermCnt % WindowDivisor == 0) { + // use time of last packet pulled as a baseline time for previous packet + // this avoids having to search for a previous packet that wasn't missing + // pkts is distance of previous packet from mLastSeqNumOut + int pkts = seq_num - 1 - mLastSeqNumOut; + if (pkts < 0) + pkts += NumSlots; + double prev_time = mIncomingTiming[mLastSeqNumOut] + (pkts * mPeerFPPdurMsec); + if (prev_time >= mIncomingTiming[seq_num]) + return; // skip edge case where mLastSeqNumOut was very late + + // update push stats + bool pushStatsUpdated = pushStat->tick(prev_time, mIncomingTiming[seq_num]); + if (pushStatsUpdated && pushStat->longTermCnt % WindowDivisor == 0) { + // once per second + const int totalGlitches = pullStat->plcUnderruns + pullStat->plcOverruns; + const int totalSkipped = mSkipped; + const int newGlitches = totalGlitches - mLastGlitches; + const int newSkipped = totalSkipped - mLastSkipped; + mLastGlitches = totalGlitches; + mLastSkipped = totalSkipped; + if (mAuto && pushStat->lastTime > AutoInitDur) { // after AutoInitDur: update auto tolerance once per second - updateTolerance(); + updateTolerance(newGlitches, newSkipped); } } -}; +} //******************************************************************************* void Regulator::pushPacket(const int8_t* buf, int seq_num) { - if (m_b_BroadcastQueueLength) - m_b_BroadcastRingBuffer->insertSlotNonBlocking(buf, mBytes, 0, seq_num); - seq_num %= mNumSlots; + if (m_b_BroadcastRingBuffer != NULL) + m_b_BroadcastRingBuffer->insertSlotNonBlocking(buf, mPeerBytes, 0, seq_num); + seq_num %= NumSlots; // if (seq_num==0) return; // impose regular loss - mIncomingTiming[seq_num] = - mMsecTolerance + (double)mIncomingTimer.nsecsElapsed() / 1000000.0; - memcpy(mSlots[seq_num], buf, mBytes); + mIncomingTiming[seq_num] = (double)mIncomingTimer.nsecsElapsed() / 1000000.0; + memcpy(mSlots[seq_num], buf, mPeerBytes); mLastSeqNumIn.store(seq_num, std::memory_order_release); }; //******************************************************************************* -void Regulator::assemblePacket(const int8_t* buf, int peer_seq_num) -{ - // copy packet fragment into slot - int seq_num = (peer_seq_num / mFPPratioNumerator) % mNumSlots; - int pkt_pos = (peer_seq_num % mFPPratioNumerator); - memcpy(&(mSlots[seq_num][pkt_pos * mBytesPeerPacket]), buf, mBytesPeerPacket); - - // check if done assembling yet - if (++mAssemblyCounts[seq_num] < mFPPratioNumerator) - return; - - // complete it - if (m_b_BroadcastQueueLength) - m_b_BroadcastRingBuffer->insertSlotNonBlocking(mSlots[seq_num], mBytes, 0, - seq_num); - mIncomingTiming[seq_num] = - mMsecTolerance + (double)mIncomingTimer.nsecsElapsed() / 1000000.0; - mLastSeqNumIn.store(seq_num, std::memory_order_release); -}; - -//******************************************************************************* -void Regulator::pullPacket() +bool Regulator::pullPacket() { const double now = (double)mIncomingTimer.nsecsElapsed() / 1000000.0; const int lastSeqNumIn = mLastSeqNumIn.load(std::memory_order_acquire); - mSkip = 0; + int skipped = 0; - if ((lastSeqNumIn == -1) || (!mFPPratioIsSet)) { + if ((lastSeqNumIn == -1) || (!mInitialized)) { goto ZERO_OUTPUT; } else if (lastSeqNumIn == mLastSeqNumOut) { goto UNDERRUN; @@ -458,34 +569,35 @@ void Regulator::pullPacket() // find the next packet to pull int new_pkts = lastSeqNumIn - mLastSeqNumOut; if (new_pkts < 0) - new_pkts += mNumSlots; + new_pkts += NumSlots; // iterate through each new packet for (int i = new_pkts - 1; i >= 0; i--) { int next = lastSeqNumIn - i; if (next < 0) - next += mNumSlots; - if (mFPPratioNumerator > 1) { - // time for assembly has passed; reset for next time - mAssemblyCounts[next] = 0; - } + next += NumSlots; if (mLastSeqNumOut != -1) { // account for missing packets - if (mIncomingTiming[next] < mIncomingTiming[mLastSeqNumOut]) + if (mIncomingTiming[next] < mIncomingTiming[mLastSeqNumOut] + && mIncomingTiming[mLastSeqNumOut] - mIncomingTiming[next] + > mMsecTolerance) continue; + updatePushStats(next); // count how many we have skipped - mSkip = next - mLastSeqNumOut - 1; - if (mSkip < 0) - mSkip += mNumSlots; + skipped = next - mLastSeqNumOut - 1; + if (skipped < 0) + skipped += NumSlots; } - // set next as the best candidate - mLastSeqNumOut = next; - // if next timestamp < now, it is too old based upon tolerance - if (mIncomingTiming[mLastSeqNumOut] >= now) { + if (mIncomingTiming[next] + mMsecTolerance >= now) { // next is the best candidate - memcpy(mXfrBuffer, mSlots[mLastSeqNumOut], mBytes); + memcpy(mXfrBuffer, mSlots[next], mPeerBytes); + mLastSeqNumOut = next; goto PACKETOK; } + // track how many good packets we skipped due to tolerance < 1ms + if (mIncomingTiming[next] + mMsecTolerance + 1 >= now) { + ++mSkipped; + } } // no viable candidate @@ -493,9 +605,10 @@ void Regulator::pullPacket() } PACKETOK : { - if (mSkip) { + if (skipped) { processPacket(true); - pullStat->plcOverruns += mSkip; + pullStat->plcOverruns += skipped; + return true; } else processPacket(false); goto OUTPUT; @@ -509,15 +622,14 @@ UNDERRUN : { } // "good underrun", not a stuck client processPacket(true); - goto OUTPUT; + return true; } ZERO_OUTPUT: - memcpy(mXfrBuffer, mZeros, mBytes); + memset(mXfrBuffer, 0, mPeerBytes); OUTPUT: - pullStat->tick(); - return; + return false; }; //******************************************************************************* @@ -526,87 +638,20 @@ void Regulator::processPacket(bool glitch) double tmp = 0.0; if (glitch) tmp = (double)mIncomingTimer.nsecsElapsed(); - for (int ch = 0; ch < mNumChannels; ch++) - processChannel(ch, glitch, mPacketCnt, mLastWasGlitch); - mLastWasGlitch = glitch; - mPacketCnt++; - // 32 bit is good for days: (/ (* (- (expt 2 32) 1) (/ 32 48000.0)) (* 60 60 24)) + + zeroTmpFloatBuf(); // ahead of either call to burg + xfrBufferToFloatBuf(); + burg(glitch); + floatBufToXfrBuffer(); if (glitch) { double tmp2 = (double)mIncomingTimer.nsecsElapsed() - tmp; tmp2 /= 1000000.0; - pullStat->lastPLCdspElapsed = tmp2; + if (tmp2 > mStatsMaxPLCdspElapsed) + mStatsMaxPLCdspElapsed = tmp2; } } -//******************************************************************************* -void Regulator::processChannel(int ch, bool glitch, int packetCnt, bool lastWasGlitch) -{ - // if(glitch) qDebug() << "glitch"; else fprintf(stderr,"."); - ChanData* cd = mChanData[ch]; - for (int s = 0; s < mFPP; s++) - cd->mTruth[s] = bitsToSample(ch, s); - if (packetCnt) { - // always update mTrain - for (int i = 0; i < mHist; i++) { - for (int s = 0; s < mFPP; s++) - cd->mTrain[s + ((mHist - (i + 1)) * mFPP)] = cd->mLastPackets[i][s]; - } - if (glitch) { - // GET LINEAR PREDICTION COEFFICIENTS - ba.train(cd->mCoeffs, cd->mTrain); - - // LINEAR PREDICT DATA - cd->mTail = cd->mTrain; - - ba.predict(cd->mCoeffs, - cd->mTail); // resizes to TRAINSAMPS-2 + TRAINSAMPS - - for (int i = 0; i < (cd->trainSamps - 2); i++) - cd->mPrediction[i] = cd->mTail[i + cd->trainSamps]; - } - // cross fade last prediction with mTruth - if (lastWasGlitch) - for (int s = 0; s < mFPP; s++) - cd->mXfadedPred[s] = - cd->mTruth[s] * mFadeUp[s] + cd->mLastPred[s] * mFadeDown[s]; - for (int s = 0; s < mFPP; s++) - sampleToBits((glitch) - ? cd->mPrediction[s] - : ((lastWasGlitch) ? cd->mXfadedPred[s] : cd->mTruth[s]), - ch, s); - if (glitch) { - for (int s = 0; s < mFPP; s++) - cd->mLastPred[s] = cd->mPrediction[s + mFPP]; - } - } - - // copy down history - - for (int i = mHist - 1; i > 0; i--) { - for (int s = 0; s < mFPP; s++) - cd->mLastPackets[i][s] = cd->mLastPackets[i - 1][s]; - } - - // add prediction or current input to history, the former checking if primed - - for (int s = 0; s < mFPP; s++) - cd->mLastPackets[0][s] = - // ((!glitch) || (packetCnt < mHist)) ? cd->mTruth[s] : - // cd->mPrediction[s]; - ((glitch) ? ((packetCnt >= mHist) ? cd->mPrediction[s] : cd->mTruth[s]) - : ((lastWasGlitch) ? cd->mXfadedPred[s] : cd->mTruth[s])); - - // diagnostic output - ///////////////////// - if (false) - for (int s = 0; s < mFPP; s++) { - sampleToBits(0.7 * sin(mPhasor[ch]), ch, s); - mPhasor[ch] += (!ch) ? 0.1 : 0.11; - } - ///////////////////// -} - //******************************************************************************* // copped from AudioInterface.cpp @@ -629,145 +674,63 @@ void Regulator::sampleToBits(sample_t sample, int ch, int frame) mBitResolutionMode); } -//******************************************************************************* -bool BurgAlgorithm::classify(double d) +/* +void Regulator::sineToXfrBuffer() { - bool tmp = false; - switch (fpclassify(d)) { - case FP_INFINITE: - qDebug() << ("infinite"); - tmp = true; - break; - case FP_NAN: - qDebug() << ("NaN"); - tmp = true; - break; - case FP_ZERO: - qDebug() << ("zero"); - tmp = true; - break; - case FP_SUBNORMAL: - qDebug() << ("subnormal"); - tmp = true; - break; - // case FP_NORMAL: qDebug() << ("normal"); break; - } - // if (signbit(d)) qDebug() << (" negative\n"); else qDebug() << (" positive or - // unsigned\n"); - return tmp; -} + for (int ch = 0; ch < mNumChannels; ch++) + for (int s = 0; s < mPeerFPP; s++) { + sampleToBits(0.7 * sin(mPhasor[ch]), ch, s); + mPhasor[ch] += (!ch) ? 0.1 : 0.11; + } +}; +*/ -void BurgAlgorithm::train(std::vector& coeffs, const std::vector& x) +void Regulator::floatBufToXfrBuffer() { - // GET SIZE FROM INPUT VECTORS - size_t N = x.size() - 1; - size_t m = coeffs.size(); - - // if (x.size() < m) qDebug() << "time_series should have more elements - // than the AR order is"; - - // INITIALIZE Ak - // vector Ak(m + 1, 0.0); - Ak.assign(m + 1, 0.0); - Ak[0] = 1.0; - - // INITIALIZE f and b - // vector f; - f.resize(x.size()); - for (unsigned int i = 0; i < x.size(); i++) - f[i] = x[i]; - // vector b(f); - b = f; - - // INITIALIZE Dk - double Dk = 0.0; - for (size_t j = 0; j <= N; j++) // CC: N is $#x-1 in C++ but $#x in perl - { - Dk += 2.00001 * f[j] * f[j]; // CC: needs more damping than orig 2.0 - } - Dk -= f[0] * f[0] + b[N] * b[N]; - - // qDebug() << "Dk" << qStringFromLongDouble1(Dk); - // if ( classify(Dk) ) - // { qDebug() << pCnt << "init"; - // } - - // BURG RECURSION - for (size_t k = 0; k < m; k++) { - // COMPUTE MU - double mu = 0.0; - for (size_t n = 0; n <= N - k - 1; n++) { - mu += f[n + k + 1] * b[n]; + for (int ch = 0; ch < mNumChannels; ch++) + for (int s = 0; s < mPeerFPP; s++) { + double tmpOut = mChanData[ch]->mTmpFloatBuf[s]; + // if (tmpOut > 1.0) tmpOut = 1.0; + // if (tmpOut < -1.0) tmpOut = -1.0; + sampleToBits(tmpOut, ch, s); } +}; - if (Dk == 0.0) - Dk = 0.0000001; // CC: from testing, needs eps - // if ( classify(Dk) ) qDebug() << pCnt << "run"; - - mu *= -2.0 / Dk; - // if ( isnan(Dk) ) { qDebug() << "k" << k; } - // if (Dk==0.0) qDebug() << "k" << k << "Dk==0"; - - // UPDATE Ak - for (size_t n = 0; n <= (k + 1) / 2; n++) { - double t1 = Ak[n] + mu * Ak[k + 1 - n]; - double t2 = Ak[k + 1 - n] + mu * Ak[n]; - Ak[n] = t1; - Ak[k + 1 - n] = t2; +void Regulator::xfrBufferToFloatBuf() +{ + for (int ch = 0; ch < mNumChannels; ch++) + for (int s = 0; s < mPeerFPP; s++) { + double tmpIn = bitsToSample(ch, s); + mChanData[ch]->mTmpFloatBuf[s] = tmpIn; } +}; - // UPDATE f and b - for (size_t n = 0; n <= N - k - 1; n++) { - double t1 = f[n + k + 1] + mu * b[n]; // were double - double t2 = b[n] + mu * f[n + k + 1]; - f[n + k + 1] = t1; - b[n] = t2; +void Regulator::toFloatBuf(qint16* in) +{ + for (int ch = 0; ch < mNumChannels; ch++) + for (int i = 0; i < mPeerFPP; i++) { + double tmpIn = ((qint16)*in++) * mInvScale; + mChanData[ch]->mTmpFloatBuf[i] = tmpIn; } - - // UPDATE Dk - Dk = (1.0 - mu * mu) * Dk - f[k + 1] * f[k + 1] - b[N - k - 1] * b[N - k - 1]; - } - // ASSIGN COEFFICIENTS - coeffs.assign(++Ak.begin(), Ak.end()); } -void BurgAlgorithm::predict(std::vector& coeffs, std::vector& tail) +void Regulator::fromFloatBuf(qint16* out) { - size_t m = coeffs.size(); - // qDebug() << "tail.at(0)" << tail[0]*32768; - // qDebug() << "tail.at(1)" << tail[1]*32768; - tail.resize(m + tail.size()); - // qDebug() << "tail.at(m)" << tail[m]*32768; - // qDebug() << "tail.at(...end...)" << tail[tail.size()-1]*32768; - // qDebug() << "m" << m << "tail.size()" << tail.size(); - for (size_t i = m; i < tail.size(); i++) { - tail[i] = 0.0; - for (size_t j = 0; j < m; j++) { - tail[i] -= coeffs[j] * tail[i - 1 - j]; + for (int ch = 0; ch < mNumChannels; ch++) + for (int i = 0; i < mPeerFPP; i++) { + double tmpOut = mChanData[ch]->mTmpFloatBuf[i]; + if (tmpOut > 1.0) + tmpOut = 1.0; + if (tmpOut < -1.0) + tmpOut = -1.0; + *out++ = (qint16)(tmpOut * mScale); } - } } -//******************************************************************************* -ChanData::ChanData(int i, int FPP, int hist) : ch(i) +void Regulator::zeroTmpFloatBuf() { - int shrinkCoeffsFactor = 1; - if (FPP == 1024) - shrinkCoeffsFactor = 8; - trainSamps = (hist * FPP); - mTruth.resize(FPP, 0.0); - mXfadedPred.resize(FPP, 0.0); - mLastPred.resize(FPP, 0.0); - for (int i = 0; i < hist; i++) { - std::vector tmp(FPP, 0.0); - mLastPackets.push_back(tmp); - } - mTrain.resize(trainSamps, 0.0); - mPrediction.resize(trainSamps - 1, 0.0); // ORDER - mCoeffs.resize(trainSamps / shrinkCoeffsFactor - 2, 0.0); - mCrossFadeDown.resize(FPP, 0.0); - mCrossFadeUp.resize(FPP, 0.0); - mCrossfade.resize(FPP, 0.0); + for (int ch = 0; ch < mNumChannels; ch++) + mChanData[ch]->mTmpFloatBuf = mChanData[ch]->mZeros; } //******************************************************************************* @@ -784,9 +747,6 @@ StdDev::StdDev(int id, QElapsedTimer* timer, int w) : mId(id), mTimer(timer), wi longTermMax = 0.0; longTermMaxAcc = 0.0; lastTime = 0.0; - lastPLCdspElapsed = 0.0; - lastPlcOverruns = 0; - lastPlcUnderruns = 0; plcOverruns = 0; plcUnderruns = 0; data.resize(w, 0.0); @@ -803,8 +763,6 @@ void StdDev::reset() double StdDev::calcAuto() { - // qDebug() << longTermStdDev << longTermMax << AutoMax << window << - // longTermCnt; if ((longTermStdDev == 0.0) || (longTermMax == 0.0)) return AutoMax; double tmp = longTermStdDev + ((longTermMax > AutoMax) ? AutoMax : longTermMax); @@ -818,35 +776,40 @@ double StdDev::smooth(double avg, double current) return avg + AutoSmoothingFactor * (current - avg); } -bool StdDev::tick() +bool StdDev::tick(double prevTime, double curTime) { - double now = (double)mTimer->nsecsElapsed() / 1000000.0; - double msElapsed = now - lastTime; - lastTime = now; + double msElapsed = curTime - prevTime; + if (msElapsed > 0) { + lastTime = curTime; + } else { + double now = (double)mTimer->nsecsElapsed() / 1000000.0; + msElapsed = now - lastTime; + lastTime = now; + } // discard measurements that exceed the max wait time // this prevents temporary outages from skewing jitter metrics if (msElapsed > gUdpWaitTimeout) return false; - if (ctr != window) { - data[ctr] = msElapsed; - if (msElapsed < min) - min = msElapsed; - else if (msElapsed > max) - max = msElapsed; - acc += msElapsed; - ctr++; - /* - // for debugging startup issues -- you'll see a bunch of pushes - // UDPDataProtocol all at once, which I imagine were queued up - // in the kernel's stack - if (gVerboseFlag && longTermCnt == 0) { - std::cout << setw(10) << msElapsed << " " << mId << endl; - } - */ - return false; + data[ctr] = msElapsed; + if (msElapsed < min) + min = msElapsed; + else if (msElapsed > max) + max = msElapsed; + acc += msElapsed; + if (ctr == 0 && longTermCnt % WindowDivisor == 0) { + lastMin = msElapsed; + lastMax = msElapsed; + } else { + if (msElapsed < lastMin) + lastMin = msElapsed; + if (msElapsed > lastMax) + lastMax = msElapsed; } + if (++ctr < window) + return false; + ctr = 0; // calculate mean and standard deviation mean = (double)acc / (double)window; @@ -859,10 +822,9 @@ bool StdDev::tick() double stdDevTmp = sqrt(var); if (longTermCnt <= 3) { - if (longTermCnt == 0 && gVerboseFlag) { - cout << "printing directly from Regulator->stdDev->tick:\n (mean / min / " - "max / " - "stdDev / longTermMax / longTermStdDev) \n"; + if (longTermCnt == 0 && gVerboseFlag && PrintDirect) { + cout << "printing directly from Regulator->stdDev->tick:" << endl + << " (mean / min / max / stdDev / longTermMax / longTermStdDev)" << endl; } // ignore first few stats because they are unreliable longTermMax = max; @@ -883,7 +845,7 @@ bool StdDev::tick() } } - if (gVerboseFlag) { + if (gVerboseFlag && PrintDirect) { cout << setw(10) << mean << setw(10) << min << setw(10) << max << setw(10) << stdDevTmp << setw(10) << longTermMax << setw(10) << longTermStdDev << " " << mId << endl; @@ -891,35 +853,202 @@ bool StdDev::tick() longTermCnt++; lastMean = mean; - lastMin = min; - lastMax = max; lastStdDev = stdDevTmp; reset(); + return true; } void Regulator::readSlotNonBlocking(int8_t* ptrToReadSlot) { - if (!mFPPratioIsSet) { + if (!mInitialized) { // audio callback before receiving first packet from peer // nothing is initialized yet, so just return silence - memcpy(ptrToReadSlot, mZeros, mBytes); + memset(ptrToReadSlot, 0, mLocalBytes); + return; + } + + pullStat->tick(); + + bool prediction = false; + if (mFPPratioNumerator == mFPPratioDenominator) { + // local FPP matches peer + if (isWorkerEnabled()) { + // we need to use a different buffer here since mXfrBuffer + // is used to pass data between the worker and PLC backend + mRegulatorWorkerPtr->pop(mWorkerBuffer); + memcpy(ptrToReadSlot, mWorkerBuffer, mLocalBytes); + } else { + prediction = pullPacket(); + memcpy(ptrToReadSlot, mXfrBuffer, mLocalBytes); + if (prediction) + enableWorker(); + // nothing special to do if enabled + } return; } - if (mUseWorkerThread) { - // use separate worker thread for PLC - mRegulatorWorkerPtr->pop(ptrToReadSlot); + + if (mFPPratioNumerator > 1) { + // 2/1, 4/1 peer FPP is lower, (local/peer)/1 + if (isWorkerEnabled()) { + for (int i = 0; i < mFPPratioNumerator; i++) { + mRegulatorWorkerPtr->pop(mWorkerBuffer); + memcpy(ptrToReadSlot, mWorkerBuffer, mPeerBytes); + ptrToReadSlot += mPeerBytes; + } + } else { + for (int i = 0; i < mFPPratioNumerator; i++) { + if (pullPacket()) + prediction = true; + memcpy(ptrToReadSlot, mXfrBuffer, mPeerBytes); + ptrToReadSlot += mPeerBytes; + } + if (prediction) + enableWorker(); + // nothing special to do if enabled + } return; } - // use jack callback thread to perform PLC - pullPacket(); - memcpy(ptrToReadSlot, mXfrBuffer, mBytes); + + // 1/2, 1/4 peer FPP is higher, 1/(peer/local) + if (isWorkerEnabled()) { + if (mXfrPullPtr == NULL || mXfrPullPtr >= (mWorkerBuffer + mPeerBytes)) { + mRegulatorWorkerPtr->pop(mWorkerBuffer); + mXfrPullPtr = mWorkerBuffer; + } + } else { + if (mXfrPullPtr == NULL || mXfrPullPtr >= (mXfrBuffer + mPeerBytes)) { + prediction = pullPacket(); + mXfrPullPtr = mXfrBuffer; + if (prediction) { + if (enableWorker()) { + // copy result to worker buffer + memcpy(mWorkerBuffer, mXfrBuffer, mPeerBytes); + mXfrPullPtr = mWorkerBuffer; + } + } + } + } + + memcpy(ptrToReadSlot, mXfrPullPtr, mLocalBytes); + mXfrPullPtr += mLocalBytes; +} + +void Regulator::readBroadcastSlot(int8_t* ptrToReadSlot) +{ + if (!mInitialized || m_b_BroadcastRingBuffer == NULL) { + // audio callback before receiving first packet from peer + // nothing is initialized yet, so just return silence + memset(ptrToReadSlot, 0, mLocalBytes); + return; + } + + if (mFPPratioNumerator == mFPPratioDenominator) { + // local FPP matches peer + m_b_BroadcastRingBuffer->readBroadcastSlot(ptrToReadSlot); + return; + } + + if (mFPPratioNumerator > 1) { + // 2/1, 4/1 peer FPP is lower, (local/peer)/1 + for (int i = 0; i < mFPPratioNumerator; i++) { + m_b_BroadcastRingBuffer->readBroadcastSlot(ptrToReadSlot); + ptrToReadSlot += mPeerBytes; + } + return; + } + + // 1/2, 1/4 peer FPP is higher, 1/(peer/local) + if (mBroadcastPullPtr == NULL + || mBroadcastPullPtr >= (mBroadcastBuffer + mPeerBytes)) { + m_b_BroadcastRingBuffer->readBroadcastSlot(mBroadcastBuffer); + mBroadcastPullPtr = mBroadcastBuffer; + } + memcpy(ptrToReadSlot, mBroadcastPullPtr, mLocalBytes); + mBroadcastPullPtr += mLocalBytes; +} + +//******************************************************************************* +void Regulator::burg(bool glitch) +{ // generate next bufferfull and convert to short int + bool primed = mPcnt > mPacketsInThePast; + for (int ch = 0; ch < mNumChannels; ch++) { + Channel* c = mChanData[ch]; + ////////////////////////////////////// + if (glitch) + mTime->trigger(ch); // if ch == 0, incr glitchCnt + + for (int s = 0; s < mPeerFPP; s++) + c->realNowPacket[s] = (!glitch) ? c->mTmpFloatBuf[s] : 0.0; + + if (!glitch) { + for (int s = 0; s < mPeerFPP; s++) + c->mTmpFloatBuf[s] = c->realNowPacket[s]; + c->ringBufferPush(); + } + + if (primed) { + int offset = 0; + for (int i = 0; i < mPacketsInThePast; i++) { + c->ringBufferPull(mPacketsInThePast - i); + for (int s = 0; s < mPeerFPP; s++) + c->realPast[s + offset] = c->mTmpFloatBuf[s]; + offset += mPeerFPP; + } + } + + if (glitch) { + for (int s = 0; s < mUpToNow; s++) + c->prediction[s] = c->predictedPast[s / mPeerFPP][s % mPeerFPP]; + + ba->train(c->coeffs, c->prediction, mUpToNow); + + ba->predict(c->coeffs, c->prediction, c->mTailSize); + + for (int s = 0; s < mPeerFPP; s++) + c->predictedNowPacket[s] = c->prediction[mUpToNow + s]; + } + + for (int s = 0; s < mPeerFPP; s++) + c->mTmpFloatBuf[s] = c->outputNowPacket[s] = + ((glitch) + ? ((primed) ? c->predictedNowPacket[s] : 0.0) + : ((c->lastWasGlitch) ? (mFadeDown[s] * c->futurePredictedPacket[s] + + mFadeUp[s] * c->realNowPacket[s]) + : c->realNowPacket[s])); + + for (int s = 0; s < mPeerFPP; s++) + c->mTmpFloatBuf[s] = c->outputNowPacket[s]; + + c->lastWasGlitch = glitch; + + for (int i = 0; i < mPacketsInThePast - 1; i++) { + for (int s = 0; s < mPeerFPP; s++) + c->predictedPast[i][s] = c->predictedPast[i + 1][s]; + } + for (int s = 0; s < mPeerFPP; s++) + c->predictedPast[mPacketsInThePast - 1][s] = c->outputNowPacket[s]; + + for (int s = 0; s < mPeerFPP; s++) + c->futurePredictedPacket[s] = c->prediction[mBeyondNow + s - 0]; + + if (glitch) + mTime->collect(); + ////////////////////////////////////// + } + + if ((!(mPcnt % 300)) && (gVerboseFlag)) + cout << "PLC avg " << mTime->avg() << " glitches " << mTime->glitches() + << " skipped " << (mSkipped - mLastSkipped) << " tolerance " + << (mMsecTolerance - mCurrentHeadroom) << " +" << mCurrentHeadroom << endl; + mPcnt++; + // 32 bit is good for days: (/ (* (- (expt 2 32) 1) (/ 32 48000.0)) (* 60 60 24)) } //******************************************************************************* bool Regulator::getStats(RingBuffer::IOStat* stat, bool reset) { - if (!mFPPratioIsSet) { + if (!mInitialized) { return false; } @@ -935,15 +1064,12 @@ bool Regulator::getStats(RingBuffer::IOStat* stat, bool reset) mBroadcastSkew = 0; } - if (mUseWorkerThread && mRegulatorWorkerPtr != nullptr) { + if (isWorkerEnabled() && mRegulatorWorkerPtr != nullptr) { mRegulatorWorkerPtr->getStats(); } // hijack of struct IOStat { - stat->underruns = (pullStat->plcUnderruns - pullStat->lastPlcUnderruns) - + (pullStat->plcOverruns - pullStat->lastPlcOverruns); - pullStat->lastPlcUnderruns = pullStat->plcUnderruns; - pullStat->lastPlcOverruns = pullStat->plcOverruns; + stat->underruns = mLastGlitches - mStatsGlitches; #define FLOATFACTOR 1000.0 stat->overflows = FLOATFACTOR * pushStat->longTermStdDev; stat->skew = FLOATFACTOR * pushStat->lastMean; @@ -957,7 +1083,10 @@ bool Regulator::getStats(RingBuffer::IOStat* stat, bool reset) stat->buf_inc_compensate = FLOATFACTOR * pullStat->lastMin; stat->broadcast_skew = FLOATFACTOR * pullStat->lastMax; stat->broadcast_delta = FLOATFACTOR * pullStat->lastStdDev; - stat->autoq_rate = FLOATFACTOR * pullStat->lastPLCdspElapsed; + stat->autoq_rate = FLOATFACTOR * mStatsMaxPLCdspElapsed; + // reset a few stats for next time + mStatsGlitches = mLastGlitches; + mStatsMaxPLCdspElapsed = 0.0; // none are unused return true; } diff --git a/src/Regulator.h b/src/Regulator.h index 208acba..c65c3d2 100644 --- a/src/Regulator.h +++ b/src/Regulator.h @@ -3,7 +3,7 @@ JackTrip: A System for High-Quality Audio Network Performance over the Internet - Copyright (c) 2021 Juan-Pablo Caceres, Chris Chafe. + Copyright (c) 2024 Juan-Pablo Caceres, Chris Chafe. SoundWIRE group at CCRMA, Stanford University. Permission is hereby granted, free of charge, to any person @@ -32,7 +32,7 @@ /** * \file Regulator.h * \author Chris Chafe - * \date May 2021 + * \date May 2021 - May 2024 */ // Initial references and starter code to bring up Burg's recursion @@ -42,14 +42,14 @@ #ifndef __REGULATOR_H__ #define __REGULATOR_H__ -//#define REGULATOR_SHARED_WORKER_THREAD - #include #include #include +#include #include #include +#include #include "AudioInterface.h" #include "RingBuffer.h" @@ -62,41 +62,96 @@ class RegulatorWorker; class BurgAlgorithm { public: - bool classify(double d); - void train(std::vector& coeffs, const std::vector& x); - void predict(std::vector& coeffs, std::vector& tail); + BurgAlgorithm(int size); + void train(std::vector& coeffs, const std::vector& x, int size); + void predict(std::vector& coeffs, std::vector& predicted, int size); private: - // the following are class members to minimize heap memory allocations - std::vector Ak; - std::vector f; - std::vector b; + int m; + int N; + int size; + std::vector Ak; + std::vector AkReset; + std::vector f; + std::vector b; }; -class ChanData +class Time { + double accum = 0.0; + int cnt = 0; + int glitchCnt = 0; + double tmpTime = 0.0; + public: - ChanData(int i, int FPP, int hist); - int ch; - int trainSamps; - std::vector mTruth; - std::vector mTrain; - std::vector mTail; - std::vector mPrediction; // ORDER - std::vector mCoeffs; - std::vector mXfadedPred; - std::vector mLastPred; - std::vector> mLastPackets; - std::vector mCrossFadeDown; - std::vector mCrossFadeUp; - std::vector mCrossfade; + QElapsedTimer mCallbackTimer; // for rcvElapsedTime + void collect() + { + double tmp = (mCallbackTimer.nsecsElapsed() - tmpTime) / 1000000.0; + accum += tmp; + cnt++; + } + double instantElapsed() + { + return (mCallbackTimer.nsecsElapsed() - tmpTime) / 1000000.0; + } + double instantAbsolute() { return (mCallbackTimer.nsecsElapsed()) / 1000000.0; } + double avg() + { + if (!cnt) + return 0.0; + double tmp = accum / (double)cnt; + accum = 0.0; + cnt = 0; + return tmp; + } + void start() { mCallbackTimer.start(); } + void trigger(int ch) + { + tmpTime = mCallbackTimer.nsecsElapsed(); + if (!ch) + glitchCnt++; + } + int glitches() + { + int tmp = glitchCnt; + glitchCnt = 0; + return tmp; + } +}; + +class Channel +{ + public: + Channel(int fpp, int upToNow, int packetsInThePast); + void ringBufferPush(); + void ringBufferPull(int past); + std::vector + mTmpFloatBuf; // one bufferfull of audio, used for rcv and send operations + std::vector prediction; + std::vector predictedNowPacket; + std::vector realNowPacket; + std::vector outputNowPacket; + std::vector futurePredictedPacket; + std::vector realPast; + std::vector zeroPast; + std::vector> predictedPast; + std::vector coeffs; + std::vector> mPacketRing; + int mWptr; + int mRing; + std::vector mZeros; + bool lastWasGlitch; + int mCoeffsSize; + int mTailSize; }; class StdDev { public: StdDev(int id, QElapsedTimer* timer, int w); - bool tick(); // returns true if stats were updated + bool tick(double prevTime = 0, + double curTime = 0); // returns true if stats were updated double calcAuto(); int mId; int plcOverruns; @@ -105,9 +160,6 @@ class StdDev double lastMean; double lastMin; double lastMax; - int lastPlcOverruns; - int lastPlcUnderruns; - double lastPLCdspElapsed; double lastStdDev; double longTermStdDev; double longTermStdDevAcc; @@ -118,7 +170,7 @@ class StdDev private: double smooth(double avg, double current); void reset(); - QElapsedTimer* mTimer; + QElapsedTimer* mTimer = nullptr; std::vector data; double mean; int window; @@ -132,16 +184,12 @@ class Regulator : public RingBuffer { public: /// construct a new regulator - Regulator(int rcvChannels, int bit_res, int FPP, int qLen, int bqLen, + Regulator(int rcvChannels, int bit_res, int localFPP, int qLen, int bqLen, int sample_rate); // virtual destructor virtual ~Regulator(); - /// @brief enables use of a separate worker thread for pulling packets - /// @param thread_ptr pointer to shared thread; if null, a unique one will be used - void enableWorkerThread(QThread* thread_ptr = nullptr); - // can hijack unused2 to propagate incoming seq num if needed // option is in UdpDataProtocol // if (!mJackTrip->writeAudioBuffer(src, host_buf_size, last_seq_num)) @@ -150,7 +198,10 @@ class Regulator : public RingBuffer virtual bool insertSlotNonBlocking(const int8_t* ptrToSlot, int len, [[maybe_unused]] int lostLen, int seq_num) { - shimFPP(ptrToSlot, len, seq_num); + if (seq_num == -1) + return true; + setFPPratio(len); + pushPacket(ptrToSlot, seq_num); return (true); } @@ -160,98 +211,103 @@ class Regulator : public RingBuffer /// @brief called by broadcast ports to get the next buffer of samples /// @param ptrToReadSlot new samples will be copied to this memory block - virtual void readBroadcastSlot(int8_t* ptrToReadSlot) - { - m_b_BroadcastRingBuffer->readBroadcastSlot(ptrToReadSlot); - } + virtual void readBroadcastSlot(int8_t* ptrToReadSlot); /// @brief returns sample rate inline int getSampleRate() const { return mSampleRate; } /// @brief returns number of bytes in an audio "packet" - inline int getPacketSize() const { return mBytes; } + inline int getPacketSize() const { return mLocalBytes; } /// @brief returns number of samples, or frames per callback period - inline int getBufferSizeInSamples() const { return mFPP; } + inline int getBufferSizeInSamples() const { return mLocalFPP; } - /// @brief returns time taken for last PLC prediction, in milliseconds - inline double getLastDspElapsed() const - { - return pullStat == nullptr ? 0 : pullStat->lastPLCdspElapsed; - } + /// @brief returns true if worker thread & queue is enabled + inline bool isWorkerEnabled() const { return mWorkerEnabled; } // virtual QString getStats(uint32_t statCount, uint32_t lostCount); virtual bool getStats(IOStat* stat, bool reset); private: - void shimFPP(const int8_t* buf, int len, int seq_num); void pushPacket(const int8_t* buf, int seq_num); - void assemblePacket(const int8_t* buf, int peer_seq_num); - void pullPacket(); - void updateTolerance(); - void setFPPratio(); + void updatePushStats(int seq_num); + bool pullPacket(); // returns true if PLC prediction + bool enableWorker(); // returns true if worker was enabled + void updateTolerance(int glitches, int skipped); + void setFPPratio(int len); void processPacket(bool glitch); - void processChannel(int ch, bool glitch, int packetCnt, bool lastWasGlitch); - - bool mFPPratioIsSet; + void burg(bool glitch); + sample_t bitsToSample(int ch, int frame); + void sampleToBits(sample_t sample, int ch, int frame); + void floatBufToXfrBuffer(); + void xfrBufferToFloatBuf(); + void toFloatBuf(qint16* in); + void fromFloatBuf(qint16* out); + void zeroTmpFloatBuf(); + + /* + void sineToXfrBuffer(); // keep this around, handy for signal test points + std::vector mPhasor; + */ + + int mPacketsInThePast; + bool mInitialized; int mNumChannels; int mAudioBitRes; - int mFPP; + int mLocalFPP; int mPeerFPP; int mSampleRate; - uint32_t mLastLostCount; - int mNumSlots; - int mHist; + int mPcnt; + std::vector mTmpFloatBuf; + std::vector mChanData; + BurgAlgorithm* ba = nullptr; + int mUpToNow; + int mBeyondNow; + std::vector mFadeUp; + std::vector mFadeDown; + float mScale; + float mInvScale; + uint32_t mLastLostCount = 0; AudioInterface::audioBitResolutionT mBitResolutionMode; - BurgAlgorithm ba; - int mBytes; - int mBytesPeerPacket; - int8_t* mXfrBuffer; - int8_t* mAssembledPacket; - int mPacketCnt; - sample_t bitsToSample(int ch, int frame); - void sampleToBits(sample_t sample, int ch, int frame); - std::vector mFadeUp; - std::vector mFadeDown; - bool mLastWasGlitch; - std::vector mSlots; - int8_t* mZeros; - double mMsecTolerance; - std::vector mChanData; - StdDev* pushStat; - StdDev* pullStat; - QElapsedTimer mIncomingTimer; + int mLocalBytes; + int mPeerBytes; + double mLocalFPPdurMsec; + double mPeerFPPdurMsec; + int8_t* mXfrBuffer = nullptr; + int8_t* mXfrPullPtr = nullptr; + int8_t* mBroadcastBuffer = nullptr; + int8_t* mBroadcastPullPtr = nullptr; + int8_t** mSlots = nullptr; + int8_t* mSlotBuf = nullptr; + StdDev* pushStat = nullptr; + StdDev* pullStat = nullptr; + double mMsecTolerance = 64; + int mLastSeqNumOut = -1; std::atomic mLastSeqNumIn; - int mLastSeqNumOut; - std::vector mPhasor; + QElapsedTimer mIncomingTimer; std::vector mIncomingTiming; - std::vector mAssemblyCounts; - int mSkip; int mFPPratioNumerator; int mFPPratioDenominator; - bool mAuto; - bool mSkipAutoHeadroom; - int mLastGlitches; - double mCurrentHeadroom; - double mAutoHeadroom; - double mFPPdurMsec; - double mPeerFPPdurMsec; - bool mUseWorkerThread; - void changeGlobal(double); - void changeGlobal_2(int); - void changeGlobal_3(int); - void printParams(); + bool mAuto = false; + bool mSkipAutoHeadroom = true; + int mSkipped = 0; + int mLastSkipped = 0; + int mLastGlitches = 0; + int mStatsGlitches = 0; + double mStatsMaxPLCdspElapsed = 0; + double mCurrentHeadroom = 0; + double mAutoHeadroom = -1; + Time* mTime = nullptr; /// Pointer for the Broadcast RingBuffer - RingBuffer* m_b_BroadcastRingBuffer; + RingBuffer* m_b_BroadcastRingBuffer = nullptr; int m_b_BroadcastQueueLength; - /// thread used to pull packets from Regulator (if mBufferStrategy==3) - QThread* mRegulatorThreadPtr; - - /// worker used to pull packets from Regulator (if mBufferStrategy==3) - RegulatorWorker* mRegulatorWorkerPtr; - + /// worker thread used to manage queue + int8_t* mWorkerBuffer = nullptr; + QThread* mWorkerThreadPtr = nullptr; + RegulatorWorker* mRegulatorWorkerPtr = nullptr; + bool mWorkerEnabled = false; friend class RegulatorWorker; }; @@ -262,7 +318,7 @@ class RegulatorWorker : public QObject public: RegulatorWorker(Regulator* rPtr) : mRegulatorPtr(rPtr) - , mPacketQueue(rPtr->getPacketSize()) + , mPacketQueue(rPtr->mPeerBytes) , mPacketQueueTarget(1) , mLastUnderrun(0) , mSkipQueueUpdate(true) @@ -354,7 +410,7 @@ class RegulatorWorker : public QObject ++mPacketQueueTarget; std::cout << "PLC worker queue: adjusting target=" << mPacketQueueTarget << " (max=" << maxPackets - << ", lastDspElapsed=" << mRegulatorPtr->getLastDspElapsed() << ")" + << ", lastDspElapsed=" << mRegulatorPtr->mStatsMaxPLCdspElapsed << ")" << std::endl; if (mPacketQueueTarget == maxPackets) { emit signalMaxQueueSize(); diff --git a/src/UdpDataProtocol.cpp b/src/UdpDataProtocol.cpp index 65082bc..417ee82 100644 --- a/src/UdpDataProtocol.cpp +++ b/src/UdpDataProtocol.cpp @@ -35,7 +35,7 @@ * \date June 2008 */ -//#define MANUAL_POLL +// #define MANUAL_POLL #include "UdpDataProtocol.h" @@ -49,7 +49,7 @@ #include "JackTrip.h" #include "jacktrip_globals.h" #ifdef _WIN32 -//#include +// #include #include #include //cc need SD_SEND #pragma comment(lib, "ws2_32.lib") @@ -397,7 +397,7 @@ functions. DWORD n_bytes; WSABUF buffer; int error; buffer.len = n; buffer.buf = sizeof(mPeerAddr)); } return n_bytes; - //#endif + // #endif } //******************************************************************************* diff --git a/src/UdpHubListener.cpp b/src/UdpHubListener.cpp index 1848976..ecd588f 100644 --- a/src/UdpHubListener.cpp +++ b/src/UdpHubListener.cpp @@ -80,7 +80,6 @@ UdpHubListener::UdpHubListener(int server_port, int server_udp_port, QObject* pa "client fan out/in, including server", "full mix, including server"}) , m_connectDefaultAudioPorts(false) , mIOStatTimeout(0) - , mRegulatorThreadPtr(NULL) { // Register JackTripWorker with the hub listener // mJTWorker = new JackTripWorker(this); @@ -124,11 +123,6 @@ UdpHubListener::~UdpHubListener() { mStopCheckTimer.stop(); QMutexLocker lock(&mMutex); - if (mRegulatorThreadPtr != NULL) { - mRegulatorThreadPtr->quit(); - mRegulatorThreadPtr->wait(); - delete mRegulatorThreadPtr; - } // delete mJTWorker; for (int i = 0; i < gMaxThreads; i++) { delete mJTWorkers->at(i); @@ -153,7 +147,6 @@ void UdpHubListener::start() QString error_message = QStringLiteral("TCP Socket Server on Port %1 ERROR: %2") .arg(mServerPort) .arg(mTcpServer.errorString()); - std::cerr << error_message.toStdString() << endl; emit signalError(error_message); return; } @@ -221,7 +214,6 @@ void UdpHubListener::start() } if (error) { - std::cerr << "ERROR: " << error_message.toStdString() << endl; emit signalError(error_message); return; } @@ -237,17 +229,6 @@ void UdpHubListener::start() mStopCheckTimer.setInterval(200); connect(&mStopCheckTimer, &QTimer::timeout, this, &UdpHubListener::stopCheck); mStopCheckTimer.start(); - -#ifdef REGULATOR_SHARED_WORKER_THREAD - // Start regulator thread if bufstrategy == 3 - if (mBufferStrategy == 3) { - // create shared regulator thread - mRegulatorThreadPtr = new QThread(); - mRegulatorThreadPtr->setObjectName("RegulatorThread"); - mRegulatorThreadPtr->start(); - } -#endif - emit signalStarted(); } @@ -364,7 +345,6 @@ void UdpHubListener::receivedClientInfo(QSslSocket* clientConnection) mJTWorkers->at(id)->setIOStatStream(mIOStatStream); } mJTWorkers->at(id)->setBufferStrategy(mBufferStrategy); - mJTWorkers->at(id)->setRegulatorThread(mRegulatorThreadPtr); mJTWorkers->at(id)->setNetIssuesSimulation(mSimulatedLossRate, mSimulatedJitterRate, mSimulatedDelayRel); mJTWorkers->at(id)->setBroadcast(mBroadcastQueue); @@ -688,11 +668,6 @@ void UdpHubListener::stopAllThreads() iterator.next(); } } - if (mRegulatorThreadPtr != nullptr) { - // Stop the Regulator thread - mRegulatorThreadPtr->quit(); - mRegulatorThreadPtr->wait(); - } } // TODO: // USE bool QAbstractSocket::isValid () const to check if socket is connect. if not, exit diff --git a/src/UdpHubListener.h b/src/UdpHubListener.h index 81b9838..a810025 100644 --- a/src/UdpHubListener.h +++ b/src/UdpHubListener.h @@ -190,9 +190,6 @@ class UdpHubListener : public QObject int mIOStatTimeout; QSharedPointer mIOStatStream; - /// thread used to pull packets from Regulator (if mBufferStrategy==3) - QThread* mRegulatorThreadPtr; - int mBufferStrategy; int mBroadcastQueue; double mSimulatedLossRate; diff --git a/src/compressordsp.h b/src/compressordsp.h index 2fcd14f..fc71611 100644 --- a/src/compressordsp.h +++ b/src/compressordsp.h @@ -1133,8 +1133,8 @@ class FAUST_API AccUpDownConverter : public UpdatableValueConverter Interpolator fF2A; public: - AccUpDownConverter(double amin, double amid, double amax, double fmin, double /*fmid*/, - double fmax) + AccUpDownConverter(double amin, double amid, double amax, double fmin, + double /*fmid*/, double fmax) : fA2F(amin, amid, amax, fmin, fmax, fmin) , fF2A(fmin, fmax, amin, amax) // Special, pseudo inverse of a non monotonic function @@ -1170,8 +1170,8 @@ class FAUST_API AccDownUpConverter : public UpdatableValueConverter Interpolator fF2A; public: - AccDownUpConverter(double amin, double amid, double amax, double fmin, double /*fmid*/, - double fmax) + AccDownUpConverter(double amin, double amid, double amax, double fmin, + double /*fmid*/, double fmax) : fA2F(amin, amid, amax, fmax, fmin, fmax) , fF2A(fmin, fmax, amin, amax) // Special, pseudo inverse of a non monotonic function @@ -1210,8 +1210,9 @@ class FAUST_API ZoneControl virtual void update(double /*v*/) const {} - virtual void setMappingValues(int /*curve*/, double /*amin*/, double /*amid*/, double /*amax*/, - double /*min*/, double /*init*/, double /*max*/) + virtual void setMappingValues(int /*curve*/, double /*amin*/, double /*amid*/, + double /*amax*/, double /*min*/, double /*init*/, + double /*max*/) { } virtual void getMappingValues(double& /*amin*/, double& /*amid*/, double& /*amax*/) {} @@ -1704,7 +1705,7 @@ class APIUI std::string path = std::string(path_aux); auto it = find_if(fItems.begin(), fItems.end(), [=](const Item& it) { return (it.fLabel == path) || (it.fShortname == path) || (it.fPath == path); - }); + }); return (it != fItems.end()) ? int(it - fItems.begin()) : -1; } diff --git a/src/freeverbdsp.h b/src/freeverbdsp.h index f22c8f0..2b7c661 100644 --- a/src/freeverbdsp.h +++ b/src/freeverbdsp.h @@ -1133,8 +1133,8 @@ class FAUST_API AccUpDownConverter : public UpdatableValueConverter Interpolator fF2A; public: - AccUpDownConverter(double amin, double amid, double amax, double fmin, double /*fmid*/, - double fmax) + AccUpDownConverter(double amin, double amid, double amax, double fmin, + double /*fmid*/, double fmax) : fA2F(amin, amid, amax, fmin, fmax, fmin) , fF2A(fmin, fmax, amin, amax) // Special, pseudo inverse of a non monotonic function @@ -1170,8 +1170,8 @@ class FAUST_API AccDownUpConverter : public UpdatableValueConverter Interpolator fF2A; public: - AccDownUpConverter(double amin, double amid, double amax, double fmin, double /*fmid*/, - double fmax) + AccDownUpConverter(double amin, double amid, double amax, double fmin, + double /*fmid*/, double fmax) : fA2F(amin, amid, amax, fmax, fmin, fmax) , fF2A(fmin, fmax, amin, amax) // Special, pseudo inverse of a non monotonic function @@ -1210,8 +1210,9 @@ class FAUST_API ZoneControl virtual void update(double /*v*/) const {} - virtual void setMappingValues(int /*curve*/, double /*amin*/, double /*amid*/, double /*amax*/, - double /*min*/, double /*init*/, double /*max*/) + virtual void setMappingValues(int /*curve*/, double /*amin*/, double /*amid*/, + double /*amax*/, double /*min*/, double /*init*/, + double /*max*/) { } virtual void getMappingValues(double& /*amin*/, double& /*amid*/, double& /*amax*/) {} @@ -1704,7 +1705,7 @@ class APIUI std::string path = std::string(path_aux); auto it = find_if(fItems.begin(), fItems.end(), [=](const Item& it) { return (it.fLabel == path) || (it.fShortname == path) || (it.fPath == path); - }); + }); return (it != fItems.end()) ? int(it - fItems.begin()) : -1; } diff --git a/src/freeverbmonodsp.h b/src/freeverbmonodsp.h index 8c291a4..e7cea89 100644 --- a/src/freeverbmonodsp.h +++ b/src/freeverbmonodsp.h @@ -1130,8 +1130,8 @@ class FAUST_API AccUpDownConverter : public UpdatableValueConverter Interpolator fF2A; public: - AccUpDownConverter(double amin, double amid, double amax, double fmin, double /*fmid*/, - double fmax) + AccUpDownConverter(double amin, double amid, double amax, double fmin, + double /*fmid*/, double fmax) : fA2F(amin, amid, amax, fmin, fmax, fmin) , fF2A(fmin, fmax, amin, amax) // Special, pseudo inverse of a non monotonic function @@ -1167,8 +1167,8 @@ class FAUST_API AccDownUpConverter : public UpdatableValueConverter Interpolator fF2A; public: - AccDownUpConverter(double amin, double amid, double amax, double fmin, double /*fmid*/, - double fmax) + AccDownUpConverter(double amin, double amid, double amax, double fmin, + double /*fmid*/, double fmax) : fA2F(amin, amid, amax, fmax, fmin, fmax) , fF2A(fmin, fmax, amin, amax) // Special, pseudo inverse of a non monotonic function @@ -1207,8 +1207,9 @@ class FAUST_API ZoneControl virtual void update(double /*v*/) const {} - virtual void setMappingValues(int /*curve*/, double /*amin*/, double /*amid*/, double /*amax*/, - double /*min*/, double /*init*/, double /*max*/) + virtual void setMappingValues(int /*curve*/, double /*amin*/, double /*amid*/, + double /*amax*/, double /*min*/, double /*init*/, + double /*max*/) { } virtual void getMappingValues(double& /*amin*/, double& /*amid*/, double& /*amax*/) {} @@ -1701,7 +1702,7 @@ class APIUI std::string path = std::string(path_aux); auto it = find_if(fItems.begin(), fItems.end(), [=](const Item& it) { return (it.fLabel == path) || (it.fShortname == path) || (it.fPath == path); - }); + }); return (it != fItems.end()) ? int(it - fItems.begin()) : -1; } diff --git a/src/gui/Browse.qml b/src/gui/Browse.qml index d5bb6dd..d632152 100644 --- a/src/gui/Browse.qml +++ b/src/gui/Browse.qml @@ -85,6 +85,7 @@ Item { available: modelData.canConnect connected: false studioId: modelData.id ? modelData.id : "" + streamId: modelData.streamId ? modelData.streamId : "" inviteKeyString: modelData.inviteKey ? modelData.inviteKey : "" sampleRate: modelData.sampleRate } diff --git a/src/gui/DeviceWarning.qml b/src/gui/DeviceWarning.qml index 3b65e38..4b8302a 100644 --- a/src/gui/DeviceWarning.qml +++ b/src/gui/DeviceWarning.qml @@ -43,9 +43,16 @@ Item { anchors.top: devicesWarningIcon.top anchors.bottom: devicesWarningIcon.bottom anchors.left: devicesWarningIcon.left - anchors.right: warningOrErrorText.right + anchors.right: devicesWarningTooltip.right hoverEnabled: true onEntered: devicesWarningTooltip.showToolTip = true onExited: devicesWarningTooltip.showToolTip = false + onClicked: { + if (Boolean(audio.devicesError) && audio.devicesErrorHelpUrl !== "") { + virtualstudio.openLink(audio.devicesErrorHelpUrl); + } else if (Boolean(audio.devicesWarning) && audio.devicesWarningHelpUrl !== "") { + virtualstudio.openLink(audio.devicesWarningHelpUrl); + } + } } } diff --git a/src/gui/LearnMoreButton.qml b/src/gui/LearnMoreButton.qml new file mode 100644 index 0000000..aa26177 --- /dev/null +++ b/src/gui/LearnMoreButton.qml @@ -0,0 +1,30 @@ +import QtQuick +import QtQuick.Controls + +Button { + property string url + property string buttonText: "Learn more" + + width: 150 * virtualstudio.uiScale; + height: 30 * virtualstudio.uiScale + + onClicked: { + virtualstudio.openLink(url); + } + + background: Rectangle { + radius: 6 * virtualstudio.uiScale + color: parent.down ? buttonPressedColour : (parent.hovered ? buttonHoverColour : buttonColour) + border.width: 1 + border.color: parent.down ? buttonPressedStroke : (parent.hovered ? buttonHoverStroke : buttonStroke) + } + + Text { + text: buttonText + font { family: "Poppins"; pixelSize: fontSmall * virtualstudio.fontScale * virtualstudio.uiScale } + color: textColour + horizontalAlignment: Text.AlignHCenter + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + } +} diff --git a/src/gui/Recommendations.qml b/src/gui/Recommendations.qml index b8de3a1..6d4e949 100644 --- a/src/gui/Recommendations.qml +++ b/src/gui/Recommendations.qml @@ -121,7 +121,7 @@ Item { AppIcon { id: ethernetRecommendationLogo - y: 120 + y: 90 anchors.horizontalCenter: parent.horizontalCenter width: 179 height: 128 @@ -145,7 +145,7 @@ Item { + "WiFi works OK for some people, but generates significantly more latency and audio glitches." font { family: "Poppins"; pixelSize: fontSmall * virtualstudio.fontScale * virtualstudio.uiScale } color: textColour - width: 560 + width: 600 wrapMode: Text.Wrap horizontalAlignment: Text.AlignHCenter anchors.horizontalCenter: parent.horizontalCenter @@ -153,6 +153,13 @@ Item { anchors.topMargin: 32 * virtualstudio.uiScale } + LearnMoreButton { + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: ethernetRecommendationSubheader1.bottom + anchors.topMargin: 32 * virtualstudio.uiScale + url: "https://support.jacktrip.com/wired-internet-versus-wi-fi" + } + Button { id: okButtonEthernet background: Rectangle { @@ -187,7 +194,7 @@ Item { AppIcon { id: fiberRecommendationLogo - y: 120 + y: 90 anchors.horizontalCenter: parent.horizontalCenter width: 179 height: 128 @@ -211,7 +218,7 @@ Item { + "It's OK to use JackTrip with Cable and DSL, but these types of Internet connections introduce significantly more latency." font { family: "Poppins"; pixelSize: fontSmall * virtualstudio.fontScale * virtualstudio.uiScale } color: textColour - width: 560 + width: 600 wrapMode: Text.Wrap horizontalAlignment: Text.AlignHCenter anchors.horizontalCenter: parent.horizontalCenter @@ -219,6 +226,12 @@ Item { anchors.topMargin: 32 * virtualstudio.uiScale } + LearnMoreButton { + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: fiberRecommendationSubheader.bottom + anchors.topMargin: 32 * virtualstudio.uiScale + url: "https://support.jacktrip.com/how-to-optimize-latency-when-using-jacktrip" + } Button { id: okButtonFiber @@ -254,7 +267,7 @@ Item { AppIcon { id: headphoneWarningLogo - y: 120 + y: 90 anchors.horizontalCenter: parent.horizontalCenter width: 118 height: 128 @@ -280,7 +293,7 @@ Item { + "Wireless and bluetooth headphones introduce higher latency." font { family: "Poppins"; pixelSize: fontSmall * virtualstudio.fontScale * virtualstudio.uiScale } color: textColour - width: 560 + width: 600 wrapMode: Text.Wrap horizontalAlignment: Text.AlignHCenter anchors.horizontalCenter: parent.horizontalCenter @@ -324,7 +337,7 @@ Item { AppIcon { id: audioInterfaceRecommendationLogo - y: 120 + y: 90 anchors.horizontalCenter: parent.horizontalCenter width: 118 height: 128 @@ -351,7 +364,7 @@ Item { + "Thunderbolt audio interfaces will usually produce better quality and lower latency." font { family: "Poppins"; pixelSize: fontSmall * virtualstudio.fontScale * virtualstudio.uiScale } color: textColour - width: 560 + width: 600 wrapMode: Text.Wrap horizontalAlignment: Text.AlignHCenter anchors.horizontalCenter: parent.horizontalCenter @@ -375,14 +388,13 @@ Item { visible: onWindows text: "Your audio device controls the quality of sound, and can also have a big impact on latency." + "

" - + "Additionally, low latency on Windows requires the use of ASIO drivers. " - + "Beware that using ASIO drivers which are not made specifically for your device can cause crashes." + + "ASIO drivers are required for low latency on Windows. " + "

" + "It's OK to use the audio device that is built into your computer, but external USB and " - + "Thunderbolt audio interfaces that provide ASIO drivers will produce better quality and much lower latency." + + "Thunderbolt devices will produce better quality and much lower latency." font { family: "Poppins"; pixelSize: fontSmall * virtualstudio.fontScale * virtualstudio.uiScale } color: textColour - width: 560 + width: 600 wrapMode: Text.Wrap horizontalAlignment: Text.AlignHCenter anchors.horizontalCenter: parent.horizontalCenter @@ -390,6 +402,15 @@ Item { anchors.topMargin: 32 * virtualstudio.uiScale } + LearnMoreButton { + width: 250 * virtualstudio.uiScale; + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: onWindows ? audioInterfaceRecommendationSubheaderWindows.bottom : audioInterfaceRecommendationSubheaderNonWindows.bottom + anchors.topMargin: 32 * virtualstudio.uiScale + buttonText: "See recommended devices" + url: "https://support.jacktrip.com/recommended-audio-interfaces" + } + Button { id: okButtonAudioInterface background: Rectangle { @@ -439,7 +460,7 @@ Item { text: "Would you like to review the getting started recommendations again the next time you start JackTrip?" font { family: "Poppins"; pixelSize: fontSmall * virtualstudio.fontScale * virtualstudio.uiScale } color: textColour - width: 560 + width: 600 wrapMode: Text.Wrap horizontalAlignment: Text.AlignHCenter anchors.horizontalCenter: parent.horizontalCenter @@ -532,7 +553,7 @@ Item { text: "You can change this setting at any time under Settings > Advanced" font { family: "Poppins"; pixelSize: fontSmall * virtualstudio.fontScale * virtualstudio.uiScale } color: textColour - width: 560 + width: 600 wrapMode: Text.Wrap horizontalAlignment: Text.AlignHCenter anchors.horizontalCenter: parent.horizontalCenter diff --git a/src/gui/Studio.qml b/src/gui/Studio.qml index 582e90a..726ac52 100644 --- a/src/gui/Studio.qml +++ b/src/gui/Studio.qml @@ -13,6 +13,7 @@ Rectangle { property string hostname: "app.jacktrip.com" property string studioName: "Test Studio" property string studioId: "" + property string streamId: "" property string inviteKeyString: "" property int sampleRate: 48000 property bool publicStudio: false @@ -33,8 +34,10 @@ Rectangle { property string backgroundColour: virtualstudio.darkMode ? "#494646" : "#F4F6F6" property string textColour: virtualstudio.darkMode ? "#FAFBFB" : "#0F0D0D" property string shadowColour: virtualstudio.darkMode ? "#40000000" : "#80A1A1A1" - property string toolTipBackgroundColour: inviteCopied ? "#57B147" : (virtualstudio.darkMode ? "#323232" : "#F3F3F3") - property string toolTipTextColour: inviteCopied ? "#FAFBFB" : textColour + property string inviteToolTipBackgroundColour: virtualstudio.darkMode ? "#323232" : "#F3F3F3" + property string inviteToolTipTextColour: textColour + property string inviteCopiedBackgroundColour: "#57B147" + property string inviteCopiedTextColour: "#FAFBFB" property string tooltipStroke: virtualstudio.darkMode ? "#80827D7D" : "#34979797" property string baseButtonColour: virtualstudio.darkMode ? "#F0F1F1" : "#EAEBEB" @@ -259,7 +262,7 @@ Rectangle { } Timer { id: copiedResetTimer - interval: 2000; running: false; repeat: false + interval: 3000; running: false; repeat: false onTriggered: inviteCopied = false; } onClicked: { @@ -286,12 +289,12 @@ Rectangle { } ToolTip { parent: inviteButton - visible: inviteButton.hovered || inviteCopied + visible: !inviteCopied && inviteButton.hovered bottomPadding: bottomToolTipMargin * virtualstudio.uiScale rightPadding: rightToolTipMargin * virtualstudio.uiScale delay: 100 contentItem: Rectangle { - color: toolTipBackgroundColour + color: inviteToolTipBackgroundColour radius: 3 anchors.fill: parent anchors.bottomMargin: bottomToolTipMargin * virtualstudio.uiScale @@ -303,8 +306,35 @@ Rectangle { Text { anchors.centerIn: parent font { family: "Poppins"; pixelSize: fontSmall * virtualstudio.fontScale * virtualstudio.uiScale} - text: inviteCopied ? qsTr("📋 Copied invitation link to Clipboard") : qsTr("Copy invite link for Studio") - color: toolTipTextColour + text: qsTr("Copy invite link for Studio") + color: inviteToolTipTextColour + } + } + background: Rectangle { + color: "transparent" + } + } + ToolTip { + parent: inviteButton + visible: inviteCopied + bottomPadding: bottomToolTipMargin * virtualstudio.uiScale + rightPadding: rightToolTipMargin * virtualstudio.uiScale + delay: 100 + contentItem: Rectangle { + color: inviteCopiedBackgroundColour + radius: 3 + anchors.fill: parent + anchors.bottomMargin: bottomToolTipMargin * virtualstudio.uiScale + anchors.rightMargin: rightToolTipMargin * virtualstudio.uiScale + layer.enabled: true + border.width: 1 + border.color: tooltipStroke + + Text { + anchors.centerIn: parent + font { family: "Poppins"; pixelSize: fontSmall * virtualstudio.fontScale * virtualstudio.uiScale} + text: qsTr("📋 Copied invitation link to Clipboard") + color: inviteCopiedTextColour } } background: Rectangle { @@ -323,28 +353,38 @@ Rectangle { } Button { - id: manageOrVideoButton + id: manageButton x: parent.width - (65 * virtualstudio.uiScale); y: topMargin * virtualstudio.uiScale width: 40 * virtualstudio.uiScale; height: width background: Rectangle { radius: width / 2 - color: manageOrVideoButton.down ? managePressedColour : (manageOrVideoButton.hovered ? manageHoverColour : manageColour) - border.width: manageOrVideoButton.down ? 1 : 0 + color: manageButton.down ? managePressedColour : (manageButton.hovered ? manageHoverColour : manageColour) + border.width: manageButton.down ? 1 : 0 border.color: manageStroke } onClicked: { - if (connected) { - virtualstudio.launchVideo(studioId) + var url = ""; + if (streamId === "") { + if (virtualstudio.testMode) { + url = "https://test.jacktrip.com/studios/" + studioId; + } else { + url = "https://app.jacktrip.com/studios/" + studioId; + } } else { - virtualstudio.manageStudio(studioId); + if (virtualstudio.testMode) { + url = "https://next-test.jacktrip.com/@" + streamId + "/dashboard"; + } else { + url = "https://www.jacktrip.com/@" + streamId + "/dashboard"; + } } + virtualstudio.openLink(qsTr(url)); } visible: admin || connected Image { id: manageImg width: 20 * virtualstudio.uiScale; height: width anchors { verticalCenter: parent.verticalCenter; horizontalCenter: parent.horizontalCenter } - source: connected ? "video.svg" : "manage.svg" + source: "manage.svg" sourceSize: Qt.size(manageImg.width,manageImg.height) fillMode: Image.PreserveAspectFit smooth: true @@ -352,9 +392,9 @@ Rectangle { } Text { - anchors.horizontalCenter: manageOrVideoButton.horizontalCenter + anchors.horizontalCenter: manageButton.horizontalCenter y: 56 * virtualstudio.uiScale - text: connected ? "Video" : "Manage" + text: "Manage" font { family: "Poppins"; pixelSize: fontMedium * virtualstudio.fontScale * virtualstudio.uiScale } visible: admin || connected color: textColour diff --git a/src/gui/qjacktrip.qrc b/src/gui/qjacktrip.qrc index 8ef3a18..7f5e0dc 100644 --- a/src/gui/qjacktrip.qrc +++ b/src/gui/qjacktrip.qrc @@ -8,6 +8,7 @@ vs.qml FirstLaunch.qml Login.qml + LearnMoreButton.qml Recommendations.qml Permissions.qml ChangeDevices.qml diff --git a/src/gui/qjacktrip.ui b/src/gui/qjacktrip.ui index 757afe3..b6d0dd5 100644 --- a/src/gui/qjacktrip.ui +++ b/src/gui/qjacktrip.ui @@ -1398,22 +1398,22 @@ for better quality at the expense of latency. - 1 + 1 (adaptable latency) - 2 + 2 (stable latency) - 3 (experimental - in own thread) + 3 (loss concealment) - 4 (experimental - in callback) + 4 (same as 3) diff --git a/src/gui/virtualstudio.cpp b/src/gui/virtualstudio.cpp index 321fdb9..7223a99 100644 --- a/src/gui/virtualstudio.cpp +++ b/src/gui/virtualstudio.cpp @@ -241,7 +241,7 @@ void VirtualStudio::show() "Click \"OK\" to proceed to classic mode.\n\n" "Details: JackTrip failed to load the QML view. " "This is likely caused by missing QML plugins. " - "Please consult help.jacktrip.org for possible solutions."); + "Please consult support.jacktrip.com for possible solutions."); msgBox.setWindowTitle(QStringLiteral("JackTrip Is Missing QML Modules")); connect(&msgBox, &QMessageBox::finished, this, &VirtualStudio::toStandard, Qt::QueuedConnection); @@ -639,7 +639,6 @@ void VirtualStudio::joinStudio() // pop studioToJoin const QString targetId = m_studioToJoin; setStudioToJoin(""); - emit studioToJoinChanged(); // stop audio if already running (settings or setup windows) m_audioConfigPtr->stopAudio(true); @@ -741,7 +740,7 @@ void VirtualStudio::logout() } logoutURL.setQuery(query); - launchBrowser(logoutURL); + QDesktopServices::openUrl(logoutURL); m_auth->logout(); @@ -896,27 +895,8 @@ void VirtualStudio::completeConnection() // increment buffer_strategy by 1 for array-index mapping int buffer_strategy = m_audioConfigPtr->getBufferStrategy() + 1; // adjust buffer_strategy for PLC "auto" mode menu item - if (buffer_strategy == 3) { - // run PLC without worker (4) - buffer_strategy = 4; - /* - // I don't believe this is still necessary, - // after splitting the input and output RtAudio streams - // See https://github.com/jacktrip/jacktrip/pull/1235 - if (useRtAudio) { - // if same device for input and output, - // run PLC without worker (4) - if (input == output) - buffer_strategy = 4; - // else run PLC with worker (3) - // to reduce crackles - } else { - // run PLC without worker (4) - buffer_strategy = 4; - } - */ - } else if (buffer_strategy == 5) { - buffer_strategy = 3; // run PLC with worker (3) + if (buffer_strategy == 4 || buffer_strategy == 5) { + buffer_strategy = 3; } // create a new JackTrip instance @@ -1048,63 +1028,6 @@ void VirtualStudio::disconnect() #endif } -void VirtualStudio::manageStudio(const QString& studioId, bool start) -{ - if (studioId.isEmpty()) { - processError("Manage requires a unique studio identifier"); - return; - } - QUrl url; - if (!start) { - url = QUrl( - QStringLiteral("https://%1/studios/%2").arg(m_api->getApiHost(), studioId)); - } else { - QString expiration = - QDateTime::currentDateTimeUtc().addSecs(60 * 30).toString(Qt::ISODate); - QJsonObject json = {{QLatin1String("enabled"), true}, - {QLatin1String("expiresAt"), expiration}}; - QJsonDocument request = QJsonDocument(json); - - QNetworkReply* reply = m_api->updateServer(studioId, request.toJson()); - connect(reply, &QNetworkReply::finished, this, [&, reply]() { - if (reply->error() != QNetworkReply::NoError) { - m_connectionState = QStringLiteral("Unable to Start Studio"); - QJsonDocument errorDoc = QJsonDocument::fromJson(reply->readAll()); - if (!errorDoc.isNull()) { - QJsonObject errorObj = errorDoc.object(); - if (errorObj.contains("error")) { - QString errorMessage = errorObj.value("error").toString(); - if (errorMessage.contains( - "Only one studio may be running at a time")) { - setConnectedErrorMsg("one-studio-limit-reached"); - } - } - } - emit connectionStateChanged(); - } else { - setConnectedErrorMsg(""); - QByteArray response = reply->readAll(); - QJsonDocument serverState = QJsonDocument::fromJson(response); - if (serverState.object()[QStringLiteral("status")].toString() - == QLatin1String("Starting")) {} - } - reply->deleteLater(); - }); - } - QDesktopServices::openUrl(url); -} - -void VirtualStudio::launchVideo(const QString& studioId) -{ - if (studioId.isEmpty()) { - processError("Manage requires a unique studio identifier"); - return; - } - QUrl url = QUrl( - QStringLiteral("https://%1/studios/%2/live").arg(m_api->getApiHost(), studioId)); - QDesktopServices::openUrl(url); -} - void VirtualStudio::createStudio() { setWindowState(QStringLiteral("create_studio")); @@ -1391,17 +1314,6 @@ void VirtualStudio::restartStudioSocket() } } -void VirtualStudio::launchBrowser(const QUrl& url) -{ - std::cout << "Launching Browser" << std::endl; - bool success = QDesktopServices::openUrl(url); - if (success) { - std::cout << "Success" << std::endl; - } else { - std::cout << "Unable to open URL" << std::endl; - } -} - void VirtualStudio::updatedStats(const QJsonObject& stats) { QJsonObject newStats; @@ -1523,6 +1435,8 @@ void VirtualStudio::getServerList(bool signalRefresh, int index) serverInfo->setId(servers.at(i)[QStringLiteral("id")].toString()); serverInfo->setSessionId( servers.at(i)[QStringLiteral("sessionId")].toString()); + serverInfo->setStreamId( + servers.at(i)[QStringLiteral("streamId")].toString()); serverInfo->setInviteKey( servers.at(i)[QStringLiteral("inviteKey")].toString()); serverInfo->setCloudId( diff --git a/src/gui/virtualstudio.h b/src/gui/virtualstudio.h index f5d60e1..fbd02c6 100644 --- a/src/gui/virtualstudio.h +++ b/src/gui/virtualstudio.h @@ -193,8 +193,6 @@ class VirtualStudio : public QObject void loadSettings(); void saveSettings(); void triggerReconnect(bool refresh); - void manageStudio(const QString& studioId, bool start = false); - void launchVideo(const QString& studioId); void createStudio(); void editProfile(); void showAbout(); @@ -249,7 +247,6 @@ class VirtualStudio : public QObject void receivedConnectionFromPeer(); void handleWebsocketMessage(const QString& msg); void restartStudioSocket(); - void launchBrowser(const QUrl& url); void updatedStats(const QJsonObject& stats); void processError(const QString& errorMessage); void detectedFeedbackLoop(); diff --git a/src/gui/vsAudio.cpp b/src/gui/vsAudio.cpp index 41970c2..a9fda8f 100644 --- a/src/gui/vsAudio.cpp +++ b/src/gui/vsAudio.cpp @@ -532,7 +532,10 @@ void VsAudio::loadSettings() } setBufferSize(settings.value(QStringLiteral("BufferSize"), 128).toInt()); - setBufferStrategy(settings.value(QStringLiteral("BufferStrategy"), 2).toInt()); + int buffer_strategy = settings.value(QStringLiteral("BufferStrategy"), 2).toInt(); + if (buffer_strategy == 3 || buffer_strategy == 4) + buffer_strategy = 2; + setBufferStrategy(buffer_strategy); setFeedbackDetectionEnabled( settings.value(QStringLiteral("FeedbackDetectionEnabled"), true).toBool()); settings.endGroup(); diff --git a/src/gui/vsAudio.h b/src/gui/vsAudio.h index c91beb5..ab53fb6 100644 --- a/src/gui/vsAudio.h +++ b/src/gui/vsAudio.h @@ -387,8 +387,7 @@ class VsAudio : public QObject QStringList m_feedbackDetectionComboModel = {"Enabled", "Disabled"}; QStringList m_bufferSizeComboModel = {"16", "32", "64", "128", "256", "512", "1024"}; QStringList m_bufferStrategyComboModel = { - "Minimal Latency", "Stable Latency", "Loss Concealment (Auto)", - "Loss Concealment (No Worker)", "Loss Concealment (Use Worker)"}; + "Adaptable Latency (Old)", "Stable Latency (Old)", "Loss Concealment (Default)"}; friend class VsAudioWorker; }; diff --git a/src/gui/vsServerInfo.cpp b/src/gui/vsServerInfo.cpp index 59c60df..9ea5010 100644 --- a/src/gui/vsServerInfo.cpp +++ b/src/gui/vsServerInfo.cpp @@ -57,6 +57,7 @@ VsServerInfo& VsServerInfo::operator=(const VsServerInfo& info) m_bannerURL = info.m_bannerURL; m_id = info.m_id; m_sessionId = info.m_sessionId; + m_streamId = info.m_streamId; m_status = info.m_status; m_cloudId = info.m_cloudId; m_inviteKey = info.m_inviteKey; @@ -275,6 +276,16 @@ void VsServerInfo::setSessionId(const QString& sessionId) m_sessionId = (sessionId == "undefined") ? "" : sessionId; } +QString VsServerInfo::streamId() const +{ + return m_streamId; +} + +void VsServerInfo::setStreamId(const QString& streamId) +{ + m_streamId = (streamId == "undefined") ? "" : streamId; +} + QString VsServerInfo::inviteKey() const { return m_inviteKey; diff --git a/src/gui/vsServerInfo.h b/src/gui/vsServerInfo.h index 14db149..5112c64 100644 --- a/src/gui/vsServerInfo.h +++ b/src/gui/vsServerInfo.h @@ -60,6 +60,7 @@ class VsServerInfo : public QObject Q_PROPERTY(quint32 sampleRate READ sampleRate CONSTANT) Q_PROPERTY(quint16 queueBuffer READ queueBuffer CONSTANT) Q_PROPERTY(QString sessionId READ sessionId CONSTANT) + Q_PROPERTY(QString streamId READ streamId CONSTANT) Q_PROPERTY(QString status READ status CONSTANT) Q_PROPERTY(bool enabled READ enabled CONSTANT) Q_PROPERTY(QString cloudId READ cloudId CONSTANT) @@ -110,6 +111,8 @@ class VsServerInfo : public QObject void setId(const QString& id); QString sessionId() const; void setSessionId(const QString& sessionId); + QString streamId() const; + void setStreamId(const QString& streamId); QString status() const; void setStatus(const QString& status); QString inviteKey() const; @@ -138,6 +141,7 @@ class VsServerInfo : public QObject QString m_bannerURL; QString m_id; QString m_sessionId; + QString m_streamId; QString m_status; QString m_cloudId; QString m_inviteKey; diff --git a/src/jacktrip_globals.h b/src/jacktrip_globals.h index f354fa2..a7bc3e3 100644 --- a/src/jacktrip_globals.h +++ b/src/jacktrip_globals.h @@ -40,7 +40,7 @@ #include "AudioInterface.h" -constexpr const char* const gVersion = "2.2.5"; ///< JackTrip version +constexpr const char* const gVersion = "2.3.0"; ///< JackTrip version //******************************************************************************* /// \name Default Values diff --git a/src/jacktrip_types.h b/src/jacktrip_types.h index 0a8c494..ea90e1f 100644 --- a/src/jacktrip_types.h +++ b/src/jacktrip_types.h @@ -38,7 +38,7 @@ #ifndef __JACKTRIP_TYPES_H__ #define __JACKTRIP_TYPES_H__ -//#include +// #include #include //For QT4 types // namespace JackTripNamespace diff --git a/src/limiterdsp.h b/src/limiterdsp.h index 6e942cd..b6371d1 100644 --- a/src/limiterdsp.h +++ b/src/limiterdsp.h @@ -1702,7 +1702,7 @@ class APIUI std::string path = std::string(path_aux); auto it = find_if(fItems.begin(), fItems.end(), [=](const Item& it) { return (it.fLabel == path) || (it.fShortname == path) || (it.fPath == path); - }); + }); return (it != fItems.end()) ? int(it - fItems.begin()) : -1; } diff --git a/src/main.cpp b/src/main.cpp index 40788a5..58d91dd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -57,7 +57,7 @@ #include #include // TODO: Add support for QtWebView -//#include +// #include #include #include "JTApplication.h" @@ -216,6 +216,11 @@ void qtMessageHandler([[maybe_unused]] QtMsgType type, #endif // NO_GUI } +void outputError(const QString& msg) +{ + std::cerr << "Error: " << msg.toStdString() << std::endl; +} + #ifndef _WIN32 static int setupUnixSignalHandler(void (*handler)(int)) { @@ -462,13 +467,16 @@ int main(int argc, char* argv[]) } else { #endif // NO_GUI // Otherwise use the non-GUI version, and parse our command line. -#ifndef PSI - QLoggingCategory::setFilterRules(QStringLiteral("*.debug=true")); -#endif try { Settings settings; settings.parseInput(argc, argv); +#ifndef PSI + if (gVerboseFlag) { + QLoggingCategory::setFilterRules(QStringLiteral("*.debug=true")); + } +#endif + // Either start our hub server or our jacktrip process as appropriate. if (settings.isHubServer()) { udpHub.reset(settings.getConfiguredHubServer()); @@ -478,6 +486,8 @@ int main(int argc, char* argv[]) QObject::connect(udpHub.data(), &UdpHubListener::signalStopped, app.data(), &QCoreApplication::quit, Qt::QueuedConnection); + QObject::connect(udpHub.data(), &UdpHubListener::signalError, + outputError); QObject::connect(udpHub.data(), &UdpHubListener::signalError, app.data(), &QCoreApplication::quit, Qt::QueuedConnection); #ifndef _WIN32 @@ -495,6 +505,7 @@ int main(int argc, char* argv[]) QObject::connect(jackTrip.data(), &JackTrip::signalProcessesStopped, app.data(), &QCoreApplication::quit, Qt::QueuedConnection); + QObject::connect(jackTrip.data(), &JackTrip::signalError, outputError); QObject::connect(jackTrip.data(), &JackTrip::signalError, app.data(), &QCoreApplication::quit, Qt::QueuedConnection); #ifndef _WIN32 diff --git a/src/meterdsp.h b/src/meterdsp.h index 24dff34..68ab248 100644 --- a/src/meterdsp.h +++ b/src/meterdsp.h @@ -1133,8 +1133,8 @@ class FAUST_API AccUpDownConverter : public UpdatableValueConverter Interpolator fF2A; public: - AccUpDownConverter(double amin, double amid, double amax, double fmin, double /*fmid*/, - double fmax) + AccUpDownConverter(double amin, double amid, double amax, double fmin, + double /*fmid*/, double fmax) : fA2F(amin, amid, amax, fmin, fmax, fmin) , fF2A(fmin, fmax, amin, amax) // Special, pseudo inverse of a non monotonic function @@ -1170,8 +1170,8 @@ class FAUST_API AccDownUpConverter : public UpdatableValueConverter Interpolator fF2A; public: - AccDownUpConverter(double amin, double amid, double amax, double fmin, double /*fmid*/, - double fmax) + AccDownUpConverter(double amin, double amid, double amax, double fmin, + double /*fmid*/, double fmax) : fA2F(amin, amid, amax, fmax, fmin, fmax) , fF2A(fmin, fmax, amin, amax) // Special, pseudo inverse of a non monotonic function @@ -1210,8 +1210,9 @@ class FAUST_API ZoneControl virtual void update(double /*v*/) const {} - virtual void setMappingValues(int /*curve*/, double /*amin*/, double /*amid*/, double /*amax*/, - double /*min*/, double /*init*/, double /*max*/) + virtual void setMappingValues(int /*curve*/, double /*amin*/, double /*amid*/, + double /*amax*/, double /*min*/, double /*init*/, + double /*max*/) { } virtual void getMappingValues(double& /*amin*/, double& /*amid*/, double& /*amax*/) {} @@ -1704,7 +1705,7 @@ class APIUI std::string path = std::string(path_aux); auto it = find_if(fItems.begin(), fItems.end(), [=](const Item& it) { return (it.fLabel == path) || (it.fShortname == path) || (it.fPath == path); - }); + }); return (it != fItems.end()) ? int(it - fItems.begin()) : -1; } @@ -2051,9 +2052,9 @@ class meterdsp : public dsp std::max(9.99999975e-05f, fTemp0))); float fTemp2 = 100.0f * float(copysignf(float(fTemp1), 1.0f)); output0[i0] = FAUSTFLOAT(float(copysignf( - float(0.00999999978f + float(0.00999999978f * float(int(fTemp2) + (fTemp2 - std::floor(fTemp2) >= 0.5f))), - float(fTemp1)))); + float(fTemp1)))); } } }; diff --git a/src/monitordsp.h b/src/monitordsp.h index c99d5db..44bbe6e 100644 --- a/src/monitordsp.h +++ b/src/monitordsp.h @@ -4,11 +4,12 @@ license: "MIT Style STK-4.2" name: "monitor" version: "1.0" Code generated with Faust 2.54.9 (https://faust.grame.fr) -Compilation options: -a faust2header.cpp -lang cpp -i -inpl -cn monitordsp -es 1 -mcd 16 -single -ftz 0 +Compilation options: -a faust2header.cpp -lang cpp -i -inpl -cn monitordsp -es 1 -mcd 16 +-single -ftz 0 ------------------------------------------------------------ */ -#ifndef __monitordsp_H__ -#define __monitordsp_H__ +#ifndef __monitordsp_H__ +#define __monitordsp_H__ // NOTE: ANY INCLUDE-GUARD HERE MUST BE DERIVED FROM THE CLASS NAME // @@ -25,16 +26,16 @@ Compilation options: -a faust2header.cpp -lang cpp -i -inpl -cn monitordsp -es 1 it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + EXCEPTION : As a special exception, you may create a larger work that contains this FAUST architecture section and distribute that work under terms of your choice, so long as this FAUST @@ -55,16 +56,16 @@ Compilation options: -a faust2header.cpp -lang cpp -i -inpl -cn monitordsp -es 1 it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + EXCEPTION : As a special exception, you may create a larger work that contains this FAUST architecture section and distribute that work under terms of your choice, so long as this FAUST @@ -76,29 +77,29 @@ Compilation options: -a faust2header.cpp -lang cpp -i -inpl -cn monitordsp -es 1 #define FAUSTVERSION "2.54.9" -// Use FAUST_API for code that is part of the external API but is also compiled in faust and libfaust -// Use LIBFAUST_API for code that is compiled in faust and libfaust +// Use FAUST_API for code that is part of the external API but is also compiled in faust +// and libfaust Use LIBFAUST_API for code that is compiled in faust and libfaust #ifdef _WIN32 - #pragma warning (disable: 4251) - #ifdef FAUST_EXE - #define FAUST_API - #define LIBFAUST_API - #elif FAUST_LIB - #define FAUST_API __declspec(dllexport) - #define LIBFAUST_API __declspec(dllexport) - #else - #define FAUST_API - #define LIBFAUST_API - #endif +#pragma warning(disable : 4251) +#ifdef FAUST_EXE +#define FAUST_API +#define LIBFAUST_API +#elif FAUST_LIB +#define FAUST_API __declspec(dllexport) +#define LIBFAUST_API __declspec(dllexport) #else - #ifdef FAUST_EXE - #define FAUST_API - #define LIBFAUST_API - #else - #define FAUST_API __attribute__((visibility("default"))) - #define LIBFAUST_API __attribute__((visibility("default"))) - #endif +#define FAUST_API +#define LIBFAUST_API +#endif +#else +#ifdef FAUST_EXE +#define FAUST_API +#define LIBFAUST_API +#else +#define FAUST_API __attribute__((visibility("default"))) +#define LIBFAUST_API __attribute__((visibility("default"))) +#endif #endif #endif @@ -115,15 +116,14 @@ struct FAUST_API Meta; */ struct FAUST_API dsp_memory_manager { - virtual ~dsp_memory_manager() {} - + /** * Inform the Memory Manager with the number of expected memory zones. * @param count - the number of expected memory zones */ virtual void begin(size_t /*count*/) {} - + /** * Give the Memory Manager information on a given memory zone. * @param size - the size in bytes of the memory zone @@ -137,145 +137,161 @@ struct FAUST_API dsp_memory_manager { * to possibly start a 'compute the best allocation strategy' step. */ virtual void end() {} - + /** * Allocate a memory zone. * @param size - the memory zone size in bytes */ virtual void* allocate(size_t size) = 0; - + /** * Destroy a memory zone. * @param ptr - the memory zone pointer to be deallocated */ virtual void destroy(void* ptr) = 0; - -}; - -/** -* Signal processor definition. -*/ - -class FAUST_API dsp { - - public: - - dsp() {} - virtual ~dsp() {} - - /* Return instance number of audio inputs */ - virtual int getNumInputs() = 0; - - /* Return instance number of audio outputs */ - virtual int getNumOutputs() = 0; - - /** - * Trigger the ui_interface parameter with instance specific calls - * to 'openTabBox', 'addButton', 'addVerticalSlider'... in order to build the UI. - * - * @param ui_interface - the user interface builder - */ - virtual void buildUserInterface(UI* ui_interface) = 0; - - /* Return the sample rate currently used by the instance */ - virtual int getSampleRate() = 0; - - /** - * Global init, calls the following methods: - * - static class 'classInit': static tables initialization - * - 'instanceInit': constants and instance state initialization - * - * @param sample_rate - the sampling rate in Hz - */ - virtual void init(int sample_rate) = 0; - - /** - * Init instance state - * - * @param sample_rate - the sampling rate in Hz - */ - virtual void instanceInit(int sample_rate) = 0; - - /** - * Init instance constant state - * - * @param sample_rate - the sampling rate in Hz - */ - virtual void instanceConstants(int sample_rate) = 0; - - /* Init default control parameters values */ - virtual void instanceResetUserInterface() = 0; - - /* Init instance state (like delay lines...) but keep the control parameter values */ - virtual void instanceClear() = 0; - - /** - * Return a clone of the instance. - * - * @return a copy of the instance on success, otherwise a null pointer. - */ - virtual dsp* clone() = 0; - - /** - * Trigger the Meta* parameter with instance specific calls to 'declare' (key, value) metadata. - * - * @param m - the Meta* meta user - */ - virtual void metadata(Meta* m) = 0; - - /** - * DSP instance computation, to be called with successive in/out audio buffers. - * - * @param count - the number of frames to compute - * @param inputs - the input audio buffers as an array of non-interleaved FAUSTFLOAT samples (eiher float, double or quad) - * @param outputs - the output audio buffers as an array of non-interleaved FAUSTFLOAT samples (eiher float, double or quad) - * - */ - virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) = 0; - - /** - * DSP instance computation: alternative method to be used by subclasses. - * - * @param date_usec - the timestamp in microsec given by audio driver. - * @param count - the number of frames to compute - * @param inputs - the input audio buffers as an array of non-interleaved FAUSTFLOAT samples (either float, double or quad) - * @param outputs - the output audio buffers as an array of non-interleaved FAUSTFLOAT samples (either float, double or quad) - * - */ - virtual void compute(double /*date_usec*/, int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { compute(count, inputs, outputs); } - }; /** - * Generic DSP decorator. + * Signal processor definition. */ -class FAUST_API decorator_dsp : public dsp { +class FAUST_API dsp +{ + public: + dsp() {} + virtual ~dsp() {} + + /* Return instance number of audio inputs */ + virtual int getNumInputs() = 0; - protected: + /* Return instance number of audio outputs */ + virtual int getNumOutputs() = 0; - dsp* fDSP; + /** + * Trigger the ui_interface parameter with instance specific calls + * to 'openTabBox', 'addButton', 'addVerticalSlider'... in order to build the UI. + * + * @param ui_interface - the user interface builder + */ + virtual void buildUserInterface(UI* ui_interface) = 0; - public: + /* Return the sample rate currently used by the instance */ + virtual int getSampleRate() = 0; - decorator_dsp(dsp* dsp = nullptr):fDSP(dsp) {} - virtual ~decorator_dsp() { delete fDSP; } + /** + * Global init, calls the following methods: + * - static class 'classInit': static tables initialization + * - 'instanceInit': constants and instance state initialization + * + * @param sample_rate - the sampling rate in Hz + */ + virtual void init(int sample_rate) = 0; + + /** + * Init instance state + * + * @param sample_rate - the sampling rate in Hz + */ + virtual void instanceInit(int sample_rate) = 0; + + /** + * Init instance constant state + * + * @param sample_rate - the sampling rate in Hz + */ + virtual void instanceConstants(int sample_rate) = 0; - virtual int getNumInputs() { return fDSP->getNumInputs(); } - virtual int getNumOutputs() { return fDSP->getNumOutputs(); } - virtual void buildUserInterface(UI* ui_interface) { fDSP->buildUserInterface(ui_interface); } - virtual int getSampleRate() { return fDSP->getSampleRate(); } - virtual void init(int sample_rate) { fDSP->init(sample_rate); } - virtual void instanceInit(int sample_rate) { fDSP->instanceInit(sample_rate); } - virtual void instanceConstants(int sample_rate) { fDSP->instanceConstants(sample_rate); } - virtual void instanceResetUserInterface() { fDSP->instanceResetUserInterface(); } - virtual void instanceClear() { fDSP->instanceClear(); } - virtual decorator_dsp* clone() { return new decorator_dsp(fDSP->clone()); } - virtual void metadata(Meta* m) { fDSP->metadata(m); } - // Beware: subclasses usually have to overload the two 'compute' methods - virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { fDSP->compute(count, inputs, outputs); } - virtual void compute(double date_usec, int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { fDSP->compute(date_usec, count, inputs, outputs); } - + /* Init default control parameters values */ + virtual void instanceResetUserInterface() = 0; + + /* Init instance state (like delay lines...) but keep the control parameter values */ + virtual void instanceClear() = 0; + + /** + * Return a clone of the instance. + * + * @return a copy of the instance on success, otherwise a null pointer. + */ + virtual dsp* clone() = 0; + + /** + * Trigger the Meta* parameter with instance specific calls to 'declare' (key, value) + * metadata. + * + * @param m - the Meta* meta user + */ + virtual void metadata(Meta* m) = 0; + + /** + * DSP instance computation, to be called with successive in/out audio buffers. + * + * @param count - the number of frames to compute + * @param inputs - the input audio buffers as an array of non-interleaved FAUSTFLOAT + * samples (eiher float, double or quad) + * @param outputs - the output audio buffers as an array of non-interleaved FAUSTFLOAT + * samples (eiher float, double or quad) + * + */ + virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) = 0; + + /** + * DSP instance computation: alternative method to be used by subclasses. + * + * @param date_usec - the timestamp in microsec given by audio driver. + * @param count - the number of frames to compute + * @param inputs - the input audio buffers as an array of non-interleaved FAUSTFLOAT + * samples (either float, double or quad) + * @param outputs - the output audio buffers as an array of non-interleaved FAUSTFLOAT + * samples (either float, double or quad) + * + */ + virtual void compute(double /*date_usec*/, int count, FAUSTFLOAT** inputs, + FAUSTFLOAT** outputs) + { + compute(count, inputs, outputs); + } +}; + +/** + * Generic DSP decorator. + */ + +class FAUST_API decorator_dsp : public dsp +{ + protected: + dsp* fDSP; + + public: + decorator_dsp(dsp* dsp = nullptr) : fDSP(dsp) {} + virtual ~decorator_dsp() { delete fDSP; } + + virtual int getNumInputs() { return fDSP->getNumInputs(); } + virtual int getNumOutputs() { return fDSP->getNumOutputs(); } + virtual void buildUserInterface(UI* ui_interface) + { + fDSP->buildUserInterface(ui_interface); + } + virtual int getSampleRate() { return fDSP->getSampleRate(); } + virtual void init(int sample_rate) { fDSP->init(sample_rate); } + virtual void instanceInit(int sample_rate) { fDSP->instanceInit(sample_rate); } + virtual void instanceConstants(int sample_rate) + { + fDSP->instanceConstants(sample_rate); + } + virtual void instanceResetUserInterface() { fDSP->instanceResetUserInterface(); } + virtual void instanceClear() { fDSP->instanceClear(); } + virtual decorator_dsp* clone() { return new decorator_dsp(fDSP->clone()); } + virtual void metadata(Meta* m) { fDSP->metadata(m); } + // Beware: subclasses usually have to overload the two 'compute' methods + virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) + { + fDSP->compute(count, inputs, outputs); + } + virtual void compute(double date_usec, int count, FAUSTFLOAT** inputs, + FAUSTFLOAT** outputs) + { + fDSP->compute(date_usec, count, inputs, outputs); + } }; /** @@ -283,87 +299,78 @@ class FAUST_API decorator_dsp : public dsp { * to create DSP instances from a compiled DSP program. */ -class FAUST_API dsp_factory { - - protected: - - // So that to force sub-classes to use deleteDSPFactory(dsp_factory* factory); - virtual ~dsp_factory() {} - - public: - - virtual std::string getName() = 0; - virtual std::string getSHAKey() = 0; - virtual std::string getDSPCode() = 0; - virtual std::string getCompileOptions() = 0; - virtual std::vector getLibraryList() = 0; - virtual std::vector getIncludePathnames() = 0; - virtual std::vector getWarningMessages() = 0; - - virtual dsp* createDSPInstance() = 0; - - virtual void setMemoryManager(dsp_memory_manager* manager) = 0; - virtual dsp_memory_manager* getMemoryManager() = 0; - +class FAUST_API dsp_factory +{ + protected: + // So that to force sub-classes to use deleteDSPFactory(dsp_factory* factory); + virtual ~dsp_factory() {} + + public: + virtual std::string getName() = 0; + virtual std::string getSHAKey() = 0; + virtual std::string getDSPCode() = 0; + virtual std::string getCompileOptions() = 0; + virtual std::vector getLibraryList() = 0; + virtual std::vector getIncludePathnames() = 0; + virtual std::vector getWarningMessages() = 0; + + virtual dsp* createDSPInstance() = 0; + + virtual void setMemoryManager(dsp_memory_manager* manager) = 0; + virtual dsp_memory_manager* getMemoryManager() = 0; }; // Denormal handling -#if defined (__SSE__) +#if defined(__SSE__) #include #endif -class FAUST_API ScopedNoDenormals { - - private: - - intptr_t fpsr = 0; - - void setFpStatusRegister(intptr_t fpsr_aux) noexcept - { - #if defined (__arm64__) || defined (__aarch64__) - asm volatile("msr fpcr, %0" : : "ri" (fpsr_aux)); - #elif defined (__SSE__) - // The volatile keyword here is needed to workaround a bug in AppleClang 13.0 - // which aggressively optimises away the variable otherwise - volatile uint32_t fpsr_w = static_cast(fpsr_aux); - _mm_setcsr(fpsr_w); - #endif - } - - void getFpStatusRegister() noexcept - { - #if defined (__arm64__) || defined (__aarch64__) - asm volatile("mrs %0, fpcr" : "=r" (fpsr)); - #elif defined (__SSE__) - fpsr = static_cast(_mm_getcsr()); - #endif - } - - public: - - ScopedNoDenormals() noexcept - { - #if defined (__arm64__) || defined (__aarch64__) - intptr_t mask = (1 << 24 /* FZ */); - #elif defined (__SSE__) - #if defined (__SSE2__) - intptr_t mask = 0x8040; - #else - intptr_t mask = 0x8000; - #endif - #else - intptr_t mask = 0x0000; - #endif - getFpStatusRegister(); - setFpStatusRegister(fpsr | mask); - } - - ~ScopedNoDenormals() noexcept - { - setFpStatusRegister(fpsr); - } +class FAUST_API ScopedNoDenormals +{ + private: + intptr_t fpsr = 0; + + void setFpStatusRegister(intptr_t fpsr_aux) noexcept + { +#if defined(__arm64__) || defined(__aarch64__) + asm volatile("msr fpcr, %0" : : "ri"(fpsr_aux)); +#elif defined(__SSE__) + // The volatile keyword here is needed to workaround a bug in AppleClang 13.0 + // which aggressively optimises away the variable otherwise + volatile uint32_t fpsr_w = static_cast(fpsr_aux); + _mm_setcsr(fpsr_w); +#endif + } + + void getFpStatusRegister() noexcept + { +#if defined(__arm64__) || defined(__aarch64__) + asm volatile("mrs %0, fpcr" : "=r"(fpsr)); +#elif defined(__SSE__) + fpsr = static_cast(_mm_getcsr()); +#endif + } + + public: + ScopedNoDenormals() noexcept + { +#if defined(__arm64__) || defined(__aarch64__) + intptr_t mask = (1 << 24 /* FZ */); +#elif defined(__SSE__) +#if defined(__SSE2__) + intptr_t mask = 0x8040; +#else + intptr_t mask = 0x8000; +#endif +#else + intptr_t mask = 0x0000; +#endif + getFpStatusRegister(); + setFpStatusRegister(fpsr | mask); + } + ~ScopedNoDenormals() noexcept { setFpStatusRegister(fpsr); } }; #define AVOIDDENORMALS ScopedNoDenormals ftz_scope; @@ -398,11 +405,12 @@ architecture section is not modified. #ifndef API_UI_H #define API_UI_H +#include + +#include #include #include #include -#include -#include /************************** BEGIN meta.h ******************************* FAUST Architecture File @@ -412,16 +420,16 @@ architecture section is not modified. it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + EXCEPTION : As a special exception, you may create a larger work that contains this FAUST architecture section and distribute that work under terms of your choice, so long as this FAUST @@ -431,9 +439,9 @@ architecture section is not modified. #ifndef __meta__ #define __meta__ - /** - The base class of Meta handler to be used in dsp::metadata(Meta* m) method to retrieve (key, value) metadata. + The base class of Meta handler to be used in dsp::metadata(Meta* m) method to retrieve + (key, value) metadata. */ struct FAUST_API Meta { virtual ~Meta() {} @@ -450,16 +458,16 @@ struct FAUST_API Meta { it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + EXCEPTION : As a special exception, you may create a larger work that contains this FAUST architecture section and distribute that work under terms of your choice, so long as this FAUST @@ -469,7 +477,6 @@ struct FAUST_API Meta { #ifndef __UI_H__ #define __UI_H__ - #ifndef FAUSTFLOAT #define FAUSTFLOAT float #endif @@ -483,38 +490,43 @@ struct FAUST_API Meta { struct Soundfile; -template +template struct FAUST_API UIReal { - UIReal() {} virtual ~UIReal() {} - + // -- widget's layouts - - virtual void openTabBox(const char* label) = 0; + + virtual void openTabBox(const char* label) = 0; virtual void openHorizontalBox(const char* label) = 0; - virtual void openVerticalBox(const char* label) = 0; - virtual void closeBox() = 0; - + virtual void openVerticalBox(const char* label) = 0; + virtual void closeBox() = 0; + // -- active widgets - - virtual void addButton(const char* label, REAL* zone) = 0; + + virtual void addButton(const char* label, REAL* zone) = 0; virtual void addCheckButton(const char* label, REAL* zone) = 0; - virtual void addVerticalSlider(const char* label, REAL* zone, REAL init, REAL min, REAL max, REAL step) = 0; - virtual void addHorizontalSlider(const char* label, REAL* zone, REAL init, REAL min, REAL max, REAL step) = 0; - virtual void addNumEntry(const char* label, REAL* zone, REAL init, REAL min, REAL max, REAL step) = 0; - + virtual void addVerticalSlider(const char* label, REAL* zone, REAL init, REAL min, + REAL max, REAL step) = 0; + virtual void addHorizontalSlider(const char* label, REAL* zone, REAL init, REAL min, + REAL max, REAL step) = 0; + virtual void addNumEntry(const char* label, REAL* zone, REAL init, REAL min, REAL max, + REAL step) = 0; + // -- passive widgets - - virtual void addHorizontalBargraph(const char* label, REAL* zone, REAL min, REAL max) = 0; - virtual void addVerticalBargraph(const char* label, REAL* zone, REAL min, REAL max) = 0; - + + virtual void addHorizontalBargraph(const char* label, REAL* zone, REAL min, + REAL max) = 0; + virtual void addVerticalBargraph(const char* label, REAL* zone, REAL min, + REAL max) = 0; + // -- soundfiles - - virtual void addSoundfile(const char* label, const char* filename, Soundfile** sf_zone) = 0; - + + virtual void addSoundfile(const char* label, const char* filename, + Soundfile** sf_zone) = 0; + // -- metadata declarations - + virtual void declare(REAL* /*zone*/, const char* /*key*/, const char* /*val*/) {} // To be used by LLVM client @@ -536,16 +548,16 @@ struct FAUST_API UI : public UIReal { it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + EXCEPTION : As a special exception, you may create a larger work that contains this FAUST architecture section and distribute that work under terms of your choice, so long as this FAUST @@ -555,187 +567,199 @@ struct FAUST_API UI : public UIReal { #ifndef __PathBuilder__ #define __PathBuilder__ -#include -#include -#include -#include #include +#include #include - +#include +#include +#include /******************************************************************************* * PathBuilder : Faust User Interface * Helper class to build complete hierarchical path for UI items. ******************************************************************************/ -class FAUST_API PathBuilder { - - protected: - - std::vector fControlsLevel; - std::vector fFullPaths; - std::map fFull2Short; // filled by computeShortNames() - - /** - * @brief check if a character is acceptable for an ID - * - * @param c - * @return true is the character is acceptable for an ID - */ - bool isIDChar(char c) const - { - return ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) || ((c >= '0') && (c <= '9')); - } - - /** - * @brief remove all "/0x00" parts - * - * @param src - * @return modified string - */ - std::string remove0x00(const std::string& src) const - { - return std::regex_replace(src, std::regex("/0x00"), ""); - } - - /** - * @brief replace all non ID char with '_' (one '_' may replace several non ID char) - * - * @param src - * @return modified string - */ - std::string str2ID(const std::string& src) const - { - std::string dst; - bool need_underscore = false; - for (char c : src) { - if (isIDChar(c) || (c == '/')) { - if (need_underscore) { - dst.push_back('_'); - need_underscore = false; - } - dst.push_back(c); - } else { - need_underscore = true; +class FAUST_API PathBuilder +{ + protected: + std::vector fControlsLevel; + std::vector fFullPaths; + std::map fFull2Short; // filled by computeShortNames() + + /** + * @brief check if a character is acceptable for an ID + * + * @param c + * @return true is the character is acceptable for an ID + */ + bool isIDChar(char c) const + { + return ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) + || ((c >= '0') && (c <= '9')); + } + + /** + * @brief remove all "/0x00" parts + * + * @param src + * @return modified string + */ + std::string remove0x00(const std::string& src) const + { + return std::regex_replace(src, std::regex("/0x00"), ""); + } + + /** + * @brief replace all non ID char with '_' (one '_' may replace several non ID char) + * + * @param src + * @return modified string + */ + std::string str2ID(const std::string& src) const + { + std::string dst; + bool need_underscore = false; + for (char c : src) { + if (isIDChar(c) || (c == '/')) { + if (need_underscore) { + dst.push_back('_'); + need_underscore = false; } + dst.push_back(c); + } else { + need_underscore = true; } - return dst; } - - /** - * @brief Keep only the last n slash-parts - * - * @param src - * @param n : 1 indicates the last slash-part - * @return modified string - */ - std::string cut(const std::string& src, int n) const - { - std::string rdst; - for (int i = int(src.length())-1; i >= 0; i--) { - char c = src[i]; - if (c != '/') { - rdst.push_back(c); - } else if (n == 1) { - std::string dst; - for (int j = int(rdst.length())-1; j >= 0; j--) { - dst.push_back(rdst[j]); - } - return dst; - } else { - n--; - rdst.push_back(c); + return dst; + } + + /** + * @brief Keep only the last n slash-parts + * + * @param src + * @param n : 1 indicates the last slash-part + * @return modified string + */ + std::string cut(const std::string& src, int n) const + { + std::string rdst; + for (int i = int(src.length()) - 1; i >= 0; i--) { + char c = src[i]; + if (c != '/') { + rdst.push_back(c); + } else if (n == 1) { + std::string dst; + for (int j = int(rdst.length()) - 1; j >= 0; j--) { + dst.push_back(rdst[j]); } + return dst; + } else { + n--; + rdst.push_back(c); } - return src; } - - void addFullPath(const std::string& label) { fFullPaths.push_back(buildPath(label)); } - - /** - * @brief Compute the mapping between full path and short names - */ - void computeShortNames() - { - std::vector uniquePaths; // all full paths transformed but made unique with a prefix - std::map unique2full; // all full paths transformed but made unique with a prefix - char num_buffer[16]; - int pnum = 0; - - for (const auto& s : fFullPaths) { - sprintf(num_buffer, "%d", pnum++); - std::string u = "/P" + std::string(num_buffer) + str2ID(remove0x00(s)); - uniquePaths.push_back(u); - unique2full[u] = s; // remember the full path associated to a unique path - } - - std::map uniquePath2level; // map path to level - for (const auto& s : uniquePaths) uniquePath2level[s] = 1; // we init all levels to 1 - bool have_collisions = true; - - while (have_collisions) { - // compute collision list - std::set collisionSet; - std::map short2full; - have_collisions = false; - for (const auto& it : uniquePath2level) { - std::string u = it.first; - int n = it.second; - std::string shortName = cut(u, n); - auto p = short2full.find(shortName); - if (p == short2full.end()) { - // no collision - short2full[shortName] = u; - } else { - // we have a collision, add the two paths to the collision set - have_collisions = true; - collisionSet.insert(u); - collisionSet.insert(p->second); - } - } - for (const auto& s : collisionSet) uniquePath2level[s]++; // increase level of colliding path - } - + return src; + } + + void addFullPath(const std::string& label) { fFullPaths.push_back(buildPath(label)); } + + /** + * @brief Compute the mapping between full path and short names + */ + void computeShortNames() + { + std::vector + uniquePaths; // all full paths transformed but made unique with a prefix + std::map + unique2full; // all full paths transformed but made unique with a prefix + char num_buffer[16]; + int pnum = 0; + + for (const auto& s : fFullPaths) { + sprintf(num_buffer, "%d", pnum++); + std::string u = "/P" + std::string(num_buffer) + str2ID(remove0x00(s)); + uniquePaths.push_back(u); + unique2full[u] = s; // remember the full path associated to a unique path + } + + std::map uniquePath2level; // map path to level + for (const auto& s : uniquePaths) + uniquePath2level[s] = 1; // we init all levels to 1 + bool have_collisions = true; + + while (have_collisions) { + // compute collision list + std::set collisionSet; + std::map short2full; + have_collisions = false; for (const auto& it : uniquePath2level) { - std::string u = it.first; - int n = it.second; - std::string shortName = replaceCharList(cut(u, n), {'/'}, '_'); - fFull2Short[unique2full[u]] = shortName; + std::string u = it.first; + int n = it.second; + std::string shortName = cut(u, n); + auto p = short2full.find(shortName); + if (p == short2full.end()) { + // no collision + short2full[shortName] = u; + } else { + // we have a collision, add the two paths to the collision set + have_collisions = true; + collisionSet.insert(u); + collisionSet.insert(p->second); + } } + for (const auto& s : collisionSet) + uniquePath2level[s]++; // increase level of colliding path } - - std::string replaceCharList(const std::string& str, const std::vector& ch1, char ch2) - { - auto beg = ch1.begin(); - auto end = ch1.end(); - std::string res = str; - for (size_t i = 0; i < str.length(); ++i) { - if (std::find(beg, end, str[i]) != end) res[i] = ch2; - } - return res; + + for (const auto& it : uniquePath2level) { + std::string u = it.first; + int n = it.second; + std::string shortName = replaceCharList(cut(u, n), {'/'}, '_'); + fFull2Short[unique2full[u]] = shortName; } - - public: - - PathBuilder() {} - virtual ~PathBuilder() {} - - // Return true for the first level of groups - bool pushLabel(const std::string& label) { fControlsLevel.push_back(label); return fControlsLevel.size() == 1;} - - // Return true for the last level of groups - bool popLabel() { fControlsLevel.pop_back(); return fControlsLevel.size() == 0; } - - std::string buildPath(const std::string& label) - { - std::string res = "/"; - for (size_t i = 0; i < fControlsLevel.size(); i++) { - res = res + fControlsLevel[i] + "/"; - } - res += label; - return replaceCharList(res, {' ', '#', '*', ',', '?', '[', ']', '{', '}', '(', ')'}, '_'); + } + + std::string replaceCharList(const std::string& str, const std::vector& ch1, + char ch2) + { + auto beg = ch1.begin(); + auto end = ch1.end(); + std::string res = str; + for (size_t i = 0; i < str.length(); ++i) { + if (std::find(beg, end, str[i]) != end) + res[i] = ch2; + } + return res; + } + + public: + PathBuilder() {} + virtual ~PathBuilder() {} + + // Return true for the first level of groups + bool pushLabel(const std::string& label) + { + fControlsLevel.push_back(label); + return fControlsLevel.size() == 1; + } + + // Return true for the last level of groups + bool popLabel() + { + fControlsLevel.pop_back(); + return fControlsLevel.size() == 0; + } + + std::string buildPath(const std::string& label) + { + std::string res = "/"; + for (size_t i = 0; i < fControlsLevel.size(); i++) { + res = res + fControlsLevel[i] + "/"; } - + res += label; + return replaceCharList( + res, {' ', '#', '*', ',', '?', '[', ']', '{', '}', '(', ')'}, '_'); + } }; #endif // __PathBuilder__ @@ -748,16 +772,16 @@ class FAUST_API PathBuilder { it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + EXCEPTION : As a special exception, you may create a larger work that contains this FAUST architecture section and distribute that work under terms of your choice, so long as this FAUST @@ -770,52 +794,53 @@ class FAUST_API PathBuilder { /*************************************************************************************** ValueConverter.h (GRAME, Copyright 2015-2019) - + Set of conversion objects used to map user interface values (for example a gui slider delivering values between 0 and 1) to faust values (for example a vslider between 20 and 20000) using a log scale. - + -- Utilities - + Range(lo,hi) : clip a value x between lo and hi - Interpolator(lo,hi,v1,v2) : Maps a value x between lo and hi to a value y between v1 and v2 - Interpolator3pt(lo,mi,hi,v1,vm,v2) : Map values between lo mid hi to values between v1 vm v2 - + Interpolator(lo,hi,v1,v2) : Maps a value x between lo and hi to a value y between v1 and +v2 Interpolator3pt(lo,mi,hi,v1,vm,v2) : Map values between lo mid hi to values between v1 +vm v2 + -- Value Converters - + ValueConverter::ui2faust(x) ValueConverter::faust2ui(x) - + -- ValueConverters used for sliders depending of the scale - + LinearValueConverter(umin, umax, fmin, fmax) LinearValueConverter2(lo, mi, hi, v1, vm, v2) using 2 segments LogValueConverter(umin, umax, fmin, fmax) ExpValueConverter(umin, umax, fmin, fmax) - + -- ValueConverters used for accelerometers based on 3 points - + AccUpConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 0 AccDownConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 1 AccUpDownConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 2 AccDownUpConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 3 - + -- lists of ZoneControl are used to implement accelerometers metadata for each axes - + ZoneControl(zone, valueConverter) : a zone with an accelerometer data converter - + -- ZoneReader are used to implement screencolor metadata - + ZoneReader(zone, valueConverter) : a zone with a data converter ****************************************************************************************/ +#include #include -#include // std::max + +#include // std::max #include #include -#include - //-------------------------------------------------------------------------------------- // Interpolator(lo,hi,v1,v2) @@ -826,458 +851,485 @@ class FAUST_API PathBuilder { // y = v1 - lo*coef + x*coef // y = offset + x*coef with offset = v1 - lo*coef //-------------------------------------------------------------------------------------- -class FAUST_API Interpolator { - - private: - - //-------------------------------------------------------------------------------------- - // Range(lo,hi) clip a value between lo and hi - //-------------------------------------------------------------------------------------- - struct Range - { - double fLo; - double fHi; - - Range(double x, double y) : fLo(std::min(x,y)), fHi(std::max(x,y)) {} - double operator()(double x) { return (xfHi) ? fHi : x; } - }; - - - Range fRange; - double fCoef; - double fOffset; - - public: - - Interpolator(double lo, double hi, double v1, double v2) : fRange(lo,hi) - { - if (hi != lo) { - // regular case - fCoef = (v2-v1)/(hi-lo); - fOffset = v1 - lo*fCoef; - } else { - // degenerate case, avoids division by zero - fCoef = 0; - fOffset = (v1+v2)/2; - } - } - double operator()(double v) +class FAUST_API Interpolator +{ + private: + //-------------------------------------------------------------------------------------- + // Range(lo,hi) clip a value between lo and hi + //-------------------------------------------------------------------------------------- + struct Range { + double fLo; + double fHi; + + Range(double x, double y) + : fLo(std::min(x, y)), fHi(std::max(x, y)) { - double x = fRange(v); - return fOffset + x*fCoef; } - - void getLowHigh(double& amin, double& amax) - { - amin = fRange.fLo; - amax = fRange.fHi; + double operator()(double x) { return (x < fLo) ? fLo : (x > fHi) ? fHi : x; } + }; + + Range fRange; + double fCoef; + double fOffset; + + public: + Interpolator(double lo, double hi, double v1, double v2) : fRange(lo, hi) + { + if (hi != lo) { + // regular case + fCoef = (v2 - v1) / (hi - lo); + fOffset = v1 - lo * fCoef; + } else { + // degenerate case, avoids division by zero + fCoef = 0; + fOffset = (v1 + v2) / 2; } + } + double operator()(double v) + { + double x = fRange(v); + return fOffset + x * fCoef; + } + + void getLowHigh(double& amin, double& amax) + { + amin = fRange.fLo; + amax = fRange.fHi; + } }; //-------------------------------------------------------------------------------------- // Interpolator3pt(lo,mi,hi,v1,vm,v2) // Map values between lo mid hi to values between v1 vm v2 //-------------------------------------------------------------------------------------- -class FAUST_API Interpolator3pt { - - private: - - Interpolator fSegment1; - Interpolator fSegment2; - double fMid; - - public: - - Interpolator3pt(double lo, double mi, double hi, double v1, double vm, double v2) : - fSegment1(lo, mi, v1, vm), - fSegment2(mi, hi, vm, v2), - fMid(mi) {} - double operator()(double x) { return (x < fMid) ? fSegment1(x) : fSegment2(x); } - - void getMappingValues(double& amin, double& amid, double& amax) - { - fSegment1.getLowHigh(amin, amid); - fSegment2.getLowHigh(amid, amax); - } +class FAUST_API Interpolator3pt +{ + private: + Interpolator fSegment1; + Interpolator fSegment2; + double fMid; + + public: + Interpolator3pt(double lo, double mi, double hi, double v1, double vm, double v2) + : fSegment1(lo, mi, v1, vm), fSegment2(mi, hi, vm, v2), fMid(mi) + { + } + double operator()(double x) { return (x < fMid) ? fSegment1(x) : fSegment2(x); } + + void getMappingValues(double& amin, double& amid, double& amax) + { + fSegment1.getLowHigh(amin, amid); + fSegment2.getLowHigh(amid, amax); + } }; //-------------------------------------------------------------------------------------- // Abstract ValueConverter class. Converts values between UI and Faust representations //-------------------------------------------------------------------------------------- -class FAUST_API ValueConverter { - - public: - - virtual ~ValueConverter() {} - virtual double ui2faust(double x) { return x; }; - virtual double faust2ui(double x) { return x; }; +class FAUST_API ValueConverter +{ + public: + virtual ~ValueConverter() {} + virtual double ui2faust(double x) { return x; }; + virtual double faust2ui(double x) { return x; }; }; //-------------------------------------------------------------------------------------- // A converter than can be updated //-------------------------------------------------------------------------------------- -class FAUST_API UpdatableValueConverter : public ValueConverter { - - protected: - - bool fActive; - - public: - - UpdatableValueConverter():fActive(true) - {} - virtual ~UpdatableValueConverter() - {} - - virtual void setMappingValues(double amin, double amid, double amax, double min, double init, double max) = 0; - virtual void getMappingValues(double& amin, double& amid, double& amax) = 0; - - void setActive(bool on_off) { fActive = on_off; } - bool getActive() { return fActive; } - +class FAUST_API UpdatableValueConverter : public ValueConverter +{ + protected: + bool fActive; + + public: + UpdatableValueConverter() : fActive(true) {} + virtual ~UpdatableValueConverter() {} + + virtual void setMappingValues(double amin, double amid, double amax, double min, + double init, double max) = 0; + virtual void getMappingValues(double& amin, double& amid, double& amax) = 0; + + void setActive(bool on_off) { fActive = on_off; } + bool getActive() { return fActive; } }; //-------------------------------------------------------------------------------------- // Linear conversion between ui and Faust values //-------------------------------------------------------------------------------------- -class FAUST_API LinearValueConverter : public ValueConverter { - - private: - - Interpolator fUI2F; - Interpolator fF2UI; - - public: - - LinearValueConverter(double umin, double umax, double fmin, double fmax) : - fUI2F(umin,umax,fmin,fmax), fF2UI(fmin,fmax,umin,umax) - {} - - LinearValueConverter() : fUI2F(0.,0.,0.,0.), fF2UI(0.,0.,0.,0.) - {} - virtual double ui2faust(double x) { return fUI2F(x); } - virtual double faust2ui(double x) { return fF2UI(x); } - +class FAUST_API LinearValueConverter : public ValueConverter +{ + private: + Interpolator fUI2F; + Interpolator fF2UI; + + public: + LinearValueConverter(double umin, double umax, double fmin, double fmax) + : fUI2F(umin, umax, fmin, fmax), fF2UI(fmin, fmax, umin, umax) + { + } + + LinearValueConverter() : fUI2F(0., 0., 0., 0.), fF2UI(0., 0., 0., 0.) {} + virtual double ui2faust(double x) { return fUI2F(x); } + virtual double faust2ui(double x) { return fF2UI(x); } }; //-------------------------------------------------------------------------------------- // Two segments linear conversion between ui and Faust values //-------------------------------------------------------------------------------------- -class FAUST_API LinearValueConverter2 : public UpdatableValueConverter { - - private: - - Interpolator3pt fUI2F; - Interpolator3pt fF2UI; - - public: - - LinearValueConverter2(double amin, double amid, double amax, double min, double init, double max) : - fUI2F(amin, amid, amax, min, init, max), fF2UI(min, init, max, amin, amid, amax) - {} - - LinearValueConverter2() : fUI2F(0.,0.,0.,0.,0.,0.), fF2UI(0.,0.,0.,0.,0.,0.) - {} - - virtual double ui2faust(double x) { return fUI2F(x); } - virtual double faust2ui(double x) { return fF2UI(x); } - - virtual void setMappingValues(double amin, double amid, double amax, double min, double init, double max) - { - fUI2F = Interpolator3pt(amin, amid, amax, min, init, max); - fF2UI = Interpolator3pt(min, init, max, amin, amid, amax); - } - - virtual void getMappingValues(double& amin, double& amid, double& amax) - { - fUI2F.getMappingValues(amin, amid, amax); - } - +class FAUST_API LinearValueConverter2 : public UpdatableValueConverter +{ + private: + Interpolator3pt fUI2F; + Interpolator3pt fF2UI; + + public: + LinearValueConverter2(double amin, double amid, double amax, double min, double init, + double max) + : fUI2F(amin, amid, amax, min, init, max), fF2UI(min, init, max, amin, amid, amax) + { + } + + LinearValueConverter2() : fUI2F(0., 0., 0., 0., 0., 0.), fF2UI(0., 0., 0., 0., 0., 0.) + { + } + + virtual double ui2faust(double x) { return fUI2F(x); } + virtual double faust2ui(double x) { return fF2UI(x); } + + virtual void setMappingValues(double amin, double amid, double amax, double min, + double init, double max) + { + fUI2F = Interpolator3pt(amin, amid, amax, min, init, max); + fF2UI = Interpolator3pt(min, init, max, amin, amid, amax); + } + + virtual void getMappingValues(double& amin, double& amid, double& amax) + { + fUI2F.getMappingValues(amin, amid, amax); + } }; //-------------------------------------------------------------------------------------- // Logarithmic conversion between ui and Faust values //-------------------------------------------------------------------------------------- -class FAUST_API LogValueConverter : public LinearValueConverter { - - public: - - LogValueConverter(double umin, double umax, double fmin, double fmax) : - LinearValueConverter(umin, umax, std::log(std::max(DBL_MIN, fmin)), std::log(std::max(DBL_MIN, fmax))) - {} - - virtual double ui2faust(double x) { return std::exp(LinearValueConverter::ui2faust(x)); } - virtual double faust2ui(double x) { return LinearValueConverter::faust2ui(std::log(std::max(x, DBL_MIN))); } - +class FAUST_API LogValueConverter : public LinearValueConverter +{ + public: + LogValueConverter(double umin, double umax, double fmin, double fmax) + : LinearValueConverter(umin, umax, std::log(std::max(DBL_MIN, fmin)), + std::log(std::max(DBL_MIN, fmax))) + { + } + + virtual double ui2faust(double x) + { + return std::exp(LinearValueConverter::ui2faust(x)); + } + virtual double faust2ui(double x) + { + return LinearValueConverter::faust2ui(std::log(std::max(x, DBL_MIN))); + } }; //-------------------------------------------------------------------------------------- // Exponential conversion between ui and Faust values //-------------------------------------------------------------------------------------- -class FAUST_API ExpValueConverter : public LinearValueConverter { - - public: - - ExpValueConverter(double umin, double umax, double fmin, double fmax) : - LinearValueConverter(umin, umax, std::min(DBL_MAX, std::exp(fmin)), std::min(DBL_MAX, std::exp(fmax))) - {} - - virtual double ui2faust(double x) { return std::log(LinearValueConverter::ui2faust(x)); } - virtual double faust2ui(double x) { return LinearValueConverter::faust2ui(std::min(DBL_MAX, std::exp(x))); } - +class FAUST_API ExpValueConverter : public LinearValueConverter +{ + public: + ExpValueConverter(double umin, double umax, double fmin, double fmax) + : LinearValueConverter(umin, umax, std::min(DBL_MAX, std::exp(fmin)), + std::min(DBL_MAX, std::exp(fmax))) + { + } + + virtual double ui2faust(double x) + { + return std::log(LinearValueConverter::ui2faust(x)); + } + virtual double faust2ui(double x) + { + return LinearValueConverter::faust2ui(std::min(DBL_MAX, std::exp(x))); + } }; //-------------------------------------------------------------------------------------- // Convert accelerometer or gyroscope values to Faust values // Using an Up curve (curve 0) //-------------------------------------------------------------------------------------- -class FAUST_API AccUpConverter : public UpdatableValueConverter { - - private: - - Interpolator3pt fA2F; - Interpolator3pt fF2A; - - public: - - AccUpConverter(double amin, double amid, double amax, double fmin, double fmid, double fmax) : - fA2F(amin,amid,amax,fmin,fmid,fmax), - fF2A(fmin,fmid,fmax,amin,amid,amax) - {} - - virtual double ui2faust(double x) { return fA2F(x); } - virtual double faust2ui(double x) { return fF2A(x); } - - virtual void setMappingValues(double amin, double amid, double amax, double fmin, double fmid, double fmax) - { - //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccUpConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax); - fA2F = Interpolator3pt(amin, amid, amax, fmin, fmid, fmax); - fF2A = Interpolator3pt(fmin, fmid, fmax, amin, amid, amax); - } - - virtual void getMappingValues(double& amin, double& amid, double& amax) - { - fA2F.getMappingValues(amin, amid, amax); - } - +class FAUST_API AccUpConverter : public UpdatableValueConverter +{ + private: + Interpolator3pt fA2F; + Interpolator3pt fF2A; + + public: + AccUpConverter(double amin, double amid, double amax, double fmin, double fmid, + double fmax) + : fA2F(amin, amid, amax, fmin, fmid, fmax) + , fF2A(fmin, fmid, fmax, amin, amid, amax) + { + } + + virtual double ui2faust(double x) { return fA2F(x); } + virtual double faust2ui(double x) { return fF2A(x); } + + virtual void setMappingValues(double amin, double amid, double amax, double fmin, + double fmid, double fmax) + { + //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccUpConverter update %f %f %f + //%f %f %f", amin,amid,amax,fmin,fmid,fmax); + fA2F = Interpolator3pt(amin, amid, amax, fmin, fmid, fmax); + fF2A = Interpolator3pt(fmin, fmid, fmax, amin, amid, amax); + } + + virtual void getMappingValues(double& amin, double& amid, double& amax) + { + fA2F.getMappingValues(amin, amid, amax); + } }; //-------------------------------------------------------------------------------------- // Convert accelerometer or gyroscope values to Faust values // Using a Down curve (curve 1) //-------------------------------------------------------------------------------------- -class FAUST_API AccDownConverter : public UpdatableValueConverter { - - private: - - Interpolator3pt fA2F; - Interpolator3pt fF2A; - - public: - - AccDownConverter(double amin, double amid, double amax, double fmin, double fmid, double fmax) : - fA2F(amin,amid,amax,fmax,fmid,fmin), - fF2A(fmin,fmid,fmax,amax,amid,amin) - {} - - virtual double ui2faust(double x) { return fA2F(x); } - virtual double faust2ui(double x) { return fF2A(x); } - - virtual void setMappingValues(double amin, double amid, double amax, double fmin, double fmid, double fmax) - { - //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccDownConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax); - fA2F = Interpolator3pt(amin, amid, amax, fmax, fmid, fmin); - fF2A = Interpolator3pt(fmin, fmid, fmax, amax, amid, amin); - } - - virtual void getMappingValues(double& amin, double& amid, double& amax) - { - fA2F.getMappingValues(amin, amid, amax); - } +class FAUST_API AccDownConverter : public UpdatableValueConverter +{ + private: + Interpolator3pt fA2F; + Interpolator3pt fF2A; + + public: + AccDownConverter(double amin, double amid, double amax, double fmin, double fmid, + double fmax) + : fA2F(amin, amid, amax, fmax, fmid, fmin) + , fF2A(fmin, fmid, fmax, amax, amid, amin) + { + } + + virtual double ui2faust(double x) { return fA2F(x); } + virtual double faust2ui(double x) { return fF2A(x); } + + virtual void setMappingValues(double amin, double amid, double amax, double fmin, + double fmid, double fmax) + { + //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccDownConverter update %f %f + //%f %f %f %f", amin,amid,amax,fmin,fmid,fmax); + fA2F = Interpolator3pt(amin, amid, amax, fmax, fmid, fmin); + fF2A = Interpolator3pt(fmin, fmid, fmax, amax, amid, amin); + } + + virtual void getMappingValues(double& amin, double& amid, double& amax) + { + fA2F.getMappingValues(amin, amid, amax); + } }; //-------------------------------------------------------------------------------------- // Convert accelerometer or gyroscope values to Faust values // Using an Up-Down curve (curve 2) //-------------------------------------------------------------------------------------- -class FAUST_API AccUpDownConverter : public UpdatableValueConverter { - - private: - - Interpolator3pt fA2F; - Interpolator fF2A; - - public: - - AccUpDownConverter(double amin, double amid, double amax, double fmin, double /*fmid*/, double fmax) : - fA2F(amin,amid,amax,fmin,fmax,fmin), - fF2A(fmin,fmax,amin,amax) // Special, pseudo inverse of a non monotonic function - {} - - virtual double ui2faust(double x) { return fA2F(x); } - virtual double faust2ui(double x) { return fF2A(x); } - - virtual void setMappingValues(double amin, double amid, double amax, double fmin, double /*fmid*/, double fmax) - { - //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccUpDownConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax); - fA2F = Interpolator3pt(amin, amid, amax, fmin, fmax, fmin); - fF2A = Interpolator(fmin, fmax, amin, amax); - } - - virtual void getMappingValues(double& amin, double& amid, double& amax) - { - fA2F.getMappingValues(amin, amid, amax); - } +class FAUST_API AccUpDownConverter : public UpdatableValueConverter +{ + private: + Interpolator3pt fA2F; + Interpolator fF2A; + + public: + AccUpDownConverter(double amin, double amid, double amax, double fmin, + double /*fmid*/, double fmax) + : fA2F(amin, amid, amax, fmin, fmax, fmin) + , fF2A(fmin, fmax, amin, + amax) // Special, pseudo inverse of a non monotonic function + { + } + + virtual double ui2faust(double x) { return fA2F(x); } + virtual double faust2ui(double x) { return fF2A(x); } + + virtual void setMappingValues(double amin, double amid, double amax, double fmin, + double /*fmid*/, double fmax) + { + //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccUpDownConverter update %f %f + //%f %f %f %f", amin,amid,amax,fmin,fmid,fmax); + fA2F = Interpolator3pt(amin, amid, amax, fmin, fmax, fmin); + fF2A = Interpolator(fmin, fmax, amin, amax); + } + + virtual void getMappingValues(double& amin, double& amid, double& amax) + { + fA2F.getMappingValues(amin, amid, amax); + } }; //-------------------------------------------------------------------------------------- // Convert accelerometer or gyroscope values to Faust values // Using a Down-Up curve (curve 3) //-------------------------------------------------------------------------------------- -class FAUST_API AccDownUpConverter : public UpdatableValueConverter { - - private: - - Interpolator3pt fA2F; - Interpolator fF2A; - - public: - - AccDownUpConverter(double amin, double amid, double amax, double fmin, double /*fmid*/, double fmax) : - fA2F(amin,amid,amax,fmax,fmin,fmax), - fF2A(fmin,fmax,amin,amax) // Special, pseudo inverse of a non monotonic function - {} - - virtual double ui2faust(double x) { return fA2F(x); } - virtual double faust2ui(double x) { return fF2A(x); } - - virtual void setMappingValues(double amin, double amid, double amax, double fmin, double /*fmid*/, double fmax) - { - //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccDownUpConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax); - fA2F = Interpolator3pt(amin, amid, amax, fmax, fmin, fmax); - fF2A = Interpolator(fmin, fmax, amin, amax); - } - - virtual void getMappingValues(double& amin, double& amid, double& amax) - { - fA2F.getMappingValues(amin, amid, amax); - } +class FAUST_API AccDownUpConverter : public UpdatableValueConverter +{ + private: + Interpolator3pt fA2F; + Interpolator fF2A; + + public: + AccDownUpConverter(double amin, double amid, double amax, double fmin, + double /*fmid*/, double fmax) + : fA2F(amin, amid, amax, fmax, fmin, fmax) + , fF2A(fmin, fmax, amin, + amax) // Special, pseudo inverse of a non monotonic function + { + } + + virtual double ui2faust(double x) { return fA2F(x); } + virtual double faust2ui(double x) { return fF2A(x); } + + virtual void setMappingValues(double amin, double amid, double amax, double fmin, + double /*fmid*/, double fmax) + { + //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccDownUpConverter update %f %f + //%f %f %f %f", amin,amid,amax,fmin,fmid,fmax); + fA2F = Interpolator3pt(amin, amid, amax, fmax, fmin, fmax); + fF2A = Interpolator(fmin, fmax, amin, amax); + } + + virtual void getMappingValues(double& amin, double& amid, double& amax) + { + fA2F.getMappingValues(amin, amid, amax); + } }; //-------------------------------------------------------------------------------------- // Base class for ZoneControl //-------------------------------------------------------------------------------------- -class FAUST_API ZoneControl { - - protected: - - FAUSTFLOAT* fZone; - - public: - - ZoneControl(FAUSTFLOAT* zone) : fZone(zone) {} - virtual ~ZoneControl() {} +class FAUST_API ZoneControl +{ + protected: + FAUSTFLOAT* fZone; - virtual void update(double /*v*/) const {} + public: + ZoneControl(FAUSTFLOAT* zone) : fZone(zone) {} + virtual ~ZoneControl() {} - virtual void setMappingValues(int /*curve*/, double /*amin*/, double /*amid*/, double /*amax*/, double /*min*/, double /*init*/, double /*max*/) {} - virtual void getMappingValues(double& /*amin*/, double& /*amid*/, double& /*amax*/) {} + virtual void update(double /*v*/) const {} - FAUSTFLOAT* getZone() { return fZone; } + virtual void setMappingValues(int /*curve*/, double /*amin*/, double /*amid*/, + double /*amax*/, double /*min*/, double /*init*/, + double /*max*/) + { + } + virtual void getMappingValues(double& /*amin*/, double& /*amid*/, double& /*amax*/) {} - virtual void setActive(bool /*on_off*/) {} - virtual bool getActive() { return false; } + FAUSTFLOAT* getZone() { return fZone; } - virtual int getCurve() { return -1; } + virtual void setActive(bool /*on_off*/) {} + virtual bool getActive() { return false; } + virtual int getCurve() { return -1; } }; //-------------------------------------------------------------------------------------- // Useful to implement accelerometers metadata as a list of ZoneControl for each axes //-------------------------------------------------------------------------------------- -class FAUST_API ConverterZoneControl : public ZoneControl { - - protected: - - ValueConverter* fValueConverter; - - public: - - ConverterZoneControl(FAUSTFLOAT* zone, ValueConverter* converter) : ZoneControl(zone), fValueConverter(converter) {} - virtual ~ConverterZoneControl() { delete fValueConverter; } // Assuming fValueConverter is not kept elsewhere... - - virtual void update(double v) const { *fZone = FAUSTFLOAT(fValueConverter->ui2faust(v)); } - - ValueConverter* getConverter() { return fValueConverter; } - +class FAUST_API ConverterZoneControl : public ZoneControl +{ + protected: + ValueConverter* fValueConverter; + + public: + ConverterZoneControl(FAUSTFLOAT* zone, ValueConverter* converter) + : ZoneControl(zone), fValueConverter(converter) + { + } + virtual ~ConverterZoneControl() + { + delete fValueConverter; + } // Assuming fValueConverter is not kept elsewhere... + + virtual void update(double v) const + { + *fZone = FAUSTFLOAT(fValueConverter->ui2faust(v)); + } + + ValueConverter* getConverter() { return fValueConverter; } }; //-------------------------------------------------------------------------------------- // Association of a zone and a four value converter, each one for each possible curve. // Useful to implement accelerometers metadata as a list of ZoneControl for each axes //-------------------------------------------------------------------------------------- -class FAUST_API CurveZoneControl : public ZoneControl { - - private: - - std::vector fValueConverters; - int fCurve; - - public: - - CurveZoneControl(FAUSTFLOAT* zone, int curve, double amin, double amid, double amax, double min, double init, double max) : ZoneControl(zone), fCurve(0) - { - assert(curve >= 0 && curve <= 3); - fValueConverters.push_back(new AccUpConverter(amin, amid, amax, min, init, max)); - fValueConverters.push_back(new AccDownConverter(amin, amid, amax, min, init, max)); - fValueConverters.push_back(new AccUpDownConverter(amin, amid, amax, min, init, max)); - fValueConverters.push_back(new AccDownUpConverter(amin, amid, amax, min, init, max)); - fCurve = curve; - } - virtual ~CurveZoneControl() - { - for (const auto& it : fValueConverters) { delete it; } - } - void update(double v) const { if (fValueConverters[fCurve]->getActive()) *fZone = FAUSTFLOAT(fValueConverters[fCurve]->ui2faust(v)); } - - void setMappingValues(int curve, double amin, double amid, double amax, double min, double init, double max) - { - fValueConverters[curve]->setMappingValues(amin, amid, amax, min, init, max); - fCurve = curve; - } - - void getMappingValues(double& amin, double& amid, double& amax) - { - fValueConverters[fCurve]->getMappingValues(amin, amid, amax); +class FAUST_API CurveZoneControl : public ZoneControl +{ + private: + std::vector fValueConverters; + int fCurve; + + public: + CurveZoneControl(FAUSTFLOAT* zone, int curve, double amin, double amid, double amax, + double min, double init, double max) + : ZoneControl(zone), fCurve(0) + { + assert(curve >= 0 && curve <= 3); + fValueConverters.push_back(new AccUpConverter(amin, amid, amax, min, init, max)); + fValueConverters.push_back( + new AccDownConverter(amin, amid, amax, min, init, max)); + fValueConverters.push_back( + new AccUpDownConverter(amin, amid, amax, min, init, max)); + fValueConverters.push_back( + new AccDownUpConverter(amin, amid, amax, min, init, max)); + fCurve = curve; + } + virtual ~CurveZoneControl() + { + for (const auto& it : fValueConverters) { + delete it; } - - void setActive(bool on_off) - { - for (const auto& it : fValueConverters) { it->setActive(on_off); } + } + void update(double v) const + { + if (fValueConverters[fCurve]->getActive()) + *fZone = FAUSTFLOAT(fValueConverters[fCurve]->ui2faust(v)); + } + + void setMappingValues(int curve, double amin, double amid, double amax, double min, + double init, double max) + { + fValueConverters[curve]->setMappingValues(amin, amid, amax, min, init, max); + fCurve = curve; + } + + void getMappingValues(double& amin, double& amid, double& amax) + { + fValueConverters[fCurve]->getMappingValues(amin, amid, amax); + } + + void setActive(bool on_off) + { + for (const auto& it : fValueConverters) { + it->setActive(on_off); } + } - int getCurve() { return fCurve; } + int getCurve() { return fCurve; } }; -class FAUST_API ZoneReader { - - private: - - FAUSTFLOAT* fZone; - Interpolator fInterpolator; - - public: - - ZoneReader(FAUSTFLOAT* zone, double lo, double hi) : fZone(zone), fInterpolator(lo, hi, 0, 255) {} +class FAUST_API ZoneReader +{ + private: + FAUSTFLOAT* fZone; + Interpolator fInterpolator; - virtual ~ZoneReader() {} + public: + ZoneReader(FAUSTFLOAT* zone, double lo, double hi) + : fZone(zone), fInterpolator(lo, hi, 0, 255) + { + } - int getValue() - { - return (fZone != nullptr) ? int(fInterpolator(*fZone)) : 127; - } + virtual ~ZoneReader() {} + int getValue() { return (fZone != nullptr) ? int(fInterpolator(*fZone)) : 127; } }; #endif @@ -1285,688 +1337,742 @@ class FAUST_API ZoneReader { typedef unsigned int uint; -class APIUI : public PathBuilder, public Meta, public UI +class APIUI + : public PathBuilder + , public Meta + , public UI { - public: - enum ItemType { kButton = 0, kCheckButton, kVSlider, kHSlider, kNumEntry, kHBargraph, kVBargraph }; - enum Type { kAcc = 0, kGyr = 1, kNoType }; - - protected: - - enum Mapping { kLin = 0, kLog = 1, kExp = 2 }; - - struct Item { - std::string fLabel; - std::string fShortname; - std::string fPath; - ValueConverter* fConversion; - FAUSTFLOAT* fZone; - FAUSTFLOAT fInit; - FAUSTFLOAT fMin; - FAUSTFLOAT fMax; - FAUSTFLOAT fStep; - ItemType fItemType; - - Item(const std::string& label, - const std::string& short_name, - const std::string& path, - ValueConverter* conversion, - FAUSTFLOAT* zone, - FAUSTFLOAT init, - FAUSTFLOAT min, - FAUSTFLOAT max, - FAUSTFLOAT step, - ItemType item_type) - :fLabel(label), fShortname(short_name), fPath(path), fConversion(conversion), - fZone(zone), fInit(init), fMin(min), fMax(max), fStep(step), fItemType(item_type) - {} - }; - std::vector fItems; - - std::vector > fMetaData; - std::vector fAcc[3]; - std::vector fGyr[3]; - - // Screen color control - // "...[screencolor:red]..." etc. - bool fHasScreenControl; // true if control screen color metadata - ZoneReader* fRedReader; - ZoneReader* fGreenReader; - ZoneReader* fBlueReader; - - // Current values controlled by metadata - std::string fCurrentUnit; - int fCurrentScale; - std::string fCurrentAcc; - std::string fCurrentGyr; - std::string fCurrentColor; - std::string fCurrentTooltip; - std::map fCurrentMetadata; - - // Add a generic parameter - virtual void addParameter(const char* label, - FAUSTFLOAT* zone, - FAUSTFLOAT init, - FAUSTFLOAT min, - FAUSTFLOAT max, - FAUSTFLOAT step, - ItemType type) + public: + enum ItemType { + kButton = 0, + kCheckButton, + kVSlider, + kHSlider, + kNumEntry, + kHBargraph, + kVBargraph + }; + enum Type { kAcc = 0, kGyr = 1, kNoType }; + + protected: + enum Mapping { kLin = 0, kLog = 1, kExp = 2 }; + + struct Item { + std::string fLabel; + std::string fShortname; + std::string fPath; + ValueConverter* fConversion; + FAUSTFLOAT* fZone; + FAUSTFLOAT fInit; + FAUSTFLOAT fMin; + FAUSTFLOAT fMax; + FAUSTFLOAT fStep; + ItemType fItemType; + + Item(const std::string& label, const std::string& short_name, + const std::string& path, ValueConverter* conversion, FAUSTFLOAT* zone, + FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step, + ItemType item_type) + : fLabel(label) + , fShortname(short_name) + , fPath(path) + , fConversion(conversion) + , fZone(zone) + , fInit(init) + , fMin(min) + , fMax(max) + , fStep(step) + , fItemType(item_type) { - std::string path = buildPath(label); - fFullPaths.push_back(path); - - // handle scale metadata - ValueConverter* converter = nullptr; - switch (fCurrentScale) { - case kLin: - converter = new LinearValueConverter(0, 1, min, max); - break; - case kLog: - converter = new LogValueConverter(0, 1, min, max); - break; - case kExp: - converter = new ExpValueConverter(0, 1, min, max); - break; - } - fCurrentScale = kLin; - - fItems.push_back(Item(label, "", path, converter, zone, init, min, max, step, type)); - - if (fCurrentAcc.size() > 0 && fCurrentGyr.size() > 0) { - fprintf(stderr, "warning : 'acc' and 'gyr' metadata used for the same %s parameter !!\n", label); - } + } + }; + std::vector fItems; + + std::vector > fMetaData; + std::vector fAcc[3]; + std::vector fGyr[3]; + + // Screen color control + // "...[screencolor:red]..." etc. + bool fHasScreenControl; // true if control screen color metadata + ZoneReader* fRedReader; + ZoneReader* fGreenReader; + ZoneReader* fBlueReader; + + // Current values controlled by metadata + std::string fCurrentUnit; + int fCurrentScale; + std::string fCurrentAcc; + std::string fCurrentGyr; + std::string fCurrentColor; + std::string fCurrentTooltip; + std::map fCurrentMetadata; + + // Add a generic parameter + virtual void addParameter(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, + FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step, + ItemType type) + { + std::string path = buildPath(label); + fFullPaths.push_back(path); + + // handle scale metadata + ValueConverter* converter = nullptr; + switch (fCurrentScale) { + case kLin: + converter = new LinearValueConverter(0, 1, min, max); + break; + case kLog: + converter = new LogValueConverter(0, 1, min, max); + break; + case kExp: + converter = new ExpValueConverter(0, 1, min, max); + break; + } + fCurrentScale = kLin; - // handle acc metadata "...[acc : ]..." - if (fCurrentAcc.size() > 0) { - std::istringstream iss(fCurrentAcc); - int axe, curve; - double amin, amid, amax; - iss >> axe >> curve >> amin >> amid >> amax; - - if ((0 <= axe) && (axe < 3) && - (0 <= curve) && (curve < 4) && - (amin < amax) && (amin <= amid) && (amid <= amax)) - { - fAcc[axe].push_back(new CurveZoneControl(zone, curve, amin, amid, amax, min, init, max)); - } else { - fprintf(stderr, "incorrect acc metadata : %s \n", fCurrentAcc.c_str()); - } - fCurrentAcc = ""; - } + fItems.push_back( + Item(label, "", path, converter, zone, init, min, max, step, type)); - // handle gyr metadata "...[gyr : ]..." - if (fCurrentGyr.size() > 0) { - std::istringstream iss(fCurrentGyr); - int axe, curve; - double amin, amid, amax; - iss >> axe >> curve >> amin >> amid >> amax; - - if ((0 <= axe) && (axe < 3) && - (0 <= curve) && (curve < 4) && - (amin < amax) && (amin <= amid) && (amid <= amax)) - { - fGyr[axe].push_back(new CurveZoneControl(zone, curve, amin, amid, amax, min, init, max)); - } else { - fprintf(stderr, "incorrect gyr metadata : %s \n", fCurrentGyr.c_str()); - } - fCurrentGyr = ""; - } + if (fCurrentAcc.size() > 0 && fCurrentGyr.size() > 0) { + fprintf( + stderr, + "warning : 'acc' and 'gyr' metadata used for the same %s parameter !!\n", + label); + } - // handle screencolor metadata "...[screencolor:red|green|blue|white]..." - if (fCurrentColor.size() > 0) { - if ((fCurrentColor == "red") && (fRedReader == nullptr)) { - fRedReader = new ZoneReader(zone, min, max); - fHasScreenControl = true; - } else if ((fCurrentColor == "green") && (fGreenReader == nullptr)) { - fGreenReader = new ZoneReader(zone, min, max); - fHasScreenControl = true; - } else if ((fCurrentColor == "blue") && (fBlueReader == nullptr)) { - fBlueReader = new ZoneReader(zone, min, max); - fHasScreenControl = true; - } else if ((fCurrentColor == "white") && (fRedReader == nullptr) && (fGreenReader == nullptr) && (fBlueReader == nullptr)) { - fRedReader = new ZoneReader(zone, min, max); - fGreenReader = new ZoneReader(zone, min, max); - fBlueReader = new ZoneReader(zone, min, max); - fHasScreenControl = true; - } else { - fprintf(stderr, "incorrect screencolor metadata : %s \n", fCurrentColor.c_str()); - } + // handle acc metadata "...[acc : ]..." + if (fCurrentAcc.size() > 0) { + std::istringstream iss(fCurrentAcc); + int axe, curve; + double amin, amid, amax; + iss >> axe >> curve >> amin >> amid >> amax; + + if ((0 <= axe) && (axe < 3) && (0 <= curve) && (curve < 4) && (amin < amax) + && (amin <= amid) && (amid <= amax)) { + fAcc[axe].push_back( + new CurveZoneControl(zone, curve, amin, amid, amax, min, init, max)); + } else { + fprintf(stderr, "incorrect acc metadata : %s \n", fCurrentAcc.c_str()); } - fCurrentColor = ""; - - fMetaData.push_back(fCurrentMetadata); - fCurrentMetadata.clear(); + fCurrentAcc = ""; } - int getZoneIndex(std::vector* table, int p, int val) - { - FAUSTFLOAT* zone = fItems[uint(p)].fZone; - for (size_t i = 0; i < table[val].size(); i++) { - if (zone == table[val][i]->getZone()) return int(i); + // handle gyr metadata "...[gyr : ]..." + if (fCurrentGyr.size() > 0) { + std::istringstream iss(fCurrentGyr); + int axe, curve; + double amin, amid, amax; + iss >> axe >> curve >> amin >> amid >> amax; + + if ((0 <= axe) && (axe < 3) && (0 <= curve) && (curve < 4) && (amin < amax) + && (amin <= amid) && (amid <= amax)) { + fGyr[axe].push_back( + new CurveZoneControl(zone, curve, amin, amid, amax, min, init, max)); + } else { + fprintf(stderr, "incorrect gyr metadata : %s \n", fCurrentGyr.c_str()); } - return -1; + fCurrentGyr = ""; } - void setConverter(std::vector* table, int p, int val, int curve, double amin, double amid, double amax) - { - int id1 = getZoneIndex(table, p, 0); - int id2 = getZoneIndex(table, p, 1); - int id3 = getZoneIndex(table, p, 2); - - // Deactivates everywhere.. - if (id1 != -1) table[0][uint(id1)]->setActive(false); - if (id2 != -1) table[1][uint(id2)]->setActive(false); - if (id3 != -1) table[2][uint(id3)]->setActive(false); - - if (val == -1) { // Means: no more mapping... - // So stay all deactivated... + // handle screencolor metadata "...[screencolor:red|green|blue|white]..." + if (fCurrentColor.size() > 0) { + if ((fCurrentColor == "red") && (fRedReader == nullptr)) { + fRedReader = new ZoneReader(zone, min, max); + fHasScreenControl = true; + } else if ((fCurrentColor == "green") && (fGreenReader == nullptr)) { + fGreenReader = new ZoneReader(zone, min, max); + fHasScreenControl = true; + } else if ((fCurrentColor == "blue") && (fBlueReader == nullptr)) { + fBlueReader = new ZoneReader(zone, min, max); + fHasScreenControl = true; + } else if ((fCurrentColor == "white") && (fRedReader == nullptr) + && (fGreenReader == nullptr) && (fBlueReader == nullptr)) { + fRedReader = new ZoneReader(zone, min, max); + fGreenReader = new ZoneReader(zone, min, max); + fBlueReader = new ZoneReader(zone, min, max); + fHasScreenControl = true; } else { - int id4 = getZoneIndex(table, p, val); - if (id4 != -1) { - // Reactivate the one we edit... - table[val][uint(id4)]->setMappingValues(curve, amin, amid, amax, fItems[uint(p)].fMin, fItems[uint(p)].fInit, fItems[uint(p)].fMax); - table[val][uint(id4)]->setActive(true); - } else { - // Allocate a new CurveZoneControl which is 'active' by default - FAUSTFLOAT* zone = fItems[uint(p)].fZone; - table[val].push_back(new CurveZoneControl(zone, curve, amin, amid, amax, fItems[uint(p)].fMin, fItems[uint(p)].fInit, fItems[uint(p)].fMax)); - } + fprintf(stderr, "incorrect screencolor metadata : %s \n", + fCurrentColor.c_str()); } } - - void getConverter(std::vector* table, int p, int& val, int& curve, double& amin, double& amid, double& amax) - { - int id1 = getZoneIndex(table, p, 0); - int id2 = getZoneIndex(table, p, 1); - int id3 = getZoneIndex(table, p, 2); - - if (id1 != -1) { - val = 0; - curve = table[val][uint(id1)]->getCurve(); - table[val][uint(id1)]->getMappingValues(amin, amid, amax); - } else if (id2 != -1) { - val = 1; - curve = table[val][uint(id2)]->getCurve(); - table[val][uint(id2)]->getMappingValues(amin, amid, amax); - } else if (id3 != -1) { - val = 2; - curve = table[val][uint(id3)]->getCurve(); - table[val][uint(id3)]->getMappingValues(amin, amid, amax); + fCurrentColor = ""; + + fMetaData.push_back(fCurrentMetadata); + fCurrentMetadata.clear(); + } + + int getZoneIndex(std::vector* table, int p, int val) + { + FAUSTFLOAT* zone = fItems[uint(p)].fZone; + for (size_t i = 0; i < table[val].size(); i++) { + if (zone == table[val][i]->getZone()) + return int(i); + } + return -1; + } + + void setConverter(std::vector* table, int p, int val, int curve, + double amin, double amid, double amax) + { + int id1 = getZoneIndex(table, p, 0); + int id2 = getZoneIndex(table, p, 1); + int id3 = getZoneIndex(table, p, 2); + + // Deactivates everywhere.. + if (id1 != -1) + table[0][uint(id1)]->setActive(false); + if (id2 != -1) + table[1][uint(id2)]->setActive(false); + if (id3 != -1) + table[2][uint(id3)]->setActive(false); + + if (val == -1) { // Means: no more mapping... + // So stay all deactivated... + } else { + int id4 = getZoneIndex(table, p, val); + if (id4 != -1) { + // Reactivate the one we edit... + table[val][uint(id4)]->setMappingValues( + curve, amin, amid, amax, fItems[uint(p)].fMin, fItems[uint(p)].fInit, + fItems[uint(p)].fMax); + table[val][uint(id4)]->setActive(true); } else { - val = -1; // No mapping - curve = 0; - amin = -100.; - amid = 0.; - amax = 100.; + // Allocate a new CurveZoneControl which is 'active' by default + FAUSTFLOAT* zone = fItems[uint(p)].fZone; + table[val].push_back(new CurveZoneControl( + zone, curve, amin, amid, amax, fItems[uint(p)].fMin, + fItems[uint(p)].fInit, fItems[uint(p)].fMax)); } } + } + + void getConverter(std::vector* table, int p, int& val, int& curve, + double& amin, double& amid, double& amax) + { + int id1 = getZoneIndex(table, p, 0); + int id2 = getZoneIndex(table, p, 1); + int id3 = getZoneIndex(table, p, 2); + + if (id1 != -1) { + val = 0; + curve = table[val][uint(id1)]->getCurve(); + table[val][uint(id1)]->getMappingValues(amin, amid, amax); + } else if (id2 != -1) { + val = 1; + curve = table[val][uint(id2)]->getCurve(); + table[val][uint(id2)]->getMappingValues(amin, amid, amax); + } else if (id3 != -1) { + val = 2; + curve = table[val][uint(id3)]->getCurve(); + table[val][uint(id3)]->getMappingValues(amin, amid, amax); + } else { + val = -1; // No mapping + curve = 0; + amin = -100.; + amid = 0.; + amax = 100.; + } + } + + public: + APIUI() + : fHasScreenControl(false) + , fRedReader(nullptr) + , fGreenReader(nullptr) + , fBlueReader(nullptr) + , fCurrentScale(kLin) + { + } + + virtual ~APIUI() + { + for (const auto& it : fItems) + delete it.fConversion; + for (int i = 0; i < 3; i++) { + for (const auto& it : fAcc[i]) + delete it; + for (const auto& it : fGyr[i]) + delete it; + } + delete fRedReader; + delete fGreenReader; + delete fBlueReader; + } - public: - - APIUI() : fHasScreenControl(false), fRedReader(nullptr), fGreenReader(nullptr), fBlueReader(nullptr), fCurrentScale(kLin) - {} + // -- widget's layouts - virtual ~APIUI() - { - for (const auto& it : fItems) delete it.fConversion; - for (int i = 0; i < 3; i++) { - for (const auto& it : fAcc[i]) delete it; - for (const auto& it : fGyr[i]) delete it; + virtual void openTabBox(const char* label) { pushLabel(label); } + virtual void openHorizontalBox(const char* label) { pushLabel(label); } + virtual void openVerticalBox(const char* label) { pushLabel(label); } + virtual void closeBox() + { + if (popLabel()) { + // Shortnames can be computed when all fullnames are known + computeShortNames(); + // Fill 'shortname' field for each item + for (const auto& it : fFull2Short) { + int index = getParamIndex(it.first.c_str()); + fItems[index].fShortname = it.second; } - delete fRedReader; - delete fGreenReader; - delete fBlueReader; } + } - // -- widget's layouts + // -- active widgets - virtual void openTabBox(const char* label) { pushLabel(label); } - virtual void openHorizontalBox(const char* label) { pushLabel(label); } - virtual void openVerticalBox(const char* label) { pushLabel(label); } - virtual void closeBox() - { - if (popLabel()) { - // Shortnames can be computed when all fullnames are known - computeShortNames(); - // Fill 'shortname' field for each item - for (const auto& it : fFull2Short) { - int index = getParamIndex(it.first.c_str()); - fItems[index].fShortname = it.second; - } - } - } + virtual void addButton(const char* label, FAUSTFLOAT* zone) + { + addParameter(label, zone, 0, 0, 1, 1, kButton); + } + + virtual void addCheckButton(const char* label, FAUSTFLOAT* zone) + { + addParameter(label, zone, 0, 0, 1, 1, kCheckButton); + } + + virtual void addVerticalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, + FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) + { + addParameter(label, zone, init, min, max, step, kVSlider); + } + + virtual void addHorizontalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, + FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) + { + addParameter(label, zone, init, min, max, step, kHSlider); + } + + virtual void addNumEntry(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, + FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) + { + addParameter(label, zone, init, min, max, step, kNumEntry); + } - // -- active widgets + // -- passive widgets - virtual void addButton(const char* label, FAUSTFLOAT* zone) - { - addParameter(label, zone, 0, 0, 1, 1, kButton); - } + virtual void addHorizontalBargraph(const char* label, FAUSTFLOAT* zone, + FAUSTFLOAT min, FAUSTFLOAT max) + { + addParameter(label, zone, min, min, max, (max - min) / 1000.0f, kHBargraph); + } - virtual void addCheckButton(const char* label, FAUSTFLOAT* zone) - { - addParameter(label, zone, 0, 0, 1, 1, kCheckButton); - } + virtual void addVerticalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT min, + FAUSTFLOAT max) + { + addParameter(label, zone, min, min, max, (max - min) / 1000.0f, kVBargraph); + } - virtual void addVerticalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) - { - addParameter(label, zone, init, min, max, step, kVSlider); - } + // -- soundfiles - virtual void addHorizontalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) - { - addParameter(label, zone, init, min, max, step, kHSlider); - } + virtual void addSoundfile(const char* /*label*/, const char* /*filename*/, + Soundfile** /*sf_zone*/) + { + } - virtual void addNumEntry(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) - { - addParameter(label, zone, init, min, max, step, kNumEntry); - } + // -- metadata declarations - // -- passive widgets + virtual void declare(FAUSTFLOAT* /*zone*/, const char* key, const char* val) + { + // Keep metadata + fCurrentMetadata[key] = val; - virtual void addHorizontalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT min, FAUSTFLOAT max) - { - addParameter(label, zone, min, min, max, (max-min)/1000.0f, kHBargraph); + if (strcmp(key, "scale") == 0) { + if (strcmp(val, "log") == 0) { + fCurrentScale = kLog; + } else if (strcmp(val, "exp") == 0) { + fCurrentScale = kExp; + } else { + fCurrentScale = kLin; + } + } else if (strcmp(key, "unit") == 0) { + fCurrentUnit = val; + } else if (strcmp(key, "acc") == 0) { + fCurrentAcc = val; + } else if (strcmp(key, "gyr") == 0) { + fCurrentGyr = val; + } else if (strcmp(key, "screencolor") == 0) { + fCurrentColor = val; // val = "red", "green", "blue" or "white" + } else if (strcmp(key, "tooltip") == 0) { + fCurrentTooltip = val; } + } - virtual void addVerticalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT min, FAUSTFLOAT max) - { - addParameter(label, zone, min, min, max, (max-min)/1000.0f, kVBargraph); - } + virtual void declare(const char* /*key*/, const char* /*val*/) {} - // -- soundfiles + //------------------------------------------------------------------------------- + // Simple API part + //------------------------------------------------------------------------------- - virtual void addSoundfile(const char* /*label*/, const char* /*filename*/, Soundfile** /*sf_zone*/) {} + /** + * Return the number of parameters in the UI. + * + * @return the number of parameters + */ + int getParamsCount() { return int(fItems.size()); } - // -- metadata declarations + /** + * Return the param index. + * + * @param str - the UI parameter label/shortname/path + * + * @return the param index + */ + int getParamIndex(const char* str) + { + std::string path = std::string(str); + auto it = find_if(fItems.begin(), fItems.end(), [=](const Item& it) { + return (it.fLabel == path) || (it.fShortname == path) || (it.fPath == path); + }); + return (it != fItems.end()) ? int(it - fItems.begin()) : -1; + } - virtual void declare(FAUSTFLOAT* /*zone*/, const char* key, const char* val) - { - // Keep metadata - fCurrentMetadata[key] = val; - - if (strcmp(key, "scale") == 0) { - if (strcmp(val, "log") == 0) { - fCurrentScale = kLog; - } else if (strcmp(val, "exp") == 0) { - fCurrentScale = kExp; - } else { - fCurrentScale = kLin; - } - } else if (strcmp(key, "unit") == 0) { - fCurrentUnit = val; - } else if (strcmp(key, "acc") == 0) { - fCurrentAcc = val; - } else if (strcmp(key, "gyr") == 0) { - fCurrentGyr = val; - } else if (strcmp(key, "screencolor") == 0) { - fCurrentColor = val; // val = "red", "green", "blue" or "white" - } else if (strcmp(key, "tooltip") == 0) { - fCurrentTooltip = val; - } - } + /** + * Return the param label. + * + * @param p - the UI parameter index + * + * @return the param label + */ + const char* getParamLabel(int p) { return fItems[uint(p)].fLabel.c_str(); } - virtual void declare(const char* /*key*/, const char* /*val*/) - {} - - //------------------------------------------------------------------------------- - // Simple API part - //------------------------------------------------------------------------------- - - /** - * Return the number of parameters in the UI. - * - * @return the number of parameters - */ - int getParamsCount() { return int(fItems.size()); } - - /** - * Return the param index. - * - * @param str - the UI parameter label/shortname/path - * - * @return the param index - */ - int getParamIndex(const char* str) - { - std::string path = std::string(str); - auto it = find_if(fItems.begin(), fItems.end(), - [=](const Item& it) { return (it.fLabel == path) || (it.fShortname == path) || (it.fPath == path); }); - return (it != fItems.end()) ? int(it - fItems.begin()) : -1; - } - - /** - * Return the param label. - * - * @param p - the UI parameter index - * - * @return the param label - */ - const char* getParamLabel(int p) { return fItems[uint(p)].fLabel.c_str(); } - - /** - * Return the param shortname. - * - * @param p - the UI parameter index - * - * @return the param shortname - */ - const char* getParamShortname(int p) { return fItems[uint(p)].fShortname.c_str(); } - - /** - * Return the param path. - * - * @param p - the UI parameter index - * - * @return the param path - */ - const char* getParamAddress(int p) { return fItems[uint(p)].fPath.c_str(); } - - /** - * Return the param metadata. - * - * @param p - the UI parameter index - * - * @return the param metadata as a map - */ - std::map getMetadata(int p) - { - std::map res; - std::map metadata = fMetaData[uint(p)]; - for (const auto& it : metadata) { - res[it.first.c_str()] = it.second.c_str(); - } - return res; - } + /** + * Return the param shortname. + * + * @param p - the UI parameter index + * + * @return the param shortname + */ + const char* getParamShortname(int p) { return fItems[uint(p)].fShortname.c_str(); } - /** - * Return the param metadata value. - * - * @param p - the UI parameter index - * @param key - the UI parameter index - * - * @return the param metadata value associate to the key - */ - const char* getMetadata(int p, const char* key) - { - return (fMetaData[uint(p)].find(key) != fMetaData[uint(p)].end()) ? fMetaData[uint(p)][key].c_str() : ""; - } - - /** - * Return the param minimum value. - * - * @param p - the UI parameter index - * - * @return the param minimum value - */ - FAUSTFLOAT getParamMin(int p) { return fItems[uint(p)].fMin; } - - /** - * Return the param maximum value. - * - * @param p - the UI parameter index - * - * @return the param maximum value - */ - FAUSTFLOAT getParamMax(int p) { return fItems[uint(p)].fMax; } - - /** - * Return the param step value. - * - * @param p - the UI parameter index - * - * @return the param step value - */ - FAUSTFLOAT getParamStep(int p) { return fItems[uint(p)].fStep; } - - /** - * Return the param init value. - * - * @param p - the UI parameter index - * - * @return the param init value - */ - FAUSTFLOAT getParamInit(int p) { return fItems[uint(p)].fInit; } - - /** - * Return the param memory zone. - * - * @param p - the UI parameter index - * - * @return the param memory zone. - */ - FAUSTFLOAT* getParamZone(int p) { return fItems[uint(p)].fZone; } - - /** - * Return the param value. - * - * @param p - the UI parameter index - * - * @return the param value. - */ - FAUSTFLOAT getParamValue(int p) { return *fItems[uint(p)].fZone; } - - /** - * Return the param value. - * - * @param str - the UI parameter label/shortname/path - * - * @return the param value. - */ - FAUSTFLOAT getParamValue(const char* str) - { - int index = getParamIndex(str); - if (index >= 0) { - return getParamValue(index); - } else { - fprintf(stderr, "getParamValue : '%s' not found\n", (str == nullptr ? "NULL" : str)); - return FAUSTFLOAT(0); - } - } + /** + * Return the param path. + * + * @param p - the UI parameter index + * + * @return the param path + */ + const char* getParamAddress(int p) { return fItems[uint(p)].fPath.c_str(); } - /** - * Set the param value. - * - * @param p - the UI parameter index - * @param v - the UI parameter value - * - */ - void setParamValue(int p, FAUSTFLOAT v) { *fItems[uint(p)].fZone = v; } - - /** - * Set the param value. - * - * @param p - the UI parameter label/shortname/path - * @param v - the UI parameter value - * - */ - void setParamValue(const char* path, FAUSTFLOAT v) - { - int index = getParamIndex(path); - if (index >= 0) { - setParamValue(index, v); - } else { - fprintf(stderr, "setParamValue : '%s' not found\n", (path == nullptr ? "NULL" : path)); - } + /** + * Return the param metadata. + * + * @param p - the UI parameter index + * + * @return the param metadata as a map + */ + std::map getMetadata(int p) + { + std::map res; + std::map metadata = fMetaData[uint(p)]; + for (const auto& it : metadata) { + res[it.first.c_str()] = it.second.c_str(); } + return res; + } - double getParamRatio(int p) { return fItems[uint(p)].fConversion->faust2ui(*fItems[uint(p)].fZone); } - void setParamRatio(int p, double r) { *fItems[uint(p)].fZone = FAUSTFLOAT(fItems[uint(p)].fConversion->ui2faust(r)); } + /** + * Return the param metadata value. + * + * @param p - the UI parameter index + * @param key - the UI parameter index + * + * @return the param metadata value associate to the key + */ + const char* getMetadata(int p, const char* key) + { + return (fMetaData[uint(p)].find(key) != fMetaData[uint(p)].end()) + ? fMetaData[uint(p)][key].c_str() + : ""; + } - double value2ratio(int p, double r) { return fItems[uint(p)].fConversion->faust2ui(r); } - double ratio2value(int p, double r) { return fItems[uint(p)].fConversion->ui2faust(r); } + /** + * Return the param minimum value. + * + * @param p - the UI parameter index + * + * @return the param minimum value + */ + FAUSTFLOAT getParamMin(int p) { return fItems[uint(p)].fMin; } - /** - * Return the control type (kAcc, kGyr, or -1) for a given parameter. - * - * @param p - the UI parameter index - * - * @return the type - */ - Type getParamType(int p) - { - if (p >= 0) { - if (getZoneIndex(fAcc, p, 0) != -1 - || getZoneIndex(fAcc, p, 1) != -1 - || getZoneIndex(fAcc, p, 2) != -1) { - return kAcc; - } else if (getZoneIndex(fGyr, p, 0) != -1 - || getZoneIndex(fGyr, p, 1) != -1 - || getZoneIndex(fGyr, p, 2) != -1) { - return kGyr; - } - } - return kNoType; - } + /** + * Return the param maximum value. + * + * @param p - the UI parameter index + * + * @return the param maximum value + */ + FAUSTFLOAT getParamMax(int p) { return fItems[uint(p)].fMax; } - /** - * Return the Item type (kButton = 0, kCheckButton, kVSlider, kHSlider, kNumEntry, kHBargraph, kVBargraph) for a given parameter. - * - * @param p - the UI parameter index - * - * @return the Item type - */ - ItemType getParamItemType(int p) - { - return fItems[uint(p)].fItemType; - } + /** + * Return the param step value. + * + * @param p - the UI parameter index + * + * @return the param step value + */ + FAUSTFLOAT getParamStep(int p) { return fItems[uint(p)].fStep; } - /** - * Set a new value coming from an accelerometer, propagate it to all relevant FAUSTFLOAT* zones. - * - * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer - * @param value - the new value - * - */ - void propagateAcc(int acc, double value) - { - for (size_t i = 0; i < fAcc[acc].size(); i++) { - fAcc[acc][i]->update(value); - } - } + /** + * Return the param init value. + * + * @param p - the UI parameter index + * + * @return the param init value + */ + FAUSTFLOAT getParamInit(int p) { return fItems[uint(p)].fInit; } - /** - * Used to edit accelerometer curves and mapping. Set curve and related mapping for a given UI parameter. - * - * @param p - the UI parameter index - * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer (-1 means "no mapping") - * @param curve - between 0 and 3 (0: up, 1: down, 2: up and down, 2: down and up) - * @param amin - mapping 'min' point - * @param amid - mapping 'middle' point - * @param amax - mapping 'max' point - * - */ - void setAccConverter(int p, int acc, int curve, double amin, double amid, double amax) - { - setConverter(fAcc, p, acc, curve, amin, amid, amax); - } + /** + * Return the param memory zone. + * + * @param p - the UI parameter index + * + * @return the param memory zone. + */ + FAUSTFLOAT* getParamZone(int p) { return fItems[uint(p)].fZone; } - /** - * Used to edit gyroscope curves and mapping. Set curve and related mapping for a given UI parameter. - * - * @param p - the UI parameter index - * @param gyr - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope (-1 means "no mapping") - * @param curve - between 0 and 3 (0: up, 1: down, 2: up and down, 2: down and up) - * @param amin - mapping 'min' point - * @param amid - mapping 'middle' point - * @param amax - mapping 'max' point - * - */ - void setGyrConverter(int p, int gyr, int curve, double amin, double amid, double amax) - { - setConverter(fGyr, p, gyr, curve, amin, amid, amax); - } + /** + * Return the param value. + * + * @param p - the UI parameter index + * + * @return the param value. + */ + FAUSTFLOAT getParamValue(int p) { return *fItems[uint(p)].fZone; } - /** - * Used to edit accelerometer curves and mapping. Get curve and related mapping for a given UI parameter. - * - * @param p - the UI parameter index - * @param acc - the acc value to be retrieved (-1 means "no mapping") - * @param curve - the curve value to be retrieved (between 0 and 3) - * @param amin - the amin value to be retrieved - * @param amid - the amid value to be retrieved - * @param amax - the amax value to be retrieved - * - */ - void getAccConverter(int p, int& acc, int& curve, double& amin, double& amid, double& amax) - { - getConverter(fAcc, p, acc, curve, amin, amid, amax); + /** + * Return the param value. + * + * @param str - the UI parameter label/shortname/path + * + * @return the param value. + */ + FAUSTFLOAT getParamValue(const char* str) + { + int index = getParamIndex(str); + if (index >= 0) { + return getParamValue(index); + } else { + fprintf(stderr, "getParamValue : '%s' not found\n", + (str == nullptr ? "NULL" : str)); + return FAUSTFLOAT(0); } + } - /** - * Used to edit gyroscope curves and mapping. Get curve and related mapping for a given UI parameter. - * - * @param p - the UI parameter index - * @param gyr - the gyr value to be retrieved (-1 means "no mapping") - * @param curve - the curve value to be retrieved (between 0 and 3) - * @param amin - the amin value to be retrieved - * @param amid - the amid value to be retrieved - * @param amax - the amax value to be retrieved - * - */ - void getGyrConverter(int p, int& gyr, int& curve, double& amin, double& amid, double& amax) - { - getConverter(fGyr, p, gyr, curve, amin, amid, amax); + /** + * Set the param value. + * + * @param p - the UI parameter index + * @param v - the UI parameter value + * + */ + void setParamValue(int p, FAUSTFLOAT v) { *fItems[uint(p)].fZone = v; } + + /** + * Set the param value. + * + * @param p - the UI parameter label/shortname/path + * @param v - the UI parameter value + * + */ + void setParamValue(const char* path, FAUSTFLOAT v) + { + int index = getParamIndex(path); + if (index >= 0) { + setParamValue(index, v); + } else { + fprintf(stderr, "setParamValue : '%s' not found\n", + (path == nullptr ? "NULL" : path)); } + } + + double getParamRatio(int p) + { + return fItems[uint(p)].fConversion->faust2ui(*fItems[uint(p)].fZone); + } + void setParamRatio(int p, double r) + { + *fItems[uint(p)].fZone = FAUSTFLOAT(fItems[uint(p)].fConversion->ui2faust(r)); + } + + double value2ratio(int p, double r) + { + return fItems[uint(p)].fConversion->faust2ui(r); + } + double ratio2value(int p, double r) + { + return fItems[uint(p)].fConversion->ui2faust(r); + } - /** - * Set a new value coming from an gyroscope, propagate it to all relevant FAUSTFLOAT* zones. - * - * @param gyr - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope - * @param value - the new value - * - */ - void propagateGyr(int gyr, double value) - { - for (size_t i = 0; i < fGyr[gyr].size(); i++) { - fGyr[gyr][i]->update(value); + /** + * Return the control type (kAcc, kGyr, or -1) for a given parameter. + * + * @param p - the UI parameter index + * + * @return the type + */ + Type getParamType(int p) + { + if (p >= 0) { + if (getZoneIndex(fAcc, p, 0) != -1 || getZoneIndex(fAcc, p, 1) != -1 + || getZoneIndex(fAcc, p, 2) != -1) { + return kAcc; + } else if (getZoneIndex(fGyr, p, 0) != -1 || getZoneIndex(fGyr, p, 1) != -1 + || getZoneIndex(fGyr, p, 2) != -1) { + return kGyr; } } + return kNoType; + } - /** - * Get the number of FAUSTFLOAT* zones controlled with the accelerometer. - * - * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer - * @return the number of zones - * - */ - int getAccCount(int acc) - { - return (acc >= 0 && acc < 3) ? int(fAcc[acc].size()) : 0; - } + /** + * Return the Item type (kButton = 0, kCheckButton, kVSlider, kHSlider, kNumEntry, + * kHBargraph, kVBargraph) for a given parameter. + * + * @param p - the UI parameter index + * + * @return the Item type + */ + ItemType getParamItemType(int p) { return fItems[uint(p)].fItemType; } - /** - * Get the number of FAUSTFLOAT* zones controlled with the gyroscope. - * - * @param gyr - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope - * @param the number of zones - * - */ - int getGyrCount(int gyr) - { - return (gyr >= 0 && gyr < 3) ? int(fGyr[gyr].size()) : 0; + /** + * Set a new value coming from an accelerometer, propagate it to all relevant + * FAUSTFLOAT* zones. + * + * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer + * @param value - the new value + * + */ + void propagateAcc(int acc, double value) + { + for (size_t i = 0; i < fAcc[acc].size(); i++) { + fAcc[acc][i]->update(value); } + } - /** - * Get the requested screen color. - * - * -1 means no screen color control (no screencolor metadata found) - * otherwise return 0x00RRGGBB a ready to use color - * - */ - int getScreenColor() - { - if (fHasScreenControl) { - int r = (fRedReader) ? fRedReader->getValue() : 0; - int g = (fGreenReader) ? fGreenReader->getValue() : 0; - int b = (fBlueReader) ? fBlueReader->getValue() : 0; - return (r<<16) | (g<<8) | b; - } else { - return -1; - } + /** + * Used to edit accelerometer curves and mapping. Set curve and related mapping for a + * given UI parameter. + * + * @param p - the UI parameter index + * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer + * (-1 means "no mapping") + * @param curve - between 0 and 3 (0: up, 1: down, 2: up and down, 2: down and up) + * @param amin - mapping 'min' point + * @param amid - mapping 'middle' point + * @param amax - mapping 'max' point + * + */ + void setAccConverter(int p, int acc, int curve, double amin, double amid, double amax) + { + setConverter(fAcc, p, acc, curve, amin, amid, amax); + } + + /** + * Used to edit gyroscope curves and mapping. Set curve and related mapping for a + * given UI parameter. + * + * @param p - the UI parameter index + * @param gyr - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope (-1 means "no + * mapping") + * @param curve - between 0 and 3 (0: up, 1: down, 2: up and down, 2: down and up) + * @param amin - mapping 'min' point + * @param amid - mapping 'middle' point + * @param amax - mapping 'max' point + * + */ + void setGyrConverter(int p, int gyr, int curve, double amin, double amid, double amax) + { + setConverter(fGyr, p, gyr, curve, amin, amid, amax); + } + + /** + * Used to edit accelerometer curves and mapping. Get curve and related mapping for a + * given UI parameter. + * + * @param p - the UI parameter index + * @param acc - the acc value to be retrieved (-1 means "no mapping") + * @param curve - the curve value to be retrieved (between 0 and 3) + * @param amin - the amin value to be retrieved + * @param amid - the amid value to be retrieved + * @param amax - the amax value to be retrieved + * + */ + void getAccConverter(int p, int& acc, int& curve, double& amin, double& amid, + double& amax) + { + getConverter(fAcc, p, acc, curve, amin, amid, amax); + } + + /** + * Used to edit gyroscope curves and mapping. Get curve and related mapping for a + * given UI parameter. + * + * @param p - the UI parameter index + * @param gyr - the gyr value to be retrieved (-1 means "no mapping") + * @param curve - the curve value to be retrieved (between 0 and 3) + * @param amin - the amin value to be retrieved + * @param amid - the amid value to be retrieved + * @param amax - the amax value to be retrieved + * + */ + void getGyrConverter(int p, int& gyr, int& curve, double& amin, double& amid, + double& amax) + { + getConverter(fGyr, p, gyr, curve, amin, amid, amax); + } + + /** + * Set a new value coming from an gyroscope, propagate it to all relevant FAUSTFLOAT* + * zones. + * + * @param gyr - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope + * @param value - the new value + * + */ + void propagateGyr(int gyr, double value) + { + for (size_t i = 0; i < fGyr[gyr].size(); i++) { + fGyr[gyr][i]->update(value); } + } + /** + * Get the number of FAUSTFLOAT* zones controlled with the accelerometer. + * + * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer + * @return the number of zones + * + */ + int getAccCount(int acc) { return (acc >= 0 && acc < 3) ? int(fAcc[acc].size()) : 0; } + + /** + * Get the number of FAUSTFLOAT* zones controlled with the gyroscope. + * + * @param gyr - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope + * @param the number of zones + * + */ + int getGyrCount(int gyr) { return (gyr >= 0 && gyr < 3) ? int(fGyr[gyr].size()) : 0; } + + /** + * Get the requested screen color. + * + * -1 means no screen color control (no screencolor metadata found) + * otherwise return 0x00RRGGBB a ready to use color + * + */ + int getScreenColor() + { + if (fHasScreenControl) { + int r = (fRedReader) ? fRedReader->getValue() : 0; + int g = (fGreenReader) ? fGreenReader->getValue() : 0; + int b = (fBlueReader) ? fBlueReader->getValue() : 0; + return (r << 16) | (g << 8) | b; + } else { + return -1; + } + } }; #endif @@ -1979,23 +2085,23 @@ class APIUI : public PathBuilder, public Meta, public UI // FAUST Generated Code //---------------------------------------------------------------------------- - #ifndef FAUSTFLOAT #define FAUSTFLOAT float -#endif +#endif + +#include #include #include #include -#include -#ifndef FAUSTCLASS +#ifndef FAUSTCLASS #define FAUSTCLASS monitordsp #endif -#ifdef __APPLE__ +#ifdef __APPLE__ #define exp10f __exp10f -#define exp10 __exp10 +#define exp10 __exp10 #endif #if defined(_WIN32) @@ -2004,113 +2110,115 @@ class APIUI : public PathBuilder, public Meta, public UI #define RESTRICT __restrict__ #endif - -class monitordsp : public dsp { - - private: - - FAUSTFLOAT fHslider0; - FAUSTFLOAT fCheckbox0; - int fSampleRate; - float fConst0; - float fConst1; - float fRec0[2]; - - public: - - void metadata(Meta* m) { - m->declare("author", "Dominick Hing, adapted from 'Volume Control' by Matt Horton"); - m->declare("basics.lib/name", "Faust Basic Element Library"); - m->declare("basics.lib/version", "0.9"); - m->declare("compile_options", "-a faust2header.cpp -lang cpp -i -inpl -cn monitordsp -es 1 -mcd 16 -single -ftz 0"); - m->declare("description", "Volume Control Faust Plugin for JackTrip, based on Faust examples"); - m->declare("filename", "monitordsp.dsp"); - m->declare("license", "MIT Style STK-4.2"); - m->declare("maths.lib/author", "GRAME"); - m->declare("maths.lib/copyright", "GRAME"); - m->declare("maths.lib/license", "LGPL with exception"); - m->declare("maths.lib/name", "Faust Math Library"); - m->declare("maths.lib/version", "2.5"); - m->declare("name", "monitor"); - m->declare("platform.lib/name", "Generic Platform Library"); - m->declare("platform.lib/version", "0.3"); - m->declare("signals.lib/name", "Faust Signal Routing Library"); - m->declare("signals.lib/version", "0.3"); - m->declare("version", "1.0"); - } - - virtual int getNumInputs() { - return 2; - } - virtual int getNumOutputs() { - return 1; - } - - static void classInit(int /*sample_rate*/) { - } - - virtual void instanceConstants(int sample_rate) { - fSampleRate = sample_rate; - fConst0 = 44.1f / std::min(1.92e+05f, std::max(1.0f, float(fSampleRate))); - fConst1 = 1.0f - fConst0; - } - - virtual void instanceResetUserInterface() { - fHslider0 = FAUSTFLOAT(0.0f); - fCheckbox0 = FAUSTFLOAT(0.0f); - } - - virtual void instanceClear() { - for (int l0 = 0; l0 < 2; l0 = l0 + 1) { - fRec0[l0] = 0.0f; - } - } - - virtual void init(int sample_rate) { - classInit(sample_rate); - instanceInit(sample_rate); - } - virtual void instanceInit(int sample_rate) { - instanceConstants(sample_rate); - instanceResetUserInterface(); - instanceClear(); - } - - virtual monitordsp* clone() { - return new monitordsp(); - } - - virtual int getSampleRate() { - return fSampleRate; - } - - virtual void buildUserInterface(UI* ui_interface) { - ui_interface->openVerticalBox("Monitor"); - ui_interface->declare(&fHslider0, "0", ""); - ui_interface->addHorizontalSlider("Volume", &fHslider0, FAUSTFLOAT(0.0f), FAUSTFLOAT(-4e+01f), FAUSTFLOAT(0.0f), FAUSTFLOAT(0.1f)); - ui_interface->declare(&fCheckbox0, "1", ""); - ui_interface->addCheckButton("Mute", &fCheckbox0); - ui_interface->closeBox(); - } - - virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { - FAUSTFLOAT* input0 = inputs[0]; - FAUSTFLOAT* input1 = inputs[1]; - FAUSTFLOAT* output0 = outputs[0]; - float fSlow0 = float(fHslider0); - int iSlow1 = fSlow0 == -4e+01f; - int iSlow2 = int(float(fCheckbox0)); - float fSlow3 = fConst0 * std::pow(1e+01f, 0.05f * fSlow0); - for (int i0 = 0; i0 < count; i0 = i0 + 1) { - float fTemp0 = float(input1[i0]); - float fTemp1 = float(input0[i0]); - fRec0[0] = fSlow3 + fConst1 * fRec0[1]; - output0[i0] = FAUSTFLOAT(fTemp0 + ((iSlow1) ? 0.0f : ((iSlow2) ? 0.0f : fTemp1 * fRec0[0]))); - fRec0[1] = fRec0[0]; - } - } - +class monitordsp : public dsp +{ + private: + FAUSTFLOAT fHslider0; + FAUSTFLOAT fCheckbox0; + int fSampleRate; + float fConst0; + float fConst1; + float fRec0[2]; + + public: + void metadata(Meta* m) + { + m->declare("author", + "Dominick Hing, adapted from 'Volume Control' by Matt Horton"); + m->declare("basics.lib/name", "Faust Basic Element Library"); + m->declare("basics.lib/version", "0.9"); + m->declare("compile_options", + "-a faust2header.cpp -lang cpp -i -inpl -cn monitordsp -es 1 -mcd 16 " + "-single -ftz 0"); + m->declare("description", + "Volume Control Faust Plugin for JackTrip, based on Faust examples"); + m->declare("filename", "monitordsp.dsp"); + m->declare("license", "MIT Style STK-4.2"); + m->declare("maths.lib/author", "GRAME"); + m->declare("maths.lib/copyright", "GRAME"); + m->declare("maths.lib/license", "LGPL with exception"); + m->declare("maths.lib/name", "Faust Math Library"); + m->declare("maths.lib/version", "2.5"); + m->declare("name", "monitor"); + m->declare("platform.lib/name", "Generic Platform Library"); + m->declare("platform.lib/version", "0.3"); + m->declare("signals.lib/name", "Faust Signal Routing Library"); + m->declare("signals.lib/version", "0.3"); + m->declare("version", "1.0"); + } + + virtual int getNumInputs() { return 2; } + virtual int getNumOutputs() { return 1; } + + static void classInit(int /*sample_rate*/) {} + + virtual void instanceConstants(int sample_rate) + { + fSampleRate = sample_rate; + fConst0 = + 44.1f / std::min(1.92e+05f, std::max(1.0f, float(fSampleRate))); + fConst1 = 1.0f - fConst0; + } + + virtual void instanceResetUserInterface() + { + fHslider0 = FAUSTFLOAT(0.0f); + fCheckbox0 = FAUSTFLOAT(0.0f); + } + + virtual void instanceClear() + { + for (int l0 = 0; l0 < 2; l0 = l0 + 1) { + fRec0[l0] = 0.0f; + } + } + + virtual void init(int sample_rate) + { + classInit(sample_rate); + instanceInit(sample_rate); + } + virtual void instanceInit(int sample_rate) + { + instanceConstants(sample_rate); + instanceResetUserInterface(); + instanceClear(); + } + + virtual monitordsp* clone() { return new monitordsp(); } + + virtual int getSampleRate() { return fSampleRate; } + + virtual void buildUserInterface(UI* ui_interface) + { + ui_interface->openVerticalBox("Monitor"); + ui_interface->declare(&fHslider0, "0", ""); + ui_interface->addHorizontalSlider("Volume", &fHslider0, FAUSTFLOAT(0.0f), + FAUSTFLOAT(-4e+01f), FAUSTFLOAT(0.0f), + FAUSTFLOAT(0.1f)); + ui_interface->declare(&fCheckbox0, "1", ""); + ui_interface->addCheckButton("Mute", &fCheckbox0); + ui_interface->closeBox(); + } + + virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) + { + FAUSTFLOAT* input0 = inputs[0]; + FAUSTFLOAT* input1 = inputs[1]; + FAUSTFLOAT* output0 = outputs[0]; + float fSlow0 = float(fHslider0); + int iSlow1 = fSlow0 == -4e+01f; + int iSlow2 = int(float(fCheckbox0)); + float fSlow3 = fConst0 * std::pow(1e+01f, 0.05f * fSlow0); + for (int i0 = 0; i0 < count; i0 = i0 + 1) { + float fTemp0 = float(input1[i0]); + float fTemp1 = float(input0[i0]); + fRec0[0] = fSlow3 + fConst1 * fRec0[1]; + output0[i0] = FAUSTFLOAT( + fTemp0 + ((iSlow1) ? 0.0f : ((iSlow2) ? 0.0f : fTemp1 * fRec0[0]))); + fRec0[1] = fRec0[0]; + } + } }; - #endif diff --git a/src/stereotomonodsp.h b/src/stereotomonodsp.h index 40a1403..1633a9f 100644 --- a/src/stereotomonodsp.h +++ b/src/stereotomonodsp.h @@ -4,11 +4,12 @@ license: "MIT Style STK-4.2" name: "stereo-to-mono" version: "1.0" Code generated with Faust 2.50.6 (https://faust.grame.fr) -Compilation options: -a faust2header.cpp -lang cpp -i -inpl -cn stereotomonodsp -es 1 -mcd 16 -single -ftz 0 +Compilation options: -a faust2header.cpp -lang cpp -i -inpl -cn stereotomonodsp -es 1 -mcd +16 -single -ftz 0 ------------------------------------------------------------ */ -#ifndef __stereotomonodsp_H__ -#define __stereotomonodsp_H__ +#ifndef __stereotomonodsp_H__ +#define __stereotomonodsp_H__ // NOTE: ANY INCLUDE-GUARD HERE MUST BE DERIVED FROM THE CLASS NAME // @@ -25,16 +26,16 @@ Compilation options: -a faust2header.cpp -lang cpp -i -inpl -cn stereotomonodsp it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + EXCEPTION : As a special exception, you may create a larger work that contains this FAUST architecture section and distribute that work under terms of your choice, so long as this FAUST @@ -73,29 +74,29 @@ Compilation options: -a faust2header.cpp -lang cpp -i -inpl -cn stereotomonodsp #define FAUSTVERSION "2.50.6" -// Use FAUST_API for code that is part of the external API but is also compiled in faust and libfaust -// Use LIBFAUST_API for code that is compiled in faust and libfaust +// Use FAUST_API for code that is part of the external API but is also compiled in faust +// and libfaust Use LIBFAUST_API for code that is compiled in faust and libfaust #ifdef _WIN32 - #pragma warning (disable: 4251) - #ifdef FAUST_EXE - #define FAUST_API - #define LIBFAUST_API - #elif FAUST_LIB - #define FAUST_API __declspec(dllexport) - #define LIBFAUST_API __declspec(dllexport) - #else - #define FAUST_API - #define LIBFAUST_API - #endif +#pragma warning(disable : 4251) +#ifdef FAUST_EXE +#define FAUST_API +#define LIBFAUST_API +#elif FAUST_LIB +#define FAUST_API __declspec(dllexport) +#define LIBFAUST_API __declspec(dllexport) +#else +#define FAUST_API +#define LIBFAUST_API +#endif +#else +#ifdef FAUST_EXE +#define FAUST_API +#define LIBFAUST_API #else - #ifdef FAUST_EXE - #define FAUST_API - #define LIBFAUST_API - #else - #define FAUST_API __attribute__((visibility("default"))) - #define LIBFAUST_API __attribute__((visibility("default"))) - #endif +#define FAUST_API __attribute__((visibility("default"))) +#define LIBFAUST_API __attribute__((visibility("default"))) +#endif #endif #endif @@ -112,15 +113,14 @@ struct FAUST_API Meta; */ struct FAUST_API dsp_memory_manager { - virtual ~dsp_memory_manager() {} - + /** * Inform the Memory Manager with the number of expected memory zones. * @param count - the number of expected memory zones */ virtual void begin(size_t /* count */) {} - + /** * Give the Memory Manager information on a given memory zone. * @param size - the size in bytes of the memory zone @@ -128,151 +128,167 @@ struct FAUST_API dsp_memory_manager { * @param writes - the number of Write access to the zone used to compute one frame */ virtual void info(size_t /* size */, size_t /* reads */, size_t /* writes */) {} - + /** * Inform the Memory Manager that all memory zones have been described, * to possibly start a 'compute the best allocation strategy' step. */ virtual void end() {} - + /** * Allocate a memory zone. * @param size - the memory zone size in bytes */ virtual void* allocate(size_t size) = 0; - + /** * Destroy a memory zone. * @param ptr - the memory zone pointer to be deallocated */ virtual void destroy(void* ptr) = 0; - -}; - -/** -* Signal processor definition. -*/ - -class FAUST_API dsp { - - public: - - dsp() {} - virtual ~dsp() {} - - /* Return instance number of audio inputs */ - virtual int getNumInputs() = 0; - - /* Return instance number of audio outputs */ - virtual int getNumOutputs() = 0; - - /** - * Trigger the ui_interface parameter with instance specific calls - * to 'openTabBox', 'addButton', 'addVerticalSlider'... in order to build the UI. - * - * @param ui_interface - the user interface builder - */ - virtual void buildUserInterface(UI* ui_interface) = 0; - - /* Return the sample rate currently used by the instance */ - virtual int getSampleRate() = 0; - - /** - * Global init, calls the following methods: - * - static class 'classInit': static tables initialization - * - 'instanceInit': constants and instance state initialization - * - * @param sample_rate - the sampling rate in Hz - */ - virtual void init(int sample_rate) = 0; - - /** - * Init instance state - * - * @param sample_rate - the sampling rate in Hz - */ - virtual void instanceInit(int sample_rate) = 0; - - /** - * Init instance constant state - * - * @param sample_rate - the sampling rate in Hz - */ - virtual void instanceConstants(int sample_rate) = 0; - - /* Init default control parameters values */ - virtual void instanceResetUserInterface() = 0; - - /* Init instance state (like delay lines...) but keep the control parameter values */ - virtual void instanceClear() = 0; - - /** - * Return a clone of the instance. - * - * @return a copy of the instance on success, otherwise a null pointer. - */ - virtual dsp* clone() = 0; - - /** - * Trigger the Meta* parameter with instance specific calls to 'declare' (key, value) metadata. - * - * @param m - the Meta* meta user - */ - virtual void metadata(Meta* m) = 0; - - /** - * DSP instance computation, to be called with successive in/out audio buffers. - * - * @param count - the number of frames to compute - * @param inputs - the input audio buffers as an array of non-interleaved FAUSTFLOAT samples (eiher float, double or quad) - * @param outputs - the output audio buffers as an array of non-interleaved FAUSTFLOAT samples (eiher float, double or quad) - * - */ - virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) = 0; - - /** - * DSP instance computation: alternative method to be used by subclasses. - * - * @param date_usec - the timestamp in microsec given by audio driver. - * @param count - the number of frames to compute - * @param inputs - the input audio buffers as an array of non-interleaved FAUSTFLOAT samples (either float, double or quad) - * @param outputs - the output audio buffers as an array of non-interleaved FAUSTFLOAT samples (either float, double or quad) - * - */ - virtual void compute(double /*date_usec*/, int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { compute(count, inputs, outputs); } - }; /** - * Generic DSP decorator. + * Signal processor definition. */ -class FAUST_API decorator_dsp : public dsp { +class FAUST_API dsp +{ + public: + dsp() {} + virtual ~dsp() {} + + /* Return instance number of audio inputs */ + virtual int getNumInputs() = 0; + + /* Return instance number of audio outputs */ + virtual int getNumOutputs() = 0; + + /** + * Trigger the ui_interface parameter with instance specific calls + * to 'openTabBox', 'addButton', 'addVerticalSlider'... in order to build the UI. + * + * @param ui_interface - the user interface builder + */ + virtual void buildUserInterface(UI* ui_interface) = 0; + + /* Return the sample rate currently used by the instance */ + virtual int getSampleRate() = 0; + + /** + * Global init, calls the following methods: + * - static class 'classInit': static tables initialization + * - 'instanceInit': constants and instance state initialization + * + * @param sample_rate - the sampling rate in Hz + */ + virtual void init(int sample_rate) = 0; + + /** + * Init instance state + * + * @param sample_rate - the sampling rate in Hz + */ + virtual void instanceInit(int sample_rate) = 0; + + /** + * Init instance constant state + * + * @param sample_rate - the sampling rate in Hz + */ + virtual void instanceConstants(int sample_rate) = 0; - protected: + /* Init default control parameters values */ + virtual void instanceResetUserInterface() = 0; - dsp* fDSP; + /* Init instance state (like delay lines...) but keep the control parameter values */ + virtual void instanceClear() = 0; - public: + /** + * Return a clone of the instance. + * + * @return a copy of the instance on success, otherwise a null pointer. + */ + virtual dsp* clone() = 0; - decorator_dsp(dsp* dsp = nullptr):fDSP(dsp) {} - virtual ~decorator_dsp() { delete fDSP; } + /** + * Trigger the Meta* parameter with instance specific calls to 'declare' (key, value) + * metadata. + * + * @param m - the Meta* meta user + */ + virtual void metadata(Meta* m) = 0; - virtual int getNumInputs() { return fDSP->getNumInputs(); } - virtual int getNumOutputs() { return fDSP->getNumOutputs(); } - virtual void buildUserInterface(UI* ui_interface) { fDSP->buildUserInterface(ui_interface); } - virtual int getSampleRate() { return fDSP->getSampleRate(); } - virtual void init(int sample_rate) { fDSP->init(sample_rate); } - virtual void instanceInit(int sample_rate) { fDSP->instanceInit(sample_rate); } - virtual void instanceConstants(int sample_rate) { fDSP->instanceConstants(sample_rate); } - virtual void instanceResetUserInterface() { fDSP->instanceResetUserInterface(); } - virtual void instanceClear() { fDSP->instanceClear(); } - virtual decorator_dsp* clone() { return new decorator_dsp(fDSP->clone()); } - virtual void metadata(Meta* m) { fDSP->metadata(m); } - // Beware: subclasses usually have to overload the two 'compute' methods - virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { fDSP->compute(count, inputs, outputs); } - virtual void compute(double date_usec, int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { fDSP->compute(date_usec, count, inputs, outputs); } - + /** + * DSP instance computation, to be called with successive in/out audio buffers. + * + * @param count - the number of frames to compute + * @param inputs - the input audio buffers as an array of non-interleaved FAUSTFLOAT + * samples (eiher float, double or quad) + * @param outputs - the output audio buffers as an array of non-interleaved FAUSTFLOAT + * samples (eiher float, double or quad) + * + */ + virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) = 0; + + /** + * DSP instance computation: alternative method to be used by subclasses. + * + * @param date_usec - the timestamp in microsec given by audio driver. + * @param count - the number of frames to compute + * @param inputs - the input audio buffers as an array of non-interleaved FAUSTFLOAT + * samples (either float, double or quad) + * @param outputs - the output audio buffers as an array of non-interleaved FAUSTFLOAT + * samples (either float, double or quad) + * + */ + virtual void compute(double /*date_usec*/, int count, FAUSTFLOAT** inputs, + FAUSTFLOAT** outputs) + { + compute(count, inputs, outputs); + } +}; + +/** + * Generic DSP decorator. + */ + +class FAUST_API decorator_dsp : public dsp +{ + protected: + dsp* fDSP; + + public: + decorator_dsp(dsp* dsp = nullptr) : fDSP(dsp) {} + virtual ~decorator_dsp() { delete fDSP; } + + virtual int getNumInputs() { return fDSP->getNumInputs(); } + virtual int getNumOutputs() { return fDSP->getNumOutputs(); } + virtual void buildUserInterface(UI* ui_interface) + { + fDSP->buildUserInterface(ui_interface); + } + virtual int getSampleRate() { return fDSP->getSampleRate(); } + virtual void init(int sample_rate) { fDSP->init(sample_rate); } + virtual void instanceInit(int sample_rate) { fDSP->instanceInit(sample_rate); } + virtual void instanceConstants(int sample_rate) + { + fDSP->instanceConstants(sample_rate); + } + virtual void instanceResetUserInterface() { fDSP->instanceResetUserInterface(); } + virtual void instanceClear() { fDSP->instanceClear(); } + virtual decorator_dsp* clone() { return new decorator_dsp(fDSP->clone()); } + virtual void metadata(Meta* m) { fDSP->metadata(m); } + // Beware: subclasses usually have to overload the two 'compute' methods + virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) + { + fDSP->compute(count, inputs, outputs); + } + virtual void compute(double date_usec, int count, FAUSTFLOAT** inputs, + FAUSTFLOAT** outputs) + { + fDSP->compute(date_usec, count, inputs, outputs); + } }; /** @@ -280,86 +296,77 @@ class FAUST_API decorator_dsp : public dsp { * to create DSP instances from a compiled DSP program. */ -class FAUST_API dsp_factory { - - protected: - - // So that to force sub-classes to use deleteDSPFactory(dsp_factory* factory); - virtual ~dsp_factory() {} - - public: - - virtual std::string getName() = 0; - virtual std::string getSHAKey() = 0; - virtual std::string getDSPCode() = 0; - virtual std::string getCompileOptions() = 0; - virtual std::vector getLibraryList() = 0; - virtual std::vector getIncludePathnames() = 0; - - virtual dsp* createDSPInstance() = 0; - - virtual void setMemoryManager(dsp_memory_manager* manager) = 0; - virtual dsp_memory_manager* getMemoryManager() = 0; - +class FAUST_API dsp_factory +{ + protected: + // So that to force sub-classes to use deleteDSPFactory(dsp_factory* factory); + virtual ~dsp_factory() {} + + public: + virtual std::string getName() = 0; + virtual std::string getSHAKey() = 0; + virtual std::string getDSPCode() = 0; + virtual std::string getCompileOptions() = 0; + virtual std::vector getLibraryList() = 0; + virtual std::vector getIncludePathnames() = 0; + + virtual dsp* createDSPInstance() = 0; + + virtual void setMemoryManager(dsp_memory_manager* manager) = 0; + virtual dsp_memory_manager* getMemoryManager() = 0; }; // Denormal handling -#if defined (__SSE__) +#if defined(__SSE__) #include #endif -class FAUST_API ScopedNoDenormals { - - private: - - intptr_t fpsr = 0; - - void setFpStatusRegister(intptr_t fpsr_aux) noexcept - { - #if defined (__arm64__) || defined (__aarch64__) - asm volatile("msr fpcr, %0" : : "ri" (fpsr_aux)); - #elif defined (__SSE__) - // The volatile keyword here is needed to workaround a bug in AppleClang 13.0 - // which aggressively optimises away the variable otherwise - volatile uint32_t fpsr_w = static_cast(fpsr_aux); - _mm_setcsr(fpsr_w); - #endif - } - - void getFpStatusRegister() noexcept - { - #if defined (__arm64__) || defined (__aarch64__) - asm volatile("mrs %0, fpcr" : "=r" (fpsr)); - #elif defined (__SSE__) - fpsr = static_cast(_mm_getcsr()); - #endif - } - - public: - - ScopedNoDenormals() noexcept - { - #if defined (__arm64__) || defined (__aarch64__) - intptr_t mask = (1 << 24 /* FZ */); - #elif defined (__SSE__) - #if defined (__SSE2__) - intptr_t mask = 0x8040; - #else - intptr_t mask = 0x8000; - #endif - #else - intptr_t mask = 0x0000; - #endif - getFpStatusRegister(); - setFpStatusRegister(fpsr | mask); - } - - ~ScopedNoDenormals() noexcept - { - setFpStatusRegister(fpsr); - } +class FAUST_API ScopedNoDenormals +{ + private: + intptr_t fpsr = 0; + + void setFpStatusRegister(intptr_t fpsr_aux) noexcept + { +#if defined(__arm64__) || defined(__aarch64__) + asm volatile("msr fpcr, %0" : : "ri"(fpsr_aux)); +#elif defined(__SSE__) + // The volatile keyword here is needed to workaround a bug in AppleClang 13.0 + // which aggressively optimises away the variable otherwise + volatile uint32_t fpsr_w = static_cast(fpsr_aux); + _mm_setcsr(fpsr_w); +#endif + } + + void getFpStatusRegister() noexcept + { +#if defined(__arm64__) || defined(__aarch64__) + asm volatile("mrs %0, fpcr" : "=r"(fpsr)); +#elif defined(__SSE__) + fpsr = static_cast(_mm_getcsr()); +#endif + } + + public: + ScopedNoDenormals() noexcept + { +#if defined(__arm64__) || defined(__aarch64__) + intptr_t mask = (1 << 24 /* FZ */); +#elif defined(__SSE__) +#if defined(__SSE2__) + intptr_t mask = 0x8040; +#else + intptr_t mask = 0x8000; +#endif +#else + intptr_t mask = 0x0000; +#endif + getFpStatusRegister(); + setFpStatusRegister(fpsr | mask); + } + ~ScopedNoDenormals() noexcept { setFpStatusRegister(fpsr); } }; #define AVOIDDENORMALS ScopedNoDenormals ftz_scope; @@ -394,11 +401,12 @@ architecture section is not modified. #ifndef API_UI_H #define API_UI_H +#include + +#include #include #include #include -#include -#include /************************** BEGIN meta.h ******************************* FAUST Architecture File @@ -408,16 +416,16 @@ architecture section is not modified. it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + EXCEPTION : As a special exception, you may create a larger work that contains this FAUST architecture section and distribute that work under terms of your choice, so long as this FAUST @@ -427,9 +435,9 @@ architecture section is not modified. #ifndef __meta__ #define __meta__ - /** - The base class of Meta handler to be used in dsp::metadata(Meta* m) method to retrieve (key, value) metadata. + The base class of Meta handler to be used in dsp::metadata(Meta* m) method to retrieve + (key, value) metadata. */ struct FAUST_API Meta { virtual ~Meta() {} @@ -446,16 +454,16 @@ struct FAUST_API Meta { it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + EXCEPTION : As a special exception, you may create a larger work that contains this FAUST architecture section and distribute that work under terms of your choice, so long as this FAUST @@ -465,7 +473,6 @@ struct FAUST_API Meta { #ifndef __UI_H__ #define __UI_H__ - #ifndef FAUSTFLOAT #define FAUSTFLOAT float #endif @@ -479,40 +486,47 @@ struct FAUST_API Meta { struct Soundfile; -template +template struct FAUST_API UIReal { - UIReal() {} virtual ~UIReal() {} - + // -- widget's layouts - - virtual void openTabBox(const char* label) = 0; + + virtual void openTabBox(const char* label) = 0; virtual void openHorizontalBox(const char* label) = 0; - virtual void openVerticalBox(const char* label) = 0; - virtual void closeBox() = 0; - + virtual void openVerticalBox(const char* label) = 0; + virtual void closeBox() = 0; + // -- active widgets - - virtual void addButton(const char* label, REAL* zone) = 0; + + virtual void addButton(const char* label, REAL* zone) = 0; virtual void addCheckButton(const char* label, REAL* zone) = 0; - virtual void addVerticalSlider(const char* label, REAL* zone, REAL init, REAL min, REAL max, REAL step) = 0; - virtual void addHorizontalSlider(const char* label, REAL* zone, REAL init, REAL min, REAL max, REAL step) = 0; - virtual void addNumEntry(const char* label, REAL* zone, REAL init, REAL min, REAL max, REAL step) = 0; - + virtual void addVerticalSlider(const char* label, REAL* zone, REAL init, REAL min, + REAL max, REAL step) = 0; + virtual void addHorizontalSlider(const char* label, REAL* zone, REAL init, REAL min, + REAL max, REAL step) = 0; + virtual void addNumEntry(const char* label, REAL* zone, REAL init, REAL min, REAL max, + REAL step) = 0; + // -- passive widgets - - virtual void addHorizontalBargraph(const char* label, REAL* zone, REAL min, REAL max) = 0; - virtual void addVerticalBargraph(const char* label, REAL* zone, REAL min, REAL max) = 0; - + + virtual void addHorizontalBargraph(const char* label, REAL* zone, REAL min, + REAL max) = 0; + virtual void addVerticalBargraph(const char* label, REAL* zone, REAL min, + REAL max) = 0; + // -- soundfiles - - virtual void addSoundfile(const char* label, const char* filename, Soundfile** sf_zone) = 0; - + + virtual void addSoundfile(const char* label, const char* filename, + Soundfile** sf_zone) = 0; + // -- metadata declarations - - virtual void declare(REAL* /* zone */, const char* /* key */, const char* /* val */) {} - + + virtual void declare(REAL* /* zone */, const char* /* key */, const char* /* val */) + { + } + // To be used by LLVM client virtual int sizeOfFAUSTFLOAT() { return sizeof(FAUSTFLOAT); } }; @@ -532,16 +546,16 @@ struct FAUST_API UI : public UIReal { it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + EXCEPTION : As a special exception, you may create a larger work that contains this FAUST architecture section and distribute that work under terms of your choice, so long as this FAUST @@ -551,187 +565,199 @@ struct FAUST_API UI : public UIReal { #ifndef __PathBuilder__ #define __PathBuilder__ -#include -#include -#include -#include #include +#include #include - +#include +#include +#include /******************************************************************************* * PathBuilder : Faust User Interface * Helper class to build complete hierarchical path for UI items. ******************************************************************************/ -class FAUST_API PathBuilder { - - protected: - - std::vector fControlsLevel; - std::vector fFullPaths; - std::map fFull2Short; // filled by computeShortNames() - - /** - * @brief check if a character is acceptable for an ID - * - * @param c - * @return true is the character is acceptable for an ID - */ - bool isIDChar(char c) const - { - return ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) || ((c >= '0') && (c <= '9')); - } - - /** - * @brief remove all "/0x00" parts - * - * @param src - * @return modified string - */ - std::string remove0x00(const std::string& src) const - { - return std::regex_replace(src, std::regex("/0x00"), ""); - } - - /** - * @brief replace all non ID char with '_' (one '_' may replace several non ID char) - * - * @param src - * @return modified string - */ - std::string str2ID(const std::string& src) const - { - std::string dst; - bool need_underscore = false; - for (char c : src) { - if (isIDChar(c) || (c == '/')) { - if (need_underscore) { - dst.push_back('_'); - need_underscore = false; - } - dst.push_back(c); - } else { - need_underscore = true; +class FAUST_API PathBuilder +{ + protected: + std::vector fControlsLevel; + std::vector fFullPaths; + std::map fFull2Short; // filled by computeShortNames() + + /** + * @brief check if a character is acceptable for an ID + * + * @param c + * @return true is the character is acceptable for an ID + */ + bool isIDChar(char c) const + { + return ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) + || ((c >= '0') && (c <= '9')); + } + + /** + * @brief remove all "/0x00" parts + * + * @param src + * @return modified string + */ + std::string remove0x00(const std::string& src) const + { + return std::regex_replace(src, std::regex("/0x00"), ""); + } + + /** + * @brief replace all non ID char with '_' (one '_' may replace several non ID char) + * + * @param src + * @return modified string + */ + std::string str2ID(const std::string& src) const + { + std::string dst; + bool need_underscore = false; + for (char c : src) { + if (isIDChar(c) || (c == '/')) { + if (need_underscore) { + dst.push_back('_'); + need_underscore = false; } + dst.push_back(c); + } else { + need_underscore = true; } - return dst; } - - /** - * @brief Keep only the last n slash-parts - * - * @param src - * @param n : 1 indicates the last slash-part - * @return modified string - */ - std::string cut(const std::string& src, int n) const - { - std::string rdst; - for (int i = int(src.length())-1; i >= 0; i--) { - char c = src[i]; - if (c != '/') { - rdst.push_back(c); - } else if (n == 1) { - std::string dst; - for (int j = int(rdst.length())-1; j >= 0; j--) { - dst.push_back(rdst[j]); - } - return dst; - } else { - n--; - rdst.push_back(c); + return dst; + } + + /** + * @brief Keep only the last n slash-parts + * + * @param src + * @param n : 1 indicates the last slash-part + * @return modified string + */ + std::string cut(const std::string& src, int n) const + { + std::string rdst; + for (int i = int(src.length()) - 1; i >= 0; i--) { + char c = src[i]; + if (c != '/') { + rdst.push_back(c); + } else if (n == 1) { + std::string dst; + for (int j = int(rdst.length()) - 1; j >= 0; j--) { + dst.push_back(rdst[j]); } + return dst; + } else { + n--; + rdst.push_back(c); } - return src; } - - void addFullPath(const std::string& label) { fFullPaths.push_back(buildPath(label)); } - - /** - * @brief Compute the mapping between full path and short names - */ - void computeShortNames() - { - std::vector uniquePaths; // all full paths transformed but made unique with a prefix - std::map unique2full; // all full paths transformed but made unique with a prefix - char num_buffer[16]; - int pnum = 0; - - for (const auto& s : fFullPaths) { - sprintf(num_buffer, "%d", pnum++); - std::string u = "/P" + std::string(num_buffer) + str2ID(remove0x00(s)); - uniquePaths.push_back(u); - unique2full[u] = s; // remember the full path associated to a unique path - } - - std::map uniquePath2level; // map path to level - for (const auto& s : uniquePaths) uniquePath2level[s] = 1; // we init all levels to 1 - bool have_collisions = true; - - while (have_collisions) { - // compute collision list - std::set collisionSet; - std::map short2full; - have_collisions = false; - for (const auto& it : uniquePath2level) { - std::string u = it.first; - int n = it.second; - std::string shortName = cut(u, n); - auto p = short2full.find(shortName); - if (p == short2full.end()) { - // no collision - short2full[shortName] = u; - } else { - // we have a collision, add the two paths to the collision set - have_collisions = true; - collisionSet.insert(u); - collisionSet.insert(p->second); - } - } - for (const auto& s : collisionSet) uniquePath2level[s]++; // increase level of colliding path - } - + return src; + } + + void addFullPath(const std::string& label) { fFullPaths.push_back(buildPath(label)); } + + /** + * @brief Compute the mapping between full path and short names + */ + void computeShortNames() + { + std::vector + uniquePaths; // all full paths transformed but made unique with a prefix + std::map + unique2full; // all full paths transformed but made unique with a prefix + char num_buffer[16]; + int pnum = 0; + + for (const auto& s : fFullPaths) { + sprintf(num_buffer, "%d", pnum++); + std::string u = "/P" + std::string(num_buffer) + str2ID(remove0x00(s)); + uniquePaths.push_back(u); + unique2full[u] = s; // remember the full path associated to a unique path + } + + std::map uniquePath2level; // map path to level + for (const auto& s : uniquePaths) + uniquePath2level[s] = 1; // we init all levels to 1 + bool have_collisions = true; + + while (have_collisions) { + // compute collision list + std::set collisionSet; + std::map short2full; + have_collisions = false; for (const auto& it : uniquePath2level) { - std::string u = it.first; - int n = it.second; - std::string shortName = replaceCharList(cut(u, n), {'/'}, '_'); - fFull2Short[unique2full[u]] = shortName; + std::string u = it.first; + int n = it.second; + std::string shortName = cut(u, n); + auto p = short2full.find(shortName); + if (p == short2full.end()) { + // no collision + short2full[shortName] = u; + } else { + // we have a collision, add the two paths to the collision set + have_collisions = true; + collisionSet.insert(u); + collisionSet.insert(p->second); + } } + for (const auto& s : collisionSet) + uniquePath2level[s]++; // increase level of colliding path } - - std::string replaceCharList(const std::string& str, const std::vector& ch1, char ch2) - { - auto beg = ch1.begin(); - auto end = ch1.end(); - std::string res = str; - for (size_t i = 0; i < str.length(); ++i) { - if (std::find(beg, end, str[i]) != end) res[i] = ch2; - } - return res; + + for (const auto& it : uniquePath2level) { + std::string u = it.first; + int n = it.second; + std::string shortName = replaceCharList(cut(u, n), {'/'}, '_'); + fFull2Short[unique2full[u]] = shortName; } - - public: - - PathBuilder() {} - virtual ~PathBuilder() {} - - // Return true for the first level of groups - bool pushLabel(const std::string& label) { fControlsLevel.push_back(label); return fControlsLevel.size() == 1;} - - // Return true for the last level of groups - bool popLabel() { fControlsLevel.pop_back(); return fControlsLevel.size() == 0; } - - std::string buildPath(const std::string& label) - { - std::string res = "/"; - for (size_t i = 0; i < fControlsLevel.size(); i++) { - res = res + fControlsLevel[i] + "/"; - } - res += label; - return replaceCharList(res, {' ', '#', '*', ',', '?', '[', ']', '{', '}', '(', ')'}, '_'); + } + + std::string replaceCharList(const std::string& str, const std::vector& ch1, + char ch2) + { + auto beg = ch1.begin(); + auto end = ch1.end(); + std::string res = str; + for (size_t i = 0; i < str.length(); ++i) { + if (std::find(beg, end, str[i]) != end) + res[i] = ch2; } - + return res; + } + + public: + PathBuilder() {} + virtual ~PathBuilder() {} + + // Return true for the first level of groups + bool pushLabel(const std::string& label) + { + fControlsLevel.push_back(label); + return fControlsLevel.size() == 1; + } + + // Return true for the last level of groups + bool popLabel() + { + fControlsLevel.pop_back(); + return fControlsLevel.size() == 0; + } + + std::string buildPath(const std::string& label) + { + std::string res = "/"; + for (size_t i = 0; i < fControlsLevel.size(); i++) { + res = res + fControlsLevel[i] + "/"; + } + res += label; + return replaceCharList( + res, {' ', '#', '*', ',', '?', '[', ']', '{', '}', '(', ')'}, '_'); + } }; #endif // __PathBuilder__ @@ -744,16 +770,16 @@ class FAUST_API PathBuilder { it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + EXCEPTION : As a special exception, you may create a larger work that contains this FAUST architecture section and distribute that work under terms of your choice, so long as this FAUST @@ -766,52 +792,53 @@ class FAUST_API PathBuilder { /*************************************************************************************** ValueConverter.h (GRAME, Copyright 2015-2019) - + Set of conversion objects used to map user interface values (for example a gui slider delivering values between 0 and 1) to faust values (for example a vslider between 20 and 20000) using a log scale. - + -- Utilities - + Range(lo,hi) : clip a value x between lo and hi - Interpolator(lo,hi,v1,v2) : Maps a value x between lo and hi to a value y between v1 and v2 - Interpolator3pt(lo,mi,hi,v1,vm,v2) : Map values between lo mid hi to values between v1 vm v2 - + Interpolator(lo,hi,v1,v2) : Maps a value x between lo and hi to a value y between v1 and +v2 Interpolator3pt(lo,mi,hi,v1,vm,v2) : Map values between lo mid hi to values between v1 +vm v2 + -- Value Converters - + ValueConverter::ui2faust(x) ValueConverter::faust2ui(x) - + -- ValueConverters used for sliders depending of the scale - + LinearValueConverter(umin, umax, fmin, fmax) LinearValueConverter2(lo, mi, hi, v1, vm, v2) using 2 segments LogValueConverter(umin, umax, fmin, fmax) ExpValueConverter(umin, umax, fmin, fmax) - + -- ValueConverters used for accelerometers based on 3 points - + AccUpConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 0 AccDownConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 1 AccUpDownConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 2 AccDownUpConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 3 - + -- lists of ZoneControl are used to implement accelerometers metadata for each axes - + ZoneControl(zone, valueConverter) : a zone with an accelerometer data converter - + -- ZoneReader are used to implement screencolor metadata - + ZoneReader(zone, valueConverter) : a zone with a data converter ****************************************************************************************/ +#include #include -#include // std::max + +#include // std::max #include #include -#include - //-------------------------------------------------------------------------------------- // Interpolator(lo,hi,v1,v2) @@ -822,458 +849,488 @@ class FAUST_API PathBuilder { // y = v1 - lo*coef + x*coef // y = offset + x*coef with offset = v1 - lo*coef //-------------------------------------------------------------------------------------- -class FAUST_API Interpolator { - - private: - - //-------------------------------------------------------------------------------------- - // Range(lo,hi) clip a value between lo and hi - //-------------------------------------------------------------------------------------- - struct Range - { - double fLo; - double fHi; - - Range(double x, double y) : fLo(std::min(x,y)), fHi(std::max(x,y)) {} - double operator()(double x) { return (xfHi) ? fHi : x; } - }; - - - Range fRange; - double fCoef; - double fOffset; - - public: - - Interpolator(double lo, double hi, double v1, double v2) : fRange(lo,hi) +class FAUST_API Interpolator +{ + private: + //-------------------------------------------------------------------------------------- + // Range(lo,hi) clip a value between lo and hi + //-------------------------------------------------------------------------------------- + struct Range { + double fLo; + double fHi; + + Range(double x, double y) + : fLo(std::min(x, y)), fHi(std::max(x, y)) { - if (hi != lo) { - // regular case - fCoef = (v2-v1)/(hi-lo); - fOffset = v1 - lo*fCoef; - } else { - // degenerate case, avoids division by zero - fCoef = 0; - fOffset = (v1+v2)/2; - } } - double operator()(double v) - { - double x = fRange(v); - return fOffset + x*fCoef; - } - - void getLowHigh(double& amin, double& amax) - { - amin = fRange.fLo; - amax = fRange.fHi; + double operator()(double x) { return (x < fLo) ? fLo : (x > fHi) ? fHi : x; } + }; + + Range fRange; + double fCoef; + double fOffset; + + public: + Interpolator(double lo, double hi, double v1, double v2) : fRange(lo, hi) + { + if (hi != lo) { + // regular case + fCoef = (v2 - v1) / (hi - lo); + fOffset = v1 - lo * fCoef; + } else { + // degenerate case, avoids division by zero + fCoef = 0; + fOffset = (v1 + v2) / 2; } + } + double operator()(double v) + { + double x = fRange(v); + return fOffset + x * fCoef; + } + + void getLowHigh(double& amin, double& amax) + { + amin = fRange.fLo; + amax = fRange.fHi; + } }; //-------------------------------------------------------------------------------------- // Interpolator3pt(lo,mi,hi,v1,vm,v2) // Map values between lo mid hi to values between v1 vm v2 //-------------------------------------------------------------------------------------- -class FAUST_API Interpolator3pt { - - private: - - Interpolator fSegment1; - Interpolator fSegment2; - double fMid; - - public: - - Interpolator3pt(double lo, double mi, double hi, double v1, double vm, double v2) : - fSegment1(lo, mi, v1, vm), - fSegment2(mi, hi, vm, v2), - fMid(mi) {} - double operator()(double x) { return (x < fMid) ? fSegment1(x) : fSegment2(x); } - - void getMappingValues(double& amin, double& amid, double& amax) - { - fSegment1.getLowHigh(amin, amid); - fSegment2.getLowHigh(amid, amax); - } +class FAUST_API Interpolator3pt +{ + private: + Interpolator fSegment1; + Interpolator fSegment2; + double fMid; + + public: + Interpolator3pt(double lo, double mi, double hi, double v1, double vm, double v2) + : fSegment1(lo, mi, v1, vm), fSegment2(mi, hi, vm, v2), fMid(mi) + { + } + double operator()(double x) { return (x < fMid) ? fSegment1(x) : fSegment2(x); } + + void getMappingValues(double& amin, double& amid, double& amax) + { + fSegment1.getLowHigh(amin, amid); + fSegment2.getLowHigh(amid, amax); + } }; //-------------------------------------------------------------------------------------- // Abstract ValueConverter class. Converts values between UI and Faust representations //-------------------------------------------------------------------------------------- -class FAUST_API ValueConverter { - - public: - - virtual ~ValueConverter() {} - virtual double ui2faust(double x) { return x; }; - virtual double faust2ui(double x) { return x; }; +class FAUST_API ValueConverter +{ + public: + virtual ~ValueConverter() {} + virtual double ui2faust(double x) { return x; }; + virtual double faust2ui(double x) { return x; }; }; //-------------------------------------------------------------------------------------- // A converter than can be updated //-------------------------------------------------------------------------------------- -class FAUST_API UpdatableValueConverter : public ValueConverter { - - protected: - - bool fActive; - - public: - - UpdatableValueConverter():fActive(true) - {} - virtual ~UpdatableValueConverter() - {} - - virtual void setMappingValues(double amin, double amid, double amax, double min, double init, double max) = 0; - virtual void getMappingValues(double& amin, double& amid, double& amax) = 0; - - void setActive(bool on_off) { fActive = on_off; } - bool getActive() { return fActive; } - +class FAUST_API UpdatableValueConverter : public ValueConverter +{ + protected: + bool fActive; + + public: + UpdatableValueConverter() : fActive(true) {} + virtual ~UpdatableValueConverter() {} + + virtual void setMappingValues(double amin, double amid, double amax, double min, + double init, double max) = 0; + virtual void getMappingValues(double& amin, double& amid, double& amax) = 0; + + void setActive(bool on_off) { fActive = on_off; } + bool getActive() { return fActive; } }; //-------------------------------------------------------------------------------------- // Linear conversion between ui and Faust values //-------------------------------------------------------------------------------------- -class FAUST_API LinearValueConverter : public ValueConverter { - - private: - - Interpolator fUI2F; - Interpolator fF2UI; - - public: - - LinearValueConverter(double umin, double umax, double fmin, double fmax) : - fUI2F(umin,umax,fmin,fmax), fF2UI(fmin,fmax,umin,umax) - {} - - LinearValueConverter() : fUI2F(0.,0.,0.,0.), fF2UI(0.,0.,0.,0.) - {} - virtual double ui2faust(double x) { return fUI2F(x); } - virtual double faust2ui(double x) { return fF2UI(x); } - +class FAUST_API LinearValueConverter : public ValueConverter +{ + private: + Interpolator fUI2F; + Interpolator fF2UI; + + public: + LinearValueConverter(double umin, double umax, double fmin, double fmax) + : fUI2F(umin, umax, fmin, fmax), fF2UI(fmin, fmax, umin, umax) + { + } + + LinearValueConverter() : fUI2F(0., 0., 0., 0.), fF2UI(0., 0., 0., 0.) {} + virtual double ui2faust(double x) { return fUI2F(x); } + virtual double faust2ui(double x) { return fF2UI(x); } }; //-------------------------------------------------------------------------------------- // Two segments linear conversion between ui and Faust values //-------------------------------------------------------------------------------------- -class FAUST_API LinearValueConverter2 : public UpdatableValueConverter { - - private: - - Interpolator3pt fUI2F; - Interpolator3pt fF2UI; - - public: - - LinearValueConverter2(double amin, double amid, double amax, double min, double init, double max) : - fUI2F(amin, amid, amax, min, init, max), fF2UI(min, init, max, amin, amid, amax) - {} - - LinearValueConverter2() : fUI2F(0.,0.,0.,0.,0.,0.), fF2UI(0.,0.,0.,0.,0.,0.) - {} - - virtual double ui2faust(double x) { return fUI2F(x); } - virtual double faust2ui(double x) { return fF2UI(x); } - - virtual void setMappingValues(double amin, double amid, double amax, double min, double init, double max) - { - fUI2F = Interpolator3pt(amin, amid, amax, min, init, max); - fF2UI = Interpolator3pt(min, init, max, amin, amid, amax); - } - - virtual void getMappingValues(double& amin, double& amid, double& amax) - { - fUI2F.getMappingValues(amin, amid, amax); - } - +class FAUST_API LinearValueConverter2 : public UpdatableValueConverter +{ + private: + Interpolator3pt fUI2F; + Interpolator3pt fF2UI; + + public: + LinearValueConverter2(double amin, double amid, double amax, double min, double init, + double max) + : fUI2F(amin, amid, amax, min, init, max), fF2UI(min, init, max, amin, amid, amax) + { + } + + LinearValueConverter2() : fUI2F(0., 0., 0., 0., 0., 0.), fF2UI(0., 0., 0., 0., 0., 0.) + { + } + + virtual double ui2faust(double x) { return fUI2F(x); } + virtual double faust2ui(double x) { return fF2UI(x); } + + virtual void setMappingValues(double amin, double amid, double amax, double min, + double init, double max) + { + fUI2F = Interpolator3pt(amin, amid, amax, min, init, max); + fF2UI = Interpolator3pt(min, init, max, amin, amid, amax); + } + + virtual void getMappingValues(double& amin, double& amid, double& amax) + { + fUI2F.getMappingValues(amin, amid, amax); + } }; //-------------------------------------------------------------------------------------- // Logarithmic conversion between ui and Faust values //-------------------------------------------------------------------------------------- -class FAUST_API LogValueConverter : public LinearValueConverter { - - public: - - LogValueConverter(double umin, double umax, double fmin, double fmax) : - LinearValueConverter(umin, umax, std::log(std::max(DBL_MIN, fmin)), std::log(std::max(DBL_MIN, fmax))) - {} - - virtual double ui2faust(double x) { return std::exp(LinearValueConverter::ui2faust(x)); } - virtual double faust2ui(double x) { return LinearValueConverter::faust2ui(std::log(std::max(x, DBL_MIN))); } - +class FAUST_API LogValueConverter : public LinearValueConverter +{ + public: + LogValueConverter(double umin, double umax, double fmin, double fmax) + : LinearValueConverter(umin, umax, std::log(std::max(DBL_MIN, fmin)), + std::log(std::max(DBL_MIN, fmax))) + { + } + + virtual double ui2faust(double x) + { + return std::exp(LinearValueConverter::ui2faust(x)); + } + virtual double faust2ui(double x) + { + return LinearValueConverter::faust2ui(std::log(std::max(x, DBL_MIN))); + } }; //-------------------------------------------------------------------------------------- // Exponential conversion between ui and Faust values //-------------------------------------------------------------------------------------- -class FAUST_API ExpValueConverter : public LinearValueConverter { - - public: - - ExpValueConverter(double umin, double umax, double fmin, double fmax) : - LinearValueConverter(umin, umax, std::min(DBL_MAX, std::exp(fmin)), std::min(DBL_MAX, std::exp(fmax))) - {} - - virtual double ui2faust(double x) { return std::log(LinearValueConverter::ui2faust(x)); } - virtual double faust2ui(double x) { return LinearValueConverter::faust2ui(std::min(DBL_MAX, std::exp(x))); } - +class FAUST_API ExpValueConverter : public LinearValueConverter +{ + public: + ExpValueConverter(double umin, double umax, double fmin, double fmax) + : LinearValueConverter(umin, umax, std::min(DBL_MAX, std::exp(fmin)), + std::min(DBL_MAX, std::exp(fmax))) + { + } + + virtual double ui2faust(double x) + { + return std::log(LinearValueConverter::ui2faust(x)); + } + virtual double faust2ui(double x) + { + return LinearValueConverter::faust2ui(std::min(DBL_MAX, std::exp(x))); + } }; //-------------------------------------------------------------------------------------- // Convert accelerometer or gyroscope values to Faust values // Using an Up curve (curve 0) //-------------------------------------------------------------------------------------- -class FAUST_API AccUpConverter : public UpdatableValueConverter { - - private: - - Interpolator3pt fA2F; - Interpolator3pt fF2A; - - public: - - AccUpConverter(double amin, double amid, double amax, double fmin, double fmid, double fmax) : - fA2F(amin,amid,amax,fmin,fmid,fmax), - fF2A(fmin,fmid,fmax,amin,amid,amax) - {} - - virtual double ui2faust(double x) { return fA2F(x); } - virtual double faust2ui(double x) { return fF2A(x); } - - virtual void setMappingValues(double amin, double amid, double amax, double fmin, double fmid, double fmax) - { - //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccUpConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax); - fA2F = Interpolator3pt(amin, amid, amax, fmin, fmid, fmax); - fF2A = Interpolator3pt(fmin, fmid, fmax, amin, amid, amax); - } - - virtual void getMappingValues(double& amin, double& amid, double& amax) - { - fA2F.getMappingValues(amin, amid, amax); - } - +class FAUST_API AccUpConverter : public UpdatableValueConverter +{ + private: + Interpolator3pt fA2F; + Interpolator3pt fF2A; + + public: + AccUpConverter(double amin, double amid, double amax, double fmin, double fmid, + double fmax) + : fA2F(amin, amid, amax, fmin, fmid, fmax) + , fF2A(fmin, fmid, fmax, amin, amid, amax) + { + } + + virtual double ui2faust(double x) { return fA2F(x); } + virtual double faust2ui(double x) { return fF2A(x); } + + virtual void setMappingValues(double amin, double amid, double amax, double fmin, + double fmid, double fmax) + { + //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccUpConverter update %f %f %f + //%f %f %f", amin,amid,amax,fmin,fmid,fmax); + fA2F = Interpolator3pt(amin, amid, amax, fmin, fmid, fmax); + fF2A = Interpolator3pt(fmin, fmid, fmax, amin, amid, amax); + } + + virtual void getMappingValues(double& amin, double& amid, double& amax) + { + fA2F.getMappingValues(amin, amid, amax); + } }; //-------------------------------------------------------------------------------------- // Convert accelerometer or gyroscope values to Faust values // Using a Down curve (curve 1) //-------------------------------------------------------------------------------------- -class FAUST_API AccDownConverter : public UpdatableValueConverter { - - private: - - Interpolator3pt fA2F; - Interpolator3pt fF2A; - - public: - - AccDownConverter(double amin, double amid, double amax, double fmin, double fmid, double fmax) : - fA2F(amin,amid,amax,fmax,fmid,fmin), - fF2A(fmin,fmid,fmax,amax,amid,amin) - {} - - virtual double ui2faust(double x) { return fA2F(x); } - virtual double faust2ui(double x) { return fF2A(x); } - - virtual void setMappingValues(double amin, double amid, double amax, double fmin, double fmid, double fmax) - { - //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccDownConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax); - fA2F = Interpolator3pt(amin, amid, amax, fmax, fmid, fmin); - fF2A = Interpolator3pt(fmin, fmid, fmax, amax, amid, amin); - } - - virtual void getMappingValues(double& amin, double& amid, double& amax) - { - fA2F.getMappingValues(amin, amid, amax); - } +class FAUST_API AccDownConverter : public UpdatableValueConverter +{ + private: + Interpolator3pt fA2F; + Interpolator3pt fF2A; + + public: + AccDownConverter(double amin, double amid, double amax, double fmin, double fmid, + double fmax) + : fA2F(amin, amid, amax, fmax, fmid, fmin) + , fF2A(fmin, fmid, fmax, amax, amid, amin) + { + } + + virtual double ui2faust(double x) { return fA2F(x); } + virtual double faust2ui(double x) { return fF2A(x); } + + virtual void setMappingValues(double amin, double amid, double amax, double fmin, + double fmid, double fmax) + { + //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccDownConverter update %f %f + //%f %f %f %f", amin,amid,amax,fmin,fmid,fmax); + fA2F = Interpolator3pt(amin, amid, amax, fmax, fmid, fmin); + fF2A = Interpolator3pt(fmin, fmid, fmax, amax, amid, amin); + } + + virtual void getMappingValues(double& amin, double& amid, double& amax) + { + fA2F.getMappingValues(amin, amid, amax); + } }; //-------------------------------------------------------------------------------------- // Convert accelerometer or gyroscope values to Faust values // Using an Up-Down curve (curve 2) //-------------------------------------------------------------------------------------- -class FAUST_API AccUpDownConverter : public UpdatableValueConverter { - - private: - - Interpolator3pt fA2F; - Interpolator fF2A; - - public: - - AccUpDownConverter(double amin, double amid, double amax, double fmin, double /* fmid */, double fmax) : - fA2F(amin,amid,amax,fmin,fmax,fmin), - fF2A(fmin,fmax,amin,amax) // Special, pseudo inverse of a non monotonic function - {} - - virtual double ui2faust(double x) { return fA2F(x); } - virtual double faust2ui(double x) { return fF2A(x); } - - virtual void setMappingValues(double amin, double amid, double amax, double fmin, double /* fmid */, double fmax) - { - //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccUpDownConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax); - fA2F = Interpolator3pt(amin, amid, amax, fmin, fmax, fmin); - fF2A = Interpolator(fmin, fmax, amin, amax); - } - - virtual void getMappingValues(double& amin, double& amid, double& amax) - { - fA2F.getMappingValues(amin, amid, amax); - } +class FAUST_API AccUpDownConverter : public UpdatableValueConverter +{ + private: + Interpolator3pt fA2F; + Interpolator fF2A; + + public: + AccUpDownConverter(double amin, double amid, double amax, double fmin, + double /* fmid */, double fmax) + : fA2F(amin, amid, amax, fmin, fmax, fmin) + , fF2A(fmin, fmax, amin, + amax) // Special, pseudo inverse of a non monotonic function + { + } + + virtual double ui2faust(double x) { return fA2F(x); } + virtual double faust2ui(double x) { return fF2A(x); } + + virtual void setMappingValues(double amin, double amid, double amax, double fmin, + double /* fmid */, double fmax) + { + //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccUpDownConverter update %f %f + //%f %f %f %f", amin,amid,amax,fmin,fmid,fmax); + fA2F = Interpolator3pt(amin, amid, amax, fmin, fmax, fmin); + fF2A = Interpolator(fmin, fmax, amin, amax); + } + + virtual void getMappingValues(double& amin, double& amid, double& amax) + { + fA2F.getMappingValues(amin, amid, amax); + } }; //-------------------------------------------------------------------------------------- // Convert accelerometer or gyroscope values to Faust values // Using a Down-Up curve (curve 3) //-------------------------------------------------------------------------------------- -class FAUST_API AccDownUpConverter : public UpdatableValueConverter { - - private: - - Interpolator3pt fA2F; - Interpolator fF2A; - - public: - - AccDownUpConverter(double amin, double amid, double amax, double fmin, double /* fmid */, double fmax) : - fA2F(amin,amid,amax,fmax,fmin,fmax), - fF2A(fmin,fmax,amin,amax) // Special, pseudo inverse of a non monotonic function - {} - - virtual double ui2faust(double x) { return fA2F(x); } - virtual double faust2ui(double x) { return fF2A(x); } - - virtual void setMappingValues(double amin, double amid, double amax, double fmin, double /* fmid */, double fmax) - { - //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccDownUpConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax); - fA2F = Interpolator3pt(amin, amid, amax, fmax, fmin, fmax); - fF2A = Interpolator(fmin, fmax, amin, amax); - } - - virtual void getMappingValues(double& amin, double& amid, double& amax) - { - fA2F.getMappingValues(amin, amid, amax); - } +class FAUST_API AccDownUpConverter : public UpdatableValueConverter +{ + private: + Interpolator3pt fA2F; + Interpolator fF2A; + + public: + AccDownUpConverter(double amin, double amid, double amax, double fmin, + double /* fmid */, double fmax) + : fA2F(amin, amid, amax, fmax, fmin, fmax) + , fF2A(fmin, fmax, amin, + amax) // Special, pseudo inverse of a non monotonic function + { + } + + virtual double ui2faust(double x) { return fA2F(x); } + virtual double faust2ui(double x) { return fF2A(x); } + + virtual void setMappingValues(double amin, double amid, double amax, double fmin, + double /* fmid */, double fmax) + { + //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccDownUpConverter update %f %f + //%f %f %f %f", amin,amid,amax,fmin,fmid,fmax); + fA2F = Interpolator3pt(amin, amid, amax, fmax, fmin, fmax); + fF2A = Interpolator(fmin, fmax, amin, amax); + } + + virtual void getMappingValues(double& amin, double& amid, double& amax) + { + fA2F.getMappingValues(amin, amid, amax); + } }; //-------------------------------------------------------------------------------------- // Base class for ZoneControl //-------------------------------------------------------------------------------------- -class FAUST_API ZoneControl { - - protected: - - FAUSTFLOAT* fZone; - - public: - - ZoneControl(FAUSTFLOAT* zone) : fZone(zone) {} - virtual ~ZoneControl() {} +class FAUST_API ZoneControl +{ + protected: + FAUSTFLOAT* fZone; - virtual void update(double /* v */) const {} + public: + ZoneControl(FAUSTFLOAT* zone) : fZone(zone) {} + virtual ~ZoneControl() {} - virtual void setMappingValues(int /* curve */, double /* amin */, double /* amid */, double /* amax */, double /* min */, double /* init */, double /* max */) {} - virtual void getMappingValues(double& /* amin */, double& /* amid */, double& /* amax */) {} + virtual void update(double /* v */) const {} - FAUSTFLOAT* getZone() { return fZone; } + virtual void setMappingValues(int /* curve */, double /* amin */, double /* amid */, + double /* amax */, double /* min */, double /* init */, + double /* max */) + { + } + virtual void getMappingValues(double& /* amin */, double& /* amid */, + double& /* amax */) + { + } - virtual void setActive(bool /* on_off */) {} - virtual bool getActive() { return false; } + FAUSTFLOAT* getZone() { return fZone; } - virtual int getCurve() { return -1; } + virtual void setActive(bool /* on_off */) {} + virtual bool getActive() { return false; } + virtual int getCurve() { return -1; } }; //-------------------------------------------------------------------------------------- // Useful to implement accelerometers metadata as a list of ZoneControl for each axes //-------------------------------------------------------------------------------------- -class FAUST_API ConverterZoneControl : public ZoneControl { - - protected: - - ValueConverter* fValueConverter; - - public: - - ConverterZoneControl(FAUSTFLOAT* zone, ValueConverter* converter) : ZoneControl(zone), fValueConverter(converter) {} - virtual ~ConverterZoneControl() { delete fValueConverter; } // Assuming fValueConverter is not kept elsewhere... - - virtual void update(double v) const { *fZone = FAUSTFLOAT(fValueConverter->ui2faust(v)); } - - ValueConverter* getConverter() { return fValueConverter; } - +class FAUST_API ConverterZoneControl : public ZoneControl +{ + protected: + ValueConverter* fValueConverter; + + public: + ConverterZoneControl(FAUSTFLOAT* zone, ValueConverter* converter) + : ZoneControl(zone), fValueConverter(converter) + { + } + virtual ~ConverterZoneControl() + { + delete fValueConverter; + } // Assuming fValueConverter is not kept elsewhere... + + virtual void update(double v) const + { + *fZone = FAUSTFLOAT(fValueConverter->ui2faust(v)); + } + + ValueConverter* getConverter() { return fValueConverter; } }; //-------------------------------------------------------------------------------------- // Association of a zone and a four value converter, each one for each possible curve. // Useful to implement accelerometers metadata as a list of ZoneControl for each axes //-------------------------------------------------------------------------------------- -class FAUST_API CurveZoneControl : public ZoneControl { - - private: - - std::vector fValueConverters; - int fCurve; - - public: - - CurveZoneControl(FAUSTFLOAT* zone, int curve, double amin, double amid, double amax, double min, double init, double max) : ZoneControl(zone), fCurve(0) - { - assert(curve >= 0 && curve <= 3); - fValueConverters.push_back(new AccUpConverter(amin, amid, amax, min, init, max)); - fValueConverters.push_back(new AccDownConverter(amin, amid, amax, min, init, max)); - fValueConverters.push_back(new AccUpDownConverter(amin, amid, amax, min, init, max)); - fValueConverters.push_back(new AccDownUpConverter(amin, amid, amax, min, init, max)); - fCurve = curve; - } - virtual ~CurveZoneControl() - { - for (const auto& it : fValueConverters) { delete it; } - } - void update(double v) const { if (fValueConverters[fCurve]->getActive()) *fZone = FAUSTFLOAT(fValueConverters[fCurve]->ui2faust(v)); } - - void setMappingValues(int curve, double amin, double amid, double amax, double min, double init, double max) - { - fValueConverters[curve]->setMappingValues(amin, amid, amax, min, init, max); - fCurve = curve; - } - - void getMappingValues(double& amin, double& amid, double& amax) - { - fValueConverters[fCurve]->getMappingValues(amin, amid, amax); +class FAUST_API CurveZoneControl : public ZoneControl +{ + private: + std::vector fValueConverters; + int fCurve; + + public: + CurveZoneControl(FAUSTFLOAT* zone, int curve, double amin, double amid, double amax, + double min, double init, double max) + : ZoneControl(zone), fCurve(0) + { + assert(curve >= 0 && curve <= 3); + fValueConverters.push_back(new AccUpConverter(amin, amid, amax, min, init, max)); + fValueConverters.push_back( + new AccDownConverter(amin, amid, amax, min, init, max)); + fValueConverters.push_back( + new AccUpDownConverter(amin, amid, amax, min, init, max)); + fValueConverters.push_back( + new AccDownUpConverter(amin, amid, amax, min, init, max)); + fCurve = curve; + } + virtual ~CurveZoneControl() + { + for (const auto& it : fValueConverters) { + delete it; } - - void setActive(bool on_off) - { - for (const auto& it : fValueConverters) { it->setActive(on_off); } + } + void update(double v) const + { + if (fValueConverters[fCurve]->getActive()) + *fZone = FAUSTFLOAT(fValueConverters[fCurve]->ui2faust(v)); + } + + void setMappingValues(int curve, double amin, double amid, double amax, double min, + double init, double max) + { + fValueConverters[curve]->setMappingValues(amin, amid, amax, min, init, max); + fCurve = curve; + } + + void getMappingValues(double& amin, double& amid, double& amax) + { + fValueConverters[fCurve]->getMappingValues(amin, amid, amax); + } + + void setActive(bool on_off) + { + for (const auto& it : fValueConverters) { + it->setActive(on_off); } + } - int getCurve() { return fCurve; } + int getCurve() { return fCurve; } }; -class FAUST_API ZoneReader { - - private: - - FAUSTFLOAT* fZone; - Interpolator fInterpolator; - - public: - - ZoneReader(FAUSTFLOAT* zone, double lo, double hi) : fZone(zone), fInterpolator(lo, hi, 0, 255) {} +class FAUST_API ZoneReader +{ + private: + FAUSTFLOAT* fZone; + Interpolator fInterpolator; - virtual ~ZoneReader() {} + public: + ZoneReader(FAUSTFLOAT* zone, double lo, double hi) + : fZone(zone), fInterpolator(lo, hi, 0, 255) + { + } - int getValue() - { - return (fZone != nullptr) ? int(fInterpolator(*fZone)) : 127; - } + virtual ~ZoneReader() {} + int getValue() { return (fZone != nullptr) ? int(fInterpolator(*fZone)) : 127; } }; #endif @@ -1281,688 +1338,742 @@ class FAUST_API ZoneReader { typedef unsigned int uint; -class APIUI : public PathBuilder, public Meta, public UI +class APIUI + : public PathBuilder + , public Meta + , public UI { - public: - enum ItemType { kButton = 0, kCheckButton, kVSlider, kHSlider, kNumEntry, kHBargraph, kVBargraph }; - enum Type { kAcc = 0, kGyr = 1, kNoType }; - - protected: - - enum Mapping { kLin = 0, kLog = 1, kExp = 2 }; - - struct Item { - std::string fLabel; - std::string fShortname; - std::string fPath; - ValueConverter* fConversion; - FAUSTFLOAT* fZone; - FAUSTFLOAT fInit; - FAUSTFLOAT fMin; - FAUSTFLOAT fMax; - FAUSTFLOAT fStep; - ItemType fItemType; - - Item(const std::string& label, - const std::string& short_name, - const std::string& path, - ValueConverter* conversion, - FAUSTFLOAT* zone, - FAUSTFLOAT init, - FAUSTFLOAT min, - FAUSTFLOAT max, - FAUSTFLOAT step, - ItemType item_type) - :fLabel(label), fShortname(short_name), fPath(path), fConversion(conversion), - fZone(zone), fInit(init), fMin(min), fMax(max), fStep(step), fItemType(item_type) - {} - }; - std::vector fItems; - - std::vector > fMetaData; - std::vector fAcc[3]; - std::vector fGyr[3]; - - // Screen color control - // "...[screencolor:red]..." etc. - bool fHasScreenControl; // true if control screen color metadata - ZoneReader* fRedReader; - ZoneReader* fGreenReader; - ZoneReader* fBlueReader; - - // Current values controlled by metadata - std::string fCurrentUnit; - int fCurrentScale; - std::string fCurrentAcc; - std::string fCurrentGyr; - std::string fCurrentColor; - std::string fCurrentTooltip; - std::map fCurrentMetadata; - - // Add a generic parameter - virtual void addParameter(const char* label, - FAUSTFLOAT* zone, - FAUSTFLOAT init, - FAUSTFLOAT min, - FAUSTFLOAT max, - FAUSTFLOAT step, - ItemType type) + public: + enum ItemType { + kButton = 0, + kCheckButton, + kVSlider, + kHSlider, + kNumEntry, + kHBargraph, + kVBargraph + }; + enum Type { kAcc = 0, kGyr = 1, kNoType }; + + protected: + enum Mapping { kLin = 0, kLog = 1, kExp = 2 }; + + struct Item { + std::string fLabel; + std::string fShortname; + std::string fPath; + ValueConverter* fConversion; + FAUSTFLOAT* fZone; + FAUSTFLOAT fInit; + FAUSTFLOAT fMin; + FAUSTFLOAT fMax; + FAUSTFLOAT fStep; + ItemType fItemType; + + Item(const std::string& label, const std::string& short_name, + const std::string& path, ValueConverter* conversion, FAUSTFLOAT* zone, + FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step, + ItemType item_type) + : fLabel(label) + , fShortname(short_name) + , fPath(path) + , fConversion(conversion) + , fZone(zone) + , fInit(init) + , fMin(min) + , fMax(max) + , fStep(step) + , fItemType(item_type) { - std::string path = buildPath(label); - fFullPaths.push_back(path); - - // handle scale metadata - ValueConverter* converter = nullptr; - switch (fCurrentScale) { - case kLin: - converter = new LinearValueConverter(0, 1, min, max); - break; - case kLog: - converter = new LogValueConverter(0, 1, min, max); - break; - case kExp: - converter = new ExpValueConverter(0, 1, min, max); - break; - } - fCurrentScale = kLin; - - fItems.push_back(Item(label, "", path, converter, zone, init, min, max, step, type)); - - if (fCurrentAcc.size() > 0 && fCurrentGyr.size() > 0) { - fprintf(stderr, "warning : 'acc' and 'gyr' metadata used for the same %s parameter !!\n", label); - } + } + }; + std::vector fItems; + + std::vector > fMetaData; + std::vector fAcc[3]; + std::vector fGyr[3]; + + // Screen color control + // "...[screencolor:red]..." etc. + bool fHasScreenControl; // true if control screen color metadata + ZoneReader* fRedReader; + ZoneReader* fGreenReader; + ZoneReader* fBlueReader; + + // Current values controlled by metadata + std::string fCurrentUnit; + int fCurrentScale; + std::string fCurrentAcc; + std::string fCurrentGyr; + std::string fCurrentColor; + std::string fCurrentTooltip; + std::map fCurrentMetadata; + + // Add a generic parameter + virtual void addParameter(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, + FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step, + ItemType type) + { + std::string path = buildPath(label); + fFullPaths.push_back(path); + + // handle scale metadata + ValueConverter* converter = nullptr; + switch (fCurrentScale) { + case kLin: + converter = new LinearValueConverter(0, 1, min, max); + break; + case kLog: + converter = new LogValueConverter(0, 1, min, max); + break; + case kExp: + converter = new ExpValueConverter(0, 1, min, max); + break; + } + fCurrentScale = kLin; - // handle acc metadata "...[acc : ]..." - if (fCurrentAcc.size() > 0) { - std::istringstream iss(fCurrentAcc); - int axe, curve; - double amin, amid, amax; - iss >> axe >> curve >> amin >> amid >> amax; - - if ((0 <= axe) && (axe < 3) && - (0 <= curve) && (curve < 4) && - (amin < amax) && (amin <= amid) && (amid <= amax)) - { - fAcc[axe].push_back(new CurveZoneControl(zone, curve, amin, amid, amax, min, init, max)); - } else { - fprintf(stderr, "incorrect acc metadata : %s \n", fCurrentAcc.c_str()); - } - fCurrentAcc = ""; - } + fItems.push_back( + Item(label, "", path, converter, zone, init, min, max, step, type)); - // handle gyr metadata "...[gyr : ]..." - if (fCurrentGyr.size() > 0) { - std::istringstream iss(fCurrentGyr); - int axe, curve; - double amin, amid, amax; - iss >> axe >> curve >> amin >> amid >> amax; - - if ((0 <= axe) && (axe < 3) && - (0 <= curve) && (curve < 4) && - (amin < amax) && (amin <= amid) && (amid <= amax)) - { - fGyr[axe].push_back(new CurveZoneControl(zone, curve, amin, amid, amax, min, init, max)); - } else { - fprintf(stderr, "incorrect gyr metadata : %s \n", fCurrentGyr.c_str()); - } - fCurrentGyr = ""; - } + if (fCurrentAcc.size() > 0 && fCurrentGyr.size() > 0) { + fprintf( + stderr, + "warning : 'acc' and 'gyr' metadata used for the same %s parameter !!\n", + label); + } - // handle screencolor metadata "...[screencolor:red|green|blue|white]..." - if (fCurrentColor.size() > 0) { - if ((fCurrentColor == "red") && (fRedReader == nullptr)) { - fRedReader = new ZoneReader(zone, min, max); - fHasScreenControl = true; - } else if ((fCurrentColor == "green") && (fGreenReader == nullptr)) { - fGreenReader = new ZoneReader(zone, min, max); - fHasScreenControl = true; - } else if ((fCurrentColor == "blue") && (fBlueReader == nullptr)) { - fBlueReader = new ZoneReader(zone, min, max); - fHasScreenControl = true; - } else if ((fCurrentColor == "white") && (fRedReader == nullptr) && (fGreenReader == nullptr) && (fBlueReader == nullptr)) { - fRedReader = new ZoneReader(zone, min, max); - fGreenReader = new ZoneReader(zone, min, max); - fBlueReader = new ZoneReader(zone, min, max); - fHasScreenControl = true; - } else { - fprintf(stderr, "incorrect screencolor metadata : %s \n", fCurrentColor.c_str()); - } + // handle acc metadata "...[acc : ]..." + if (fCurrentAcc.size() > 0) { + std::istringstream iss(fCurrentAcc); + int axe, curve; + double amin, amid, amax; + iss >> axe >> curve >> amin >> amid >> amax; + + if ((0 <= axe) && (axe < 3) && (0 <= curve) && (curve < 4) && (amin < amax) + && (amin <= amid) && (amid <= amax)) { + fAcc[axe].push_back( + new CurveZoneControl(zone, curve, amin, amid, amax, min, init, max)); + } else { + fprintf(stderr, "incorrect acc metadata : %s \n", fCurrentAcc.c_str()); } - fCurrentColor = ""; - - fMetaData.push_back(fCurrentMetadata); - fCurrentMetadata.clear(); + fCurrentAcc = ""; } - int getZoneIndex(std::vector* table, int p, int val) - { - FAUSTFLOAT* zone = fItems[uint(p)].fZone; - for (size_t i = 0; i < table[val].size(); i++) { - if (zone == table[val][i]->getZone()) return int(i); + // handle gyr metadata "...[gyr : ]..." + if (fCurrentGyr.size() > 0) { + std::istringstream iss(fCurrentGyr); + int axe, curve; + double amin, amid, amax; + iss >> axe >> curve >> amin >> amid >> amax; + + if ((0 <= axe) && (axe < 3) && (0 <= curve) && (curve < 4) && (amin < amax) + && (amin <= amid) && (amid <= amax)) { + fGyr[axe].push_back( + new CurveZoneControl(zone, curve, amin, amid, amax, min, init, max)); + } else { + fprintf(stderr, "incorrect gyr metadata : %s \n", fCurrentGyr.c_str()); } - return -1; + fCurrentGyr = ""; } - void setConverter(std::vector* table, int p, int val, int curve, double amin, double amid, double amax) - { - int id1 = getZoneIndex(table, p, 0); - int id2 = getZoneIndex(table, p, 1); - int id3 = getZoneIndex(table, p, 2); - - // Deactivates everywhere.. - if (id1 != -1) table[0][uint(id1)]->setActive(false); - if (id2 != -1) table[1][uint(id2)]->setActive(false); - if (id3 != -1) table[2][uint(id3)]->setActive(false); - - if (val == -1) { // Means: no more mapping... - // So stay all deactivated... + // handle screencolor metadata "...[screencolor:red|green|blue|white]..." + if (fCurrentColor.size() > 0) { + if ((fCurrentColor == "red") && (fRedReader == nullptr)) { + fRedReader = new ZoneReader(zone, min, max); + fHasScreenControl = true; + } else if ((fCurrentColor == "green") && (fGreenReader == nullptr)) { + fGreenReader = new ZoneReader(zone, min, max); + fHasScreenControl = true; + } else if ((fCurrentColor == "blue") && (fBlueReader == nullptr)) { + fBlueReader = new ZoneReader(zone, min, max); + fHasScreenControl = true; + } else if ((fCurrentColor == "white") && (fRedReader == nullptr) + && (fGreenReader == nullptr) && (fBlueReader == nullptr)) { + fRedReader = new ZoneReader(zone, min, max); + fGreenReader = new ZoneReader(zone, min, max); + fBlueReader = new ZoneReader(zone, min, max); + fHasScreenControl = true; } else { - int id4 = getZoneIndex(table, p, val); - if (id4 != -1) { - // Reactivate the one we edit... - table[val][uint(id4)]->setMappingValues(curve, amin, amid, amax, fItems[uint(p)].fMin, fItems[uint(p)].fInit, fItems[uint(p)].fMax); - table[val][uint(id4)]->setActive(true); - } else { - // Allocate a new CurveZoneControl which is 'active' by default - FAUSTFLOAT* zone = fItems[uint(p)].fZone; - table[val].push_back(new CurveZoneControl(zone, curve, amin, amid, amax, fItems[uint(p)].fMin, fItems[uint(p)].fInit, fItems[uint(p)].fMax)); - } + fprintf(stderr, "incorrect screencolor metadata : %s \n", + fCurrentColor.c_str()); } } - - void getConverter(std::vector* table, int p, int& val, int& curve, double& amin, double& amid, double& amax) - { - int id1 = getZoneIndex(table, p, 0); - int id2 = getZoneIndex(table, p, 1); - int id3 = getZoneIndex(table, p, 2); - - if (id1 != -1) { - val = 0; - curve = table[val][uint(id1)]->getCurve(); - table[val][uint(id1)]->getMappingValues(amin, amid, amax); - } else if (id2 != -1) { - val = 1; - curve = table[val][uint(id2)]->getCurve(); - table[val][uint(id2)]->getMappingValues(amin, amid, amax); - } else if (id3 != -1) { - val = 2; - curve = table[val][uint(id3)]->getCurve(); - table[val][uint(id3)]->getMappingValues(amin, amid, amax); + fCurrentColor = ""; + + fMetaData.push_back(fCurrentMetadata); + fCurrentMetadata.clear(); + } + + int getZoneIndex(std::vector* table, int p, int val) + { + FAUSTFLOAT* zone = fItems[uint(p)].fZone; + for (size_t i = 0; i < table[val].size(); i++) { + if (zone == table[val][i]->getZone()) + return int(i); + } + return -1; + } + + void setConverter(std::vector* table, int p, int val, int curve, + double amin, double amid, double amax) + { + int id1 = getZoneIndex(table, p, 0); + int id2 = getZoneIndex(table, p, 1); + int id3 = getZoneIndex(table, p, 2); + + // Deactivates everywhere.. + if (id1 != -1) + table[0][uint(id1)]->setActive(false); + if (id2 != -1) + table[1][uint(id2)]->setActive(false); + if (id3 != -1) + table[2][uint(id3)]->setActive(false); + + if (val == -1) { // Means: no more mapping... + // So stay all deactivated... + } else { + int id4 = getZoneIndex(table, p, val); + if (id4 != -1) { + // Reactivate the one we edit... + table[val][uint(id4)]->setMappingValues( + curve, amin, amid, amax, fItems[uint(p)].fMin, fItems[uint(p)].fInit, + fItems[uint(p)].fMax); + table[val][uint(id4)]->setActive(true); } else { - val = -1; // No mapping - curve = 0; - amin = -100.; - amid = 0.; - amax = 100.; + // Allocate a new CurveZoneControl which is 'active' by default + FAUSTFLOAT* zone = fItems[uint(p)].fZone; + table[val].push_back(new CurveZoneControl( + zone, curve, amin, amid, amax, fItems[uint(p)].fMin, + fItems[uint(p)].fInit, fItems[uint(p)].fMax)); } } + } + + void getConverter(std::vector* table, int p, int& val, int& curve, + double& amin, double& amid, double& amax) + { + int id1 = getZoneIndex(table, p, 0); + int id2 = getZoneIndex(table, p, 1); + int id3 = getZoneIndex(table, p, 2); + + if (id1 != -1) { + val = 0; + curve = table[val][uint(id1)]->getCurve(); + table[val][uint(id1)]->getMappingValues(amin, amid, amax); + } else if (id2 != -1) { + val = 1; + curve = table[val][uint(id2)]->getCurve(); + table[val][uint(id2)]->getMappingValues(amin, amid, amax); + } else if (id3 != -1) { + val = 2; + curve = table[val][uint(id3)]->getCurve(); + table[val][uint(id3)]->getMappingValues(amin, amid, amax); + } else { + val = -1; // No mapping + curve = 0; + amin = -100.; + amid = 0.; + amax = 100.; + } + } + + public: + APIUI() + : fHasScreenControl(false) + , fRedReader(nullptr) + , fGreenReader(nullptr) + , fBlueReader(nullptr) + , fCurrentScale(kLin) + { + } + + virtual ~APIUI() + { + for (const auto& it : fItems) + delete it.fConversion; + for (int i = 0; i < 3; i++) { + for (const auto& it : fAcc[i]) + delete it; + for (const auto& it : fGyr[i]) + delete it; + } + delete fRedReader; + delete fGreenReader; + delete fBlueReader; + } - public: - - APIUI() : fHasScreenControl(false), fRedReader(nullptr), fGreenReader(nullptr), fBlueReader(nullptr), fCurrentScale(kLin) - {} + // -- widget's layouts - virtual ~APIUI() - { - for (const auto& it : fItems) delete it.fConversion; - for (int i = 0; i < 3; i++) { - for (const auto& it : fAcc[i]) delete it; - for (const auto& it : fGyr[i]) delete it; + virtual void openTabBox(const char* label) { pushLabel(label); } + virtual void openHorizontalBox(const char* label) { pushLabel(label); } + virtual void openVerticalBox(const char* label) { pushLabel(label); } + virtual void closeBox() + { + if (popLabel()) { + // Shortnames can be computed when all fullnames are known + computeShortNames(); + // Fill 'shortname' field for each item + for (const auto& it : fFull2Short) { + int index = getParamIndex(it.first.c_str()); + fItems[index].fShortname = it.second; } - delete fRedReader; - delete fGreenReader; - delete fBlueReader; } + } - // -- widget's layouts + // -- active widgets - virtual void openTabBox(const char* label) { pushLabel(label); } - virtual void openHorizontalBox(const char* label) { pushLabel(label); } - virtual void openVerticalBox(const char* label) { pushLabel(label); } - virtual void closeBox() - { - if (popLabel()) { - // Shortnames can be computed when all fullnames are known - computeShortNames(); - // Fill 'shortname' field for each item - for (const auto& it : fFull2Short) { - int index = getParamIndex(it.first.c_str()); - fItems[index].fShortname = it.second; - } - } - } + virtual void addButton(const char* label, FAUSTFLOAT* zone) + { + addParameter(label, zone, 0, 0, 1, 1, kButton); + } + + virtual void addCheckButton(const char* label, FAUSTFLOAT* zone) + { + addParameter(label, zone, 0, 0, 1, 1, kCheckButton); + } + + virtual void addVerticalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, + FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) + { + addParameter(label, zone, init, min, max, step, kVSlider); + } + + virtual void addHorizontalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, + FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) + { + addParameter(label, zone, init, min, max, step, kHSlider); + } + + virtual void addNumEntry(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, + FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) + { + addParameter(label, zone, init, min, max, step, kNumEntry); + } - // -- active widgets + // -- passive widgets - virtual void addButton(const char* label, FAUSTFLOAT* zone) - { - addParameter(label, zone, 0, 0, 1, 1, kButton); - } + virtual void addHorizontalBargraph(const char* label, FAUSTFLOAT* zone, + FAUSTFLOAT min, FAUSTFLOAT max) + { + addParameter(label, zone, min, min, max, (max - min) / 1000.0f, kHBargraph); + } - virtual void addCheckButton(const char* label, FAUSTFLOAT* zone) - { - addParameter(label, zone, 0, 0, 1, 1, kCheckButton); - } + virtual void addVerticalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT min, + FAUSTFLOAT max) + { + addParameter(label, zone, min, min, max, (max - min) / 1000.0f, kVBargraph); + } - virtual void addVerticalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) - { - addParameter(label, zone, init, min, max, step, kVSlider); - } + // -- soundfiles - virtual void addHorizontalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) - { - addParameter(label, zone, init, min, max, step, kHSlider); - } + virtual void addSoundfile(const char* /* label */, const char* /* filename */, + Soundfile** /* sf_zone */) + { + } - virtual void addNumEntry(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) - { - addParameter(label, zone, init, min, max, step, kNumEntry); - } + // -- metadata declarations - // -- passive widgets + virtual void declare(FAUSTFLOAT* /* zone */, const char* key, const char* val) + { + // Keep metadata + fCurrentMetadata[key] = val; - virtual void addHorizontalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT min, FAUSTFLOAT max) - { - addParameter(label, zone, min, min, max, (max-min)/1000.0f, kHBargraph); + if (strcmp(key, "scale") == 0) { + if (strcmp(val, "log") == 0) { + fCurrentScale = kLog; + } else if (strcmp(val, "exp") == 0) { + fCurrentScale = kExp; + } else { + fCurrentScale = kLin; + } + } else if (strcmp(key, "unit") == 0) { + fCurrentUnit = val; + } else if (strcmp(key, "acc") == 0) { + fCurrentAcc = val; + } else if (strcmp(key, "gyr") == 0) { + fCurrentGyr = val; + } else if (strcmp(key, "screencolor") == 0) { + fCurrentColor = val; // val = "red", "green", "blue" or "white" + } else if (strcmp(key, "tooltip") == 0) { + fCurrentTooltip = val; } + } - virtual void addVerticalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT min, FAUSTFLOAT max) - { - addParameter(label, zone, min, min, max, (max-min)/1000.0f, kVBargraph); - } + virtual void declare(const char* /* key */, const char* /* val */) {} - // -- soundfiles + //------------------------------------------------------------------------------- + // Simple API part + //------------------------------------------------------------------------------- - virtual void addSoundfile(const char* /* label */, const char* /* filename */, Soundfile** /* sf_zone */) {} + /** + * Return the number of parameters in the UI. + * + * @return the number of parameters + */ + int getParamsCount() { return int(fItems.size()); } - // -- metadata declarations + /** + * Return the param index. + * + * @param str - the UI parameter label/shortname/path + * + * @return the param index + */ + int getParamIndex(const char* str) + { + std::string path = std::string(str); + auto it = find_if(fItems.begin(), fItems.end(), [=](const Item& it) { + return (it.fLabel == path) || (it.fShortname == path) || (it.fPath == path); + }); + return (it != fItems.end()) ? int(it - fItems.begin()) : -1; + } - virtual void declare(FAUSTFLOAT* /* zone */, const char* key, const char* val) - { - // Keep metadata - fCurrentMetadata[key] = val; - - if (strcmp(key, "scale") == 0) { - if (strcmp(val, "log") == 0) { - fCurrentScale = kLog; - } else if (strcmp(val, "exp") == 0) { - fCurrentScale = kExp; - } else { - fCurrentScale = kLin; - } - } else if (strcmp(key, "unit") == 0) { - fCurrentUnit = val; - } else if (strcmp(key, "acc") == 0) { - fCurrentAcc = val; - } else if (strcmp(key, "gyr") == 0) { - fCurrentGyr = val; - } else if (strcmp(key, "screencolor") == 0) { - fCurrentColor = val; // val = "red", "green", "blue" or "white" - } else if (strcmp(key, "tooltip") == 0) { - fCurrentTooltip = val; - } - } + /** + * Return the param label. + * + * @param p - the UI parameter index + * + * @return the param label + */ + const char* getParamLabel(int p) { return fItems[uint(p)].fLabel.c_str(); } - virtual void declare(const char* /* key */, const char* /* val */) - {} - - //------------------------------------------------------------------------------- - // Simple API part - //------------------------------------------------------------------------------- - - /** - * Return the number of parameters in the UI. - * - * @return the number of parameters - */ - int getParamsCount() { return int(fItems.size()); } - - /** - * Return the param index. - * - * @param str - the UI parameter label/shortname/path - * - * @return the param index - */ - int getParamIndex(const char* str) - { - std::string path = std::string(str); - auto it = find_if(fItems.begin(), fItems.end(), - [=](const Item& it) { return (it.fLabel == path) || (it.fShortname == path) || (it.fPath == path); }); - return (it != fItems.end()) ? int(it - fItems.begin()) : -1; - } - - /** - * Return the param label. - * - * @param p - the UI parameter index - * - * @return the param label - */ - const char* getParamLabel(int p) { return fItems[uint(p)].fLabel.c_str(); } - - /** - * Return the param shortname. - * - * @param p - the UI parameter index - * - * @return the param shortname - */ - const char* getParamShortname(int p) { return fItems[uint(p)].fShortname.c_str(); } - - /** - * Return the param path. - * - * @param p - the UI parameter index - * - * @return the param path - */ - const char* getParamAddress(int p) { return fItems[uint(p)].fPath.c_str(); } - - /** - * Return the param metadata. - * - * @param p - the UI parameter index - * - * @return the param metadata as a map - */ - std::map getMetadata(int p) - { - std::map res; - std::map metadata = fMetaData[uint(p)]; - for (const auto& it : metadata) { - res[it.first.c_str()] = it.second.c_str(); - } - return res; - } + /** + * Return the param shortname. + * + * @param p - the UI parameter index + * + * @return the param shortname + */ + const char* getParamShortname(int p) { return fItems[uint(p)].fShortname.c_str(); } - /** - * Return the param metadata value. - * - * @param p - the UI parameter index - * @param key - the UI parameter index - * - * @return the param metadata value associate to the key - */ - const char* getMetadata(int p, const char* key) - { - return (fMetaData[uint(p)].find(key) != fMetaData[uint(p)].end()) ? fMetaData[uint(p)][key].c_str() : ""; - } - - /** - * Return the param minimum value. - * - * @param p - the UI parameter index - * - * @return the param minimum value - */ - FAUSTFLOAT getParamMin(int p) { return fItems[uint(p)].fMin; } - - /** - * Return the param maximum value. - * - * @param p - the UI parameter index - * - * @return the param maximum value - */ - FAUSTFLOAT getParamMax(int p) { return fItems[uint(p)].fMax; } - - /** - * Return the param step value. - * - * @param p - the UI parameter index - * - * @return the param step value - */ - FAUSTFLOAT getParamStep(int p) { return fItems[uint(p)].fStep; } - - /** - * Return the param init value. - * - * @param p - the UI parameter index - * - * @return the param init value - */ - FAUSTFLOAT getParamInit(int p) { return fItems[uint(p)].fInit; } - - /** - * Return the param memory zone. - * - * @param p - the UI parameter index - * - * @return the param memory zone. - */ - FAUSTFLOAT* getParamZone(int p) { return fItems[uint(p)].fZone; } - - /** - * Return the param value. - * - * @param p - the UI parameter index - * - * @return the param value. - */ - FAUSTFLOAT getParamValue(int p) { return *fItems[uint(p)].fZone; } - - /** - * Return the param value. - * - * @param str - the UI parameter label/shortname/path - * - * @return the param value. - */ - FAUSTFLOAT getParamValue(const char* str) - { - int index = getParamIndex(str); - if (index >= 0) { - return getParamValue(index); - } else { - fprintf(stderr, "getParamValue : '%s' not found\n", (str == nullptr ? "NULL" : str)); - return FAUSTFLOAT(0); - } - } + /** + * Return the param path. + * + * @param p - the UI parameter index + * + * @return the param path + */ + const char* getParamAddress(int p) { return fItems[uint(p)].fPath.c_str(); } - /** - * Set the param value. - * - * @param p - the UI parameter index - * @param v - the UI parameter value - * - */ - void setParamValue(int p, FAUSTFLOAT v) { *fItems[uint(p)].fZone = v; } - - /** - * Set the param value. - * - * @param p - the UI parameter label/shortname/path - * @param v - the UI parameter value - * - */ - void setParamValue(const char* path, FAUSTFLOAT v) - { - int index = getParamIndex(path); - if (index >= 0) { - setParamValue(index, v); - } else { - fprintf(stderr, "setParamValue : '%s' not found\n", (path == nullptr ? "NULL" : path)); - } + /** + * Return the param metadata. + * + * @param p - the UI parameter index + * + * @return the param metadata as a map + */ + std::map getMetadata(int p) + { + std::map res; + std::map metadata = fMetaData[uint(p)]; + for (const auto& it : metadata) { + res[it.first.c_str()] = it.second.c_str(); } + return res; + } - double getParamRatio(int p) { return fItems[uint(p)].fConversion->faust2ui(*fItems[uint(p)].fZone); } - void setParamRatio(int p, double r) { *fItems[uint(p)].fZone = FAUSTFLOAT(fItems[uint(p)].fConversion->ui2faust(r)); } + /** + * Return the param metadata value. + * + * @param p - the UI parameter index + * @param key - the UI parameter index + * + * @return the param metadata value associate to the key + */ + const char* getMetadata(int p, const char* key) + { + return (fMetaData[uint(p)].find(key) != fMetaData[uint(p)].end()) + ? fMetaData[uint(p)][key].c_str() + : ""; + } - double value2ratio(int p, double r) { return fItems[uint(p)].fConversion->faust2ui(r); } - double ratio2value(int p, double r) { return fItems[uint(p)].fConversion->ui2faust(r); } + /** + * Return the param minimum value. + * + * @param p - the UI parameter index + * + * @return the param minimum value + */ + FAUSTFLOAT getParamMin(int p) { return fItems[uint(p)].fMin; } - /** - * Return the control type (kAcc, kGyr, or -1) for a given parameter. - * - * @param p - the UI parameter index - * - * @return the type - */ - Type getParamType(int p) - { - if (p >= 0) { - if (getZoneIndex(fAcc, p, 0) != -1 - || getZoneIndex(fAcc, p, 1) != -1 - || getZoneIndex(fAcc, p, 2) != -1) { - return kAcc; - } else if (getZoneIndex(fGyr, p, 0) != -1 - || getZoneIndex(fGyr, p, 1) != -1 - || getZoneIndex(fGyr, p, 2) != -1) { - return kGyr; - } - } - return kNoType; - } + /** + * Return the param maximum value. + * + * @param p - the UI parameter index + * + * @return the param maximum value + */ + FAUSTFLOAT getParamMax(int p) { return fItems[uint(p)].fMax; } - /** - * Return the Item type (kButton = 0, kCheckButton, kVSlider, kHSlider, kNumEntry, kHBargraph, kVBargraph) for a given parameter. - * - * @param p - the UI parameter index - * - * @return the Item type - */ - ItemType getParamItemType(int p) - { - return fItems[uint(p)].fItemType; - } + /** + * Return the param step value. + * + * @param p - the UI parameter index + * + * @return the param step value + */ + FAUSTFLOAT getParamStep(int p) { return fItems[uint(p)].fStep; } - /** - * Set a new value coming from an accelerometer, propagate it to all relevant FAUSTFLOAT* zones. - * - * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer - * @param value - the new value - * - */ - void propagateAcc(int acc, double value) - { - for (size_t i = 0; i < fAcc[acc].size(); i++) { - fAcc[acc][i]->update(value); - } - } + /** + * Return the param init value. + * + * @param p - the UI parameter index + * + * @return the param init value + */ + FAUSTFLOAT getParamInit(int p) { return fItems[uint(p)].fInit; } - /** - * Used to edit accelerometer curves and mapping. Set curve and related mapping for a given UI parameter. - * - * @param p - the UI parameter index - * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer (-1 means "no mapping") - * @param curve - between 0 and 3 (0: up, 1: down, 2: up and down, 2: down and up) - * @param amin - mapping 'min' point - * @param amid - mapping 'middle' point - * @param amax - mapping 'max' point - * - */ - void setAccConverter(int p, int acc, int curve, double amin, double amid, double amax) - { - setConverter(fAcc, p, acc, curve, amin, amid, amax); - } + /** + * Return the param memory zone. + * + * @param p - the UI parameter index + * + * @return the param memory zone. + */ + FAUSTFLOAT* getParamZone(int p) { return fItems[uint(p)].fZone; } - /** - * Used to edit gyroscope curves and mapping. Set curve and related mapping for a given UI parameter. - * - * @param p - the UI parameter index - * @param gyr - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope (-1 means "no mapping") - * @param curve - between 0 and 3 (0: up, 1: down, 2: up and down, 2: down and up) - * @param amin - mapping 'min' point - * @param amid - mapping 'middle' point - * @param amax - mapping 'max' point - * - */ - void setGyrConverter(int p, int gyr, int curve, double amin, double amid, double amax) - { - setConverter(fGyr, p, gyr, curve, amin, amid, amax); - } + /** + * Return the param value. + * + * @param p - the UI parameter index + * + * @return the param value. + */ + FAUSTFLOAT getParamValue(int p) { return *fItems[uint(p)].fZone; } - /** - * Used to edit accelerometer curves and mapping. Get curve and related mapping for a given UI parameter. - * - * @param p - the UI parameter index - * @param acc - the acc value to be retrieved (-1 means "no mapping") - * @param curve - the curve value to be retrieved (between 0 and 3) - * @param amin - the amin value to be retrieved - * @param amid - the amid value to be retrieved - * @param amax - the amax value to be retrieved - * - */ - void getAccConverter(int p, int& acc, int& curve, double& amin, double& amid, double& amax) - { - getConverter(fAcc, p, acc, curve, amin, amid, amax); + /** + * Return the param value. + * + * @param str - the UI parameter label/shortname/path + * + * @return the param value. + */ + FAUSTFLOAT getParamValue(const char* str) + { + int index = getParamIndex(str); + if (index >= 0) { + return getParamValue(index); + } else { + fprintf(stderr, "getParamValue : '%s' not found\n", + (str == nullptr ? "NULL" : str)); + return FAUSTFLOAT(0); } + } - /** - * Used to edit gyroscope curves and mapping. Get curve and related mapping for a given UI parameter. - * - * @param p - the UI parameter index - * @param gyr - the gyr value to be retrieved (-1 means "no mapping") - * @param curve - the curve value to be retrieved (between 0 and 3) - * @param amin - the amin value to be retrieved - * @param amid - the amid value to be retrieved - * @param amax - the amax value to be retrieved - * - */ - void getGyrConverter(int p, int& gyr, int& curve, double& amin, double& amid, double& amax) - { - getConverter(fGyr, p, gyr, curve, amin, amid, amax); + /** + * Set the param value. + * + * @param p - the UI parameter index + * @param v - the UI parameter value + * + */ + void setParamValue(int p, FAUSTFLOAT v) { *fItems[uint(p)].fZone = v; } + + /** + * Set the param value. + * + * @param p - the UI parameter label/shortname/path + * @param v - the UI parameter value + * + */ + void setParamValue(const char* path, FAUSTFLOAT v) + { + int index = getParamIndex(path); + if (index >= 0) { + setParamValue(index, v); + } else { + fprintf(stderr, "setParamValue : '%s' not found\n", + (path == nullptr ? "NULL" : path)); } + } + + double getParamRatio(int p) + { + return fItems[uint(p)].fConversion->faust2ui(*fItems[uint(p)].fZone); + } + void setParamRatio(int p, double r) + { + *fItems[uint(p)].fZone = FAUSTFLOAT(fItems[uint(p)].fConversion->ui2faust(r)); + } + + double value2ratio(int p, double r) + { + return fItems[uint(p)].fConversion->faust2ui(r); + } + double ratio2value(int p, double r) + { + return fItems[uint(p)].fConversion->ui2faust(r); + } - /** - * Set a new value coming from an gyroscope, propagate it to all relevant FAUSTFLOAT* zones. - * - * @param gyr - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope - * @param value - the new value - * - */ - void propagateGyr(int gyr, double value) - { - for (size_t i = 0; i < fGyr[gyr].size(); i++) { - fGyr[gyr][i]->update(value); + /** + * Return the control type (kAcc, kGyr, or -1) for a given parameter. + * + * @param p - the UI parameter index + * + * @return the type + */ + Type getParamType(int p) + { + if (p >= 0) { + if (getZoneIndex(fAcc, p, 0) != -1 || getZoneIndex(fAcc, p, 1) != -1 + || getZoneIndex(fAcc, p, 2) != -1) { + return kAcc; + } else if (getZoneIndex(fGyr, p, 0) != -1 || getZoneIndex(fGyr, p, 1) != -1 + || getZoneIndex(fGyr, p, 2) != -1) { + return kGyr; } } + return kNoType; + } - /** - * Get the number of FAUSTFLOAT* zones controlled with the accelerometer. - * - * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer - * @return the number of zones - * - */ - int getAccCount(int acc) - { - return (acc >= 0 && acc < 3) ? int(fAcc[acc].size()) : 0; - } + /** + * Return the Item type (kButton = 0, kCheckButton, kVSlider, kHSlider, kNumEntry, + * kHBargraph, kVBargraph) for a given parameter. + * + * @param p - the UI parameter index + * + * @return the Item type + */ + ItemType getParamItemType(int p) { return fItems[uint(p)].fItemType; } - /** - * Get the number of FAUSTFLOAT* zones controlled with the gyroscope. - * - * @param gyr - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope - * @param the number of zones - * - */ - int getGyrCount(int gyr) - { - return (gyr >= 0 && gyr < 3) ? int(fGyr[gyr].size()) : 0; + /** + * Set a new value coming from an accelerometer, propagate it to all relevant + * FAUSTFLOAT* zones. + * + * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer + * @param value - the new value + * + */ + void propagateAcc(int acc, double value) + { + for (size_t i = 0; i < fAcc[acc].size(); i++) { + fAcc[acc][i]->update(value); } + } - /** - * Get the requested screen color. - * - * -1 means no screen color control (no screencolor metadata found) - * otherwise return 0x00RRGGBB a ready to use color - * - */ - int getScreenColor() - { - if (fHasScreenControl) { - int r = (fRedReader) ? fRedReader->getValue() : 0; - int g = (fGreenReader) ? fGreenReader->getValue() : 0; - int b = (fBlueReader) ? fBlueReader->getValue() : 0; - return (r<<16) | (g<<8) | b; - } else { - return -1; - } + /** + * Used to edit accelerometer curves and mapping. Set curve and related mapping for a + * given UI parameter. + * + * @param p - the UI parameter index + * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer + * (-1 means "no mapping") + * @param curve - between 0 and 3 (0: up, 1: down, 2: up and down, 2: down and up) + * @param amin - mapping 'min' point + * @param amid - mapping 'middle' point + * @param amax - mapping 'max' point + * + */ + void setAccConverter(int p, int acc, int curve, double amin, double amid, double amax) + { + setConverter(fAcc, p, acc, curve, amin, amid, amax); + } + + /** + * Used to edit gyroscope curves and mapping. Set curve and related mapping for a + * given UI parameter. + * + * @param p - the UI parameter index + * @param gyr - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope (-1 means "no + * mapping") + * @param curve - between 0 and 3 (0: up, 1: down, 2: up and down, 2: down and up) + * @param amin - mapping 'min' point + * @param amid - mapping 'middle' point + * @param amax - mapping 'max' point + * + */ + void setGyrConverter(int p, int gyr, int curve, double amin, double amid, double amax) + { + setConverter(fGyr, p, gyr, curve, amin, amid, amax); + } + + /** + * Used to edit accelerometer curves and mapping. Get curve and related mapping for a + * given UI parameter. + * + * @param p - the UI parameter index + * @param acc - the acc value to be retrieved (-1 means "no mapping") + * @param curve - the curve value to be retrieved (between 0 and 3) + * @param amin - the amin value to be retrieved + * @param amid - the amid value to be retrieved + * @param amax - the amax value to be retrieved + * + */ + void getAccConverter(int p, int& acc, int& curve, double& amin, double& amid, + double& amax) + { + getConverter(fAcc, p, acc, curve, amin, amid, amax); + } + + /** + * Used to edit gyroscope curves and mapping. Get curve and related mapping for a + * given UI parameter. + * + * @param p - the UI parameter index + * @param gyr - the gyr value to be retrieved (-1 means "no mapping") + * @param curve - the curve value to be retrieved (between 0 and 3) + * @param amin - the amin value to be retrieved + * @param amid - the amid value to be retrieved + * @param amax - the amax value to be retrieved + * + */ + void getGyrConverter(int p, int& gyr, int& curve, double& amin, double& amid, + double& amax) + { + getConverter(fGyr, p, gyr, curve, amin, amid, amax); + } + + /** + * Set a new value coming from an gyroscope, propagate it to all relevant FAUSTFLOAT* + * zones. + * + * @param gyr - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope + * @param value - the new value + * + */ + void propagateGyr(int gyr, double value) + { + for (size_t i = 0; i < fGyr[gyr].size(); i++) { + fGyr[gyr][i]->update(value); } + } + + /** + * Get the number of FAUSTFLOAT* zones controlled with the accelerometer. + * + * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer + * @return the number of zones + * + */ + int getAccCount(int acc) { return (acc >= 0 && acc < 3) ? int(fAcc[acc].size()) : 0; } + /** + * Get the number of FAUSTFLOAT* zones controlled with the gyroscope. + * + * @param gyr - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope + * @param the number of zones + * + */ + int getGyrCount(int gyr) { return (gyr >= 0 && gyr < 3) ? int(fGyr[gyr].size()) : 0; } + + /** + * Get the requested screen color. + * + * -1 means no screen color control (no screencolor metadata found) + * otherwise return 0x00RRGGBB a ready to use color + * + */ + int getScreenColor() + { + if (fHasScreenControl) { + int r = (fRedReader) ? fRedReader->getValue() : 0; + int g = (fGreenReader) ? fGreenReader->getValue() : 0; + int b = (fBlueReader) ? fBlueReader->getValue() : 0; + return (r << 16) | (g << 8) | b; + } else { + return -1; + } + } }; #endif @@ -1975,22 +2086,21 @@ class APIUI : public PathBuilder, public Meta, public UI // FAUST Generated Code //---------------------------------------------------------------------------- - #ifndef FAUSTFLOAT #define FAUSTFLOAT float -#endif +#endif #include #include #include -#ifndef FAUSTCLASS +#ifndef FAUSTCLASS #define FAUSTCLASS stereotomonodsp #endif -#ifdef __APPLE__ +#ifdef __APPLE__ #define exp10f __exp10f -#define exp10 __exp10 +#define exp10 __exp10 #endif #if defined(_WIN32) @@ -1999,80 +2109,69 @@ class APIUI : public PathBuilder, public Meta, public UI #define RESTRICT __restrict__ #endif - -class stereotomonodsp : public dsp { - - private: - - int fSampleRate; - - public: - - void metadata(Meta* m) { - m->declare("author", "Dominick Hing"); - m->declare("compile_options", "-a faust2header.cpp -lang cpp -i -inpl -cn stereotomonodsp -es 1 -mcd 16 -single -ftz 0"); - m->declare("description", "Stereo-to-Mono Faust Plugin for JackTrip"); - m->declare("filename", "stereotomonodsp.dsp"); - m->declare("license", "MIT Style STK-4.2"); - m->declare("name", "stereo-to-mono"); - m->declare("version", "1.0"); - } - - virtual int getNumInputs() { - return 2; - } - virtual int getNumOutputs() { - return 1; - } - - static void classInit(int /* sample_rate */) { - } - - virtual void instanceConstants(int sample_rate) { - fSampleRate = sample_rate; - } - - virtual void instanceResetUserInterface() { - } - - virtual void instanceClear() { - } - - virtual void init(int sample_rate) { - classInit(sample_rate); - instanceInit(sample_rate); - } - virtual void instanceInit(int sample_rate) { - instanceConstants(sample_rate); - instanceResetUserInterface(); - instanceClear(); - } - - virtual stereotomonodsp* clone() { - return new stereotomonodsp(); - } - - virtual int getSampleRate() { - return fSampleRate; - } - - virtual void buildUserInterface(UI* ui_interface) { - ui_interface->openVerticalBox("stereo-to-mono"); - ui_interface->closeBox(); - } - - virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { - FAUSTFLOAT* input0 = inputs[0]; - FAUSTFLOAT* input1 = inputs[1]; - FAUSTFLOAT* output0 = outputs[0]; - for (int i0 = 0; i0 < count; i0 = i0 + 1) { - float fTemp0 = float(input0[i0]); - float fTemp1 = float(input1[i0]); - output0[i0] = FAUSTFLOAT(0.5f * (fTemp0 + fTemp1)); - } - } - +class stereotomonodsp : public dsp +{ + private: + int fSampleRate; + + public: + void metadata(Meta* m) + { + m->declare("author", "Dominick Hing"); + m->declare("compile_options", + "-a faust2header.cpp -lang cpp -i -inpl -cn stereotomonodsp -es 1 " + "-mcd 16 -single -ftz 0"); + m->declare("description", "Stereo-to-Mono Faust Plugin for JackTrip"); + m->declare("filename", "stereotomonodsp.dsp"); + m->declare("license", "MIT Style STK-4.2"); + m->declare("name", "stereo-to-mono"); + m->declare("version", "1.0"); + } + + virtual int getNumInputs() { return 2; } + virtual int getNumOutputs() { return 1; } + + static void classInit(int /* sample_rate */) {} + + virtual void instanceConstants(int sample_rate) { fSampleRate = sample_rate; } + + virtual void instanceResetUserInterface() {} + + virtual void instanceClear() {} + + virtual void init(int sample_rate) + { + classInit(sample_rate); + instanceInit(sample_rate); + } + virtual void instanceInit(int sample_rate) + { + instanceConstants(sample_rate); + instanceResetUserInterface(); + instanceClear(); + } + + virtual stereotomonodsp* clone() { return new stereotomonodsp(); } + + virtual int getSampleRate() { return fSampleRate; } + + virtual void buildUserInterface(UI* ui_interface) + { + ui_interface->openVerticalBox("stereo-to-mono"); + ui_interface->closeBox(); + } + + virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) + { + FAUSTFLOAT* input0 = inputs[0]; + FAUSTFLOAT* input1 = inputs[1]; + FAUSTFLOAT* output0 = outputs[0]; + for (int i0 = 0; i0 < count; i0 = i0 + 1) { + float fTemp0 = float(input0[i0]); + float fTemp1 = float(input1[i0]); + output0[i0] = FAUSTFLOAT(0.5f * (fTemp0 + fTemp1)); + } + } }; - #endif diff --git a/src/tonedsp.h b/src/tonedsp.h index e999299..84af3a1 100644 --- a/src/tonedsp.h +++ b/src/tonedsp.h @@ -1,11 +1,12 @@ /* ------------------------------------------------------------ name: "tonedsp" Code generated with Faust 2.50.6 (https://faust.grame.fr) -Compilation options: -a faust2header.cpp -lang cpp -i -inpl -cn tonedsp -es 1 -mcd 16 -single -ftz 0 +Compilation options: -a faust2header.cpp -lang cpp -i -inpl -cn tonedsp -es 1 -mcd 16 +-single -ftz 0 ------------------------------------------------------------ */ -#ifndef __tonedsp_H__ -#define __tonedsp_H__ +#ifndef __tonedsp_H__ +#define __tonedsp_H__ // NOTE: ANY INCLUDE-GUARD HERE MUST BE DERIVED FROM THE CLASS NAME // @@ -22,16 +23,16 @@ Compilation options: -a faust2header.cpp -lang cpp -i -inpl -cn tonedsp -es 1 -m it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + EXCEPTION : As a special exception, you may create a larger work that contains this FAUST architecture section and distribute that work under terms of your choice, so long as this FAUST @@ -70,29 +71,29 @@ Compilation options: -a faust2header.cpp -lang cpp -i -inpl -cn tonedsp -es 1 -m #define FAUSTVERSION "2.50.6" -// Use FAUST_API for code that is part of the external API but is also compiled in faust and libfaust -// Use LIBFAUST_API for code that is compiled in faust and libfaust +// Use FAUST_API for code that is part of the external API but is also compiled in faust +// and libfaust Use LIBFAUST_API for code that is compiled in faust and libfaust #ifdef _WIN32 - #pragma warning (disable: 4251) - #ifdef FAUST_EXE - #define FAUST_API - #define LIBFAUST_API - #elif FAUST_LIB - #define FAUST_API __declspec(dllexport) - #define LIBFAUST_API __declspec(dllexport) - #else - #define FAUST_API - #define LIBFAUST_API - #endif +#pragma warning(disable : 4251) +#ifdef FAUST_EXE +#define FAUST_API +#define LIBFAUST_API +#elif FAUST_LIB +#define FAUST_API __declspec(dllexport) +#define LIBFAUST_API __declspec(dllexport) +#else +#define FAUST_API +#define LIBFAUST_API +#endif +#else +#ifdef FAUST_EXE +#define FAUST_API +#define LIBFAUST_API #else - #ifdef FAUST_EXE - #define FAUST_API - #define LIBFAUST_API - #else - #define FAUST_API __attribute__((visibility("default"))) - #define LIBFAUST_API __attribute__((visibility("default"))) - #endif +#define FAUST_API __attribute__((visibility("default"))) +#define LIBFAUST_API __attribute__((visibility("default"))) +#endif #endif #endif @@ -109,15 +110,14 @@ struct FAUST_API Meta; */ struct FAUST_API dsp_memory_manager { - virtual ~dsp_memory_manager() {} - + /** * Inform the Memory Manager with the number of expected memory zones. * @param count - the number of expected memory zones */ virtual void begin(size_t /*count*/) {} - + /** * Give the Memory Manager information on a given memory zone. * @param size - the size in bytes of the memory zone @@ -125,151 +125,167 @@ struct FAUST_API dsp_memory_manager { * @param writes - the number of Write access to the zone used to compute one frame */ virtual void info(size_t /*size*/, size_t /*reads*/, size_t /*writes*/) {} - + /** * Inform the Memory Manager that all memory zones have been described, * to possibly start a 'compute the best allocation strategy' step. */ virtual void end() {} - + /** * Allocate a memory zone. * @param size - the memory zone size in bytes */ virtual void* allocate(size_t size) = 0; - + /** * Destroy a memory zone. * @param ptr - the memory zone pointer to be deallocated */ virtual void destroy(void* ptr) = 0; - -}; - -/** -* Signal processor definition. -*/ - -class FAUST_API dsp { - - public: - - dsp() {} - virtual ~dsp() {} - - /* Return instance number of audio inputs */ - virtual int getNumInputs() = 0; - - /* Return instance number of audio outputs */ - virtual int getNumOutputs() = 0; - - /** - * Trigger the ui_interface parameter with instance specific calls - * to 'openTabBox', 'addButton', 'addVerticalSlider'... in order to build the UI. - * - * @param ui_interface - the user interface builder - */ - virtual void buildUserInterface(UI* ui_interface) = 0; - - /* Return the sample rate currently used by the instance */ - virtual int getSampleRate() = 0; - - /** - * Global init, calls the following methods: - * - static class 'classInit': static tables initialization - * - 'instanceInit': constants and instance state initialization - * - * @param sample_rate - the sampling rate in Hz - */ - virtual void init(int sample_rate) = 0; - - /** - * Init instance state - * - * @param sample_rate - the sampling rate in Hz - */ - virtual void instanceInit(int sample_rate) = 0; - - /** - * Init instance constant state - * - * @param sample_rate - the sampling rate in Hz - */ - virtual void instanceConstants(int sample_rate) = 0; - - /* Init default control parameters values */ - virtual void instanceResetUserInterface() = 0; - - /* Init instance state (like delay lines...) but keep the control parameter values */ - virtual void instanceClear() = 0; - - /** - * Return a clone of the instance. - * - * @return a copy of the instance on success, otherwise a null pointer. - */ - virtual dsp* clone() = 0; - - /** - * Trigger the Meta* parameter with instance specific calls to 'declare' (key, value) metadata. - * - * @param m - the Meta* meta user - */ - virtual void metadata(Meta* m) = 0; - - /** - * DSP instance computation, to be called with successive in/out audio buffers. - * - * @param count - the number of frames to compute - * @param inputs - the input audio buffers as an array of non-interleaved FAUSTFLOAT samples (eiher float, double or quad) - * @param outputs - the output audio buffers as an array of non-interleaved FAUSTFLOAT samples (eiher float, double or quad) - * - */ - virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) = 0; - - /** - * DSP instance computation: alternative method to be used by subclasses. - * - * @param date_usec - the timestamp in microsec given by audio driver. - * @param count - the number of frames to compute - * @param inputs - the input audio buffers as an array of non-interleaved FAUSTFLOAT samples (either float, double or quad) - * @param outputs - the output audio buffers as an array of non-interleaved FAUSTFLOAT samples (either float, double or quad) - * - */ - virtual void compute(double /*date_usec*/, int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { compute(count, inputs, outputs); } - }; /** - * Generic DSP decorator. + * Signal processor definition. */ -class FAUST_API decorator_dsp : public dsp { +class FAUST_API dsp +{ + public: + dsp() {} + virtual ~dsp() {} + + /* Return instance number of audio inputs */ + virtual int getNumInputs() = 0; + + /* Return instance number of audio outputs */ + virtual int getNumOutputs() = 0; + + /** + * Trigger the ui_interface parameter with instance specific calls + * to 'openTabBox', 'addButton', 'addVerticalSlider'... in order to build the UI. + * + * @param ui_interface - the user interface builder + */ + virtual void buildUserInterface(UI* ui_interface) = 0; + + /* Return the sample rate currently used by the instance */ + virtual int getSampleRate() = 0; + + /** + * Global init, calls the following methods: + * - static class 'classInit': static tables initialization + * - 'instanceInit': constants and instance state initialization + * + * @param sample_rate - the sampling rate in Hz + */ + virtual void init(int sample_rate) = 0; + + /** + * Init instance state + * + * @param sample_rate - the sampling rate in Hz + */ + virtual void instanceInit(int sample_rate) = 0; + + /** + * Init instance constant state + * + * @param sample_rate - the sampling rate in Hz + */ + virtual void instanceConstants(int sample_rate) = 0; - protected: + /* Init default control parameters values */ + virtual void instanceResetUserInterface() = 0; - dsp* fDSP; + /* Init instance state (like delay lines...) but keep the control parameter values */ + virtual void instanceClear() = 0; + + /** + * Return a clone of the instance. + * + * @return a copy of the instance on success, otherwise a null pointer. + */ + virtual dsp* clone() = 0; - public: + /** + * Trigger the Meta* parameter with instance specific calls to 'declare' (key, value) + * metadata. + * + * @param m - the Meta* meta user + */ + virtual void metadata(Meta* m) = 0; - decorator_dsp(dsp* dsp = nullptr):fDSP(dsp) {} - virtual ~decorator_dsp() { delete fDSP; } + /** + * DSP instance computation, to be called with successive in/out audio buffers. + * + * @param count - the number of frames to compute + * @param inputs - the input audio buffers as an array of non-interleaved FAUSTFLOAT + * samples (eiher float, double or quad) + * @param outputs - the output audio buffers as an array of non-interleaved FAUSTFLOAT + * samples (eiher float, double or quad) + * + */ + virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) = 0; + + /** + * DSP instance computation: alternative method to be used by subclasses. + * + * @param date_usec - the timestamp in microsec given by audio driver. + * @param count - the number of frames to compute + * @param inputs - the input audio buffers as an array of non-interleaved FAUSTFLOAT + * samples (either float, double or quad) + * @param outputs - the output audio buffers as an array of non-interleaved FAUSTFLOAT + * samples (either float, double or quad) + * + */ + virtual void compute(double /*date_usec*/, int count, FAUSTFLOAT** inputs, + FAUSTFLOAT** outputs) + { + compute(count, inputs, outputs); + } +}; + +/** + * Generic DSP decorator. + */ - virtual int getNumInputs() { return fDSP->getNumInputs(); } - virtual int getNumOutputs() { return fDSP->getNumOutputs(); } - virtual void buildUserInterface(UI* ui_interface) { fDSP->buildUserInterface(ui_interface); } - virtual int getSampleRate() { return fDSP->getSampleRate(); } - virtual void init(int sample_rate) { fDSP->init(sample_rate); } - virtual void instanceInit(int sample_rate) { fDSP->instanceInit(sample_rate); } - virtual void instanceConstants(int sample_rate) { fDSP->instanceConstants(sample_rate); } - virtual void instanceResetUserInterface() { fDSP->instanceResetUserInterface(); } - virtual void instanceClear() { fDSP->instanceClear(); } - virtual decorator_dsp* clone() { return new decorator_dsp(fDSP->clone()); } - virtual void metadata(Meta* m) { fDSP->metadata(m); } - // Beware: subclasses usually have to overload the two 'compute' methods - virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { fDSP->compute(count, inputs, outputs); } - virtual void compute(double date_usec, int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { fDSP->compute(date_usec, count, inputs, outputs); } - +class FAUST_API decorator_dsp : public dsp +{ + protected: + dsp* fDSP; + + public: + decorator_dsp(dsp* dsp = nullptr) : fDSP(dsp) {} + virtual ~decorator_dsp() { delete fDSP; } + + virtual int getNumInputs() { return fDSP->getNumInputs(); } + virtual int getNumOutputs() { return fDSP->getNumOutputs(); } + virtual void buildUserInterface(UI* ui_interface) + { + fDSP->buildUserInterface(ui_interface); + } + virtual int getSampleRate() { return fDSP->getSampleRate(); } + virtual void init(int sample_rate) { fDSP->init(sample_rate); } + virtual void instanceInit(int sample_rate) { fDSP->instanceInit(sample_rate); } + virtual void instanceConstants(int sample_rate) + { + fDSP->instanceConstants(sample_rate); + } + virtual void instanceResetUserInterface() { fDSP->instanceResetUserInterface(); } + virtual void instanceClear() { fDSP->instanceClear(); } + virtual decorator_dsp* clone() { return new decorator_dsp(fDSP->clone()); } + virtual void metadata(Meta* m) { fDSP->metadata(m); } + // Beware: subclasses usually have to overload the two 'compute' methods + virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) + { + fDSP->compute(count, inputs, outputs); + } + virtual void compute(double date_usec, int count, FAUSTFLOAT** inputs, + FAUSTFLOAT** outputs) + { + fDSP->compute(date_usec, count, inputs, outputs); + } }; /** @@ -277,86 +293,77 @@ class FAUST_API decorator_dsp : public dsp { * to create DSP instances from a compiled DSP program. */ -class FAUST_API dsp_factory { - - protected: - - // So that to force sub-classes to use deleteDSPFactory(dsp_factory* factory); - virtual ~dsp_factory() {} - - public: - - virtual std::string getName() = 0; - virtual std::string getSHAKey() = 0; - virtual std::string getDSPCode() = 0; - virtual std::string getCompileOptions() = 0; - virtual std::vector getLibraryList() = 0; - virtual std::vector getIncludePathnames() = 0; - - virtual dsp* createDSPInstance() = 0; - - virtual void setMemoryManager(dsp_memory_manager* manager) = 0; - virtual dsp_memory_manager* getMemoryManager() = 0; - +class FAUST_API dsp_factory +{ + protected: + // So that to force sub-classes to use deleteDSPFactory(dsp_factory* factory); + virtual ~dsp_factory() {} + + public: + virtual std::string getName() = 0; + virtual std::string getSHAKey() = 0; + virtual std::string getDSPCode() = 0; + virtual std::string getCompileOptions() = 0; + virtual std::vector getLibraryList() = 0; + virtual std::vector getIncludePathnames() = 0; + + virtual dsp* createDSPInstance() = 0; + + virtual void setMemoryManager(dsp_memory_manager* manager) = 0; + virtual dsp_memory_manager* getMemoryManager() = 0; }; // Denormal handling -#if defined (__SSE__) +#if defined(__SSE__) #include #endif -class FAUST_API ScopedNoDenormals { - - private: - - intptr_t fpsr = 0; - - void setFpStatusRegister(intptr_t fpsr_aux) noexcept - { - #if defined (__arm64__) || defined (__aarch64__) - asm volatile("msr fpcr, %0" : : "ri" (fpsr_aux)); - #elif defined (__SSE__) - // The volatile keyword here is needed to workaround a bug in AppleClang 13.0 - // which aggressively optimises away the variable otherwise - volatile uint32_t fpsr_w = static_cast(fpsr_aux); - _mm_setcsr(fpsr_w); - #endif - } - - void getFpStatusRegister() noexcept - { - #if defined (__arm64__) || defined (__aarch64__) - asm volatile("mrs %0, fpcr" : "=r" (fpsr)); - #elif defined (__SSE__) - fpsr = static_cast(_mm_getcsr()); - #endif - } - - public: - - ScopedNoDenormals() noexcept - { - #if defined (__arm64__) || defined (__aarch64__) - intptr_t mask = (1 << 24 /* FZ */); - #elif defined (__SSE__) - #if defined (__SSE2__) - intptr_t mask = 0x8040; - #else - intptr_t mask = 0x8000; - #endif - #else - intptr_t mask = 0x0000; - #endif - getFpStatusRegister(); - setFpStatusRegister(fpsr | mask); - } - - ~ScopedNoDenormals() noexcept - { - setFpStatusRegister(fpsr); - } +class FAUST_API ScopedNoDenormals +{ + private: + intptr_t fpsr = 0; + + void setFpStatusRegister(intptr_t fpsr_aux) noexcept + { +#if defined(__arm64__) || defined(__aarch64__) + asm volatile("msr fpcr, %0" : : "ri"(fpsr_aux)); +#elif defined(__SSE__) + // The volatile keyword here is needed to workaround a bug in AppleClang 13.0 + // which aggressively optimises away the variable otherwise + volatile uint32_t fpsr_w = static_cast(fpsr_aux); + _mm_setcsr(fpsr_w); +#endif + } + + void getFpStatusRegister() noexcept + { +#if defined(__arm64__) || defined(__aarch64__) + asm volatile("mrs %0, fpcr" : "=r"(fpsr)); +#elif defined(__SSE__) + fpsr = static_cast(_mm_getcsr()); +#endif + } + + public: + ScopedNoDenormals() noexcept + { +#if defined(__arm64__) || defined(__aarch64__) + intptr_t mask = (1 << 24 /* FZ */); +#elif defined(__SSE__) +#if defined(__SSE2__) + intptr_t mask = 0x8040; +#else + intptr_t mask = 0x8000; +#endif +#else + intptr_t mask = 0x0000; +#endif + getFpStatusRegister(); + setFpStatusRegister(fpsr | mask); + } + ~ScopedNoDenormals() noexcept { setFpStatusRegister(fpsr); } }; #define AVOIDDENORMALS ScopedNoDenormals ftz_scope; @@ -391,11 +398,12 @@ architecture section is not modified. #ifndef API_UI_H #define API_UI_H +#include + +#include #include #include #include -#include -#include /************************** BEGIN meta.h ******************************* FAUST Architecture File @@ -405,16 +413,16 @@ architecture section is not modified. it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + EXCEPTION : As a special exception, you may create a larger work that contains this FAUST architecture section and distribute that work under terms of your choice, so long as this FAUST @@ -424,9 +432,9 @@ architecture section is not modified. #ifndef __meta__ #define __meta__ - /** - The base class of Meta handler to be used in dsp::metadata(Meta* m) method to retrieve (key, value) metadata. + The base class of Meta handler to be used in dsp::metadata(Meta* m) method to retrieve + (key, value) metadata. */ struct FAUST_API Meta { virtual ~Meta() {} @@ -443,16 +451,16 @@ struct FAUST_API Meta { it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + EXCEPTION : As a special exception, you may create a larger work that contains this FAUST architecture section and distribute that work under terms of your choice, so long as this FAUST @@ -462,7 +470,6 @@ struct FAUST_API Meta { #ifndef __UI_H__ #define __UI_H__ - #ifndef FAUSTFLOAT #define FAUSTFLOAT float #endif @@ -476,40 +483,45 @@ struct FAUST_API Meta { struct Soundfile; -template +template struct FAUST_API UIReal { - UIReal() {} virtual ~UIReal() {} - + // -- widget's layouts - - virtual void openTabBox(const char* label) = 0; + + virtual void openTabBox(const char* label) = 0; virtual void openHorizontalBox(const char* label) = 0; - virtual void openVerticalBox(const char* label) = 0; - virtual void closeBox() = 0; - + virtual void openVerticalBox(const char* label) = 0; + virtual void closeBox() = 0; + // -- active widgets - - virtual void addButton(const char* label, REAL* zone) = 0; + + virtual void addButton(const char* label, REAL* zone) = 0; virtual void addCheckButton(const char* label, REAL* zone) = 0; - virtual void addVerticalSlider(const char* label, REAL* zone, REAL init, REAL min, REAL max, REAL step) = 0; - virtual void addHorizontalSlider(const char* label, REAL* zone, REAL init, REAL min, REAL max, REAL step) = 0; - virtual void addNumEntry(const char* label, REAL* zone, REAL init, REAL min, REAL max, REAL step) = 0; - + virtual void addVerticalSlider(const char* label, REAL* zone, REAL init, REAL min, + REAL max, REAL step) = 0; + virtual void addHorizontalSlider(const char* label, REAL* zone, REAL init, REAL min, + REAL max, REAL step) = 0; + virtual void addNumEntry(const char* label, REAL* zone, REAL init, REAL min, REAL max, + REAL step) = 0; + // -- passive widgets - - virtual void addHorizontalBargraph(const char* label, REAL* zone, REAL min, REAL max) = 0; - virtual void addVerticalBargraph(const char* label, REAL* zone, REAL min, REAL max) = 0; - + + virtual void addHorizontalBargraph(const char* label, REAL* zone, REAL min, + REAL max) = 0; + virtual void addVerticalBargraph(const char* label, REAL* zone, REAL min, + REAL max) = 0; + // -- soundfiles - - virtual void addSoundfile(const char* label, const char* filename, Soundfile** sf_zone) = 0; - + + virtual void addSoundfile(const char* label, const char* filename, + Soundfile** sf_zone) = 0; + // -- metadata declarations - + virtual void declare(REAL* /*zone*/, const char* /*key*/, const char* /*val*/) {} - + // To be used by LLVM client virtual int sizeOfFAUSTFLOAT() { return sizeof(FAUSTFLOAT); } }; @@ -529,16 +541,16 @@ struct FAUST_API UI : public UIReal { it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + EXCEPTION : As a special exception, you may create a larger work that contains this FAUST architecture section and distribute that work under terms of your choice, so long as this FAUST @@ -548,187 +560,199 @@ struct FAUST_API UI : public UIReal { #ifndef __PathBuilder__ #define __PathBuilder__ -#include -#include -#include -#include #include +#include #include - +#include +#include +#include /******************************************************************************* * PathBuilder : Faust User Interface * Helper class to build complete hierarchical path for UI items. ******************************************************************************/ -class FAUST_API PathBuilder { - - protected: - - std::vector fControlsLevel; - std::vector fFullPaths; - std::map fFull2Short; // filled by computeShortNames() - - /** - * @brief check if a character is acceptable for an ID - * - * @param c - * @return true is the character is acceptable for an ID - */ - bool isIDChar(char c) const - { - return ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) || ((c >= '0') && (c <= '9')); - } - - /** - * @brief remove all "/0x00" parts - * - * @param src - * @return modified string - */ - std::string remove0x00(const std::string& src) const - { - return std::regex_replace(src, std::regex("/0x00"), ""); - } - - /** - * @brief replace all non ID char with '_' (one '_' may replace several non ID char) - * - * @param src - * @return modified string - */ - std::string str2ID(const std::string& src) const - { - std::string dst; - bool need_underscore = false; - for (char c : src) { - if (isIDChar(c) || (c == '/')) { - if (need_underscore) { - dst.push_back('_'); - need_underscore = false; - } - dst.push_back(c); - } else { - need_underscore = true; +class FAUST_API PathBuilder +{ + protected: + std::vector fControlsLevel; + std::vector fFullPaths; + std::map fFull2Short; // filled by computeShortNames() + + /** + * @brief check if a character is acceptable for an ID + * + * @param c + * @return true is the character is acceptable for an ID + */ + bool isIDChar(char c) const + { + return ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) + || ((c >= '0') && (c <= '9')); + } + + /** + * @brief remove all "/0x00" parts + * + * @param src + * @return modified string + */ + std::string remove0x00(const std::string& src) const + { + return std::regex_replace(src, std::regex("/0x00"), ""); + } + + /** + * @brief replace all non ID char with '_' (one '_' may replace several non ID char) + * + * @param src + * @return modified string + */ + std::string str2ID(const std::string& src) const + { + std::string dst; + bool need_underscore = false; + for (char c : src) { + if (isIDChar(c) || (c == '/')) { + if (need_underscore) { + dst.push_back('_'); + need_underscore = false; } + dst.push_back(c); + } else { + need_underscore = true; } - return dst; } - - /** - * @brief Keep only the last n slash-parts - * - * @param src - * @param n : 1 indicates the last slash-part - * @return modified string - */ - std::string cut(const std::string& src, int n) const - { - std::string rdst; - for (int i = int(src.length())-1; i >= 0; i--) { - char c = src[i]; - if (c != '/') { - rdst.push_back(c); - } else if (n == 1) { - std::string dst; - for (int j = int(rdst.length())-1; j >= 0; j--) { - dst.push_back(rdst[j]); - } - return dst; - } else { - n--; - rdst.push_back(c); + return dst; + } + + /** + * @brief Keep only the last n slash-parts + * + * @param src + * @param n : 1 indicates the last slash-part + * @return modified string + */ + std::string cut(const std::string& src, int n) const + { + std::string rdst; + for (int i = int(src.length()) - 1; i >= 0; i--) { + char c = src[i]; + if (c != '/') { + rdst.push_back(c); + } else if (n == 1) { + std::string dst; + for (int j = int(rdst.length()) - 1; j >= 0; j--) { + dst.push_back(rdst[j]); } + return dst; + } else { + n--; + rdst.push_back(c); } - return src; } - - void addFullPath(const std::string& label) { fFullPaths.push_back(buildPath(label)); } - - /** - * @brief Compute the mapping between full path and short names - */ - void computeShortNames() - { - std::vector uniquePaths; // all full paths transformed but made unique with a prefix - std::map unique2full; // all full paths transformed but made unique with a prefix - char num_buffer[16]; - int pnum = 0; - - for (const auto& s : fFullPaths) { - sprintf(num_buffer, "%d", pnum++); - std::string u = "/P" + std::string(num_buffer) + str2ID(remove0x00(s)); - uniquePaths.push_back(u); - unique2full[u] = s; // remember the full path associated to a unique path - } - - std::map uniquePath2level; // map path to level - for (const auto& s : uniquePaths) uniquePath2level[s] = 1; // we init all levels to 1 - bool have_collisions = true; - - while (have_collisions) { - // compute collision list - std::set collisionSet; - std::map short2full; - have_collisions = false; - for (const auto& it : uniquePath2level) { - std::string u = it.first; - int n = it.second; - std::string shortName = cut(u, n); - auto p = short2full.find(shortName); - if (p == short2full.end()) { - // no collision - short2full[shortName] = u; - } else { - // we have a collision, add the two paths to the collision set - have_collisions = true; - collisionSet.insert(u); - collisionSet.insert(p->second); - } - } - for (const auto& s : collisionSet) uniquePath2level[s]++; // increase level of colliding path - } - + return src; + } + + void addFullPath(const std::string& label) { fFullPaths.push_back(buildPath(label)); } + + /** + * @brief Compute the mapping between full path and short names + */ + void computeShortNames() + { + std::vector + uniquePaths; // all full paths transformed but made unique with a prefix + std::map + unique2full; // all full paths transformed but made unique with a prefix + char num_buffer[16]; + int pnum = 0; + + for (const auto& s : fFullPaths) { + sprintf(num_buffer, "%d", pnum++); + std::string u = "/P" + std::string(num_buffer) + str2ID(remove0x00(s)); + uniquePaths.push_back(u); + unique2full[u] = s; // remember the full path associated to a unique path + } + + std::map uniquePath2level; // map path to level + for (const auto& s : uniquePaths) + uniquePath2level[s] = 1; // we init all levels to 1 + bool have_collisions = true; + + while (have_collisions) { + // compute collision list + std::set collisionSet; + std::map short2full; + have_collisions = false; for (const auto& it : uniquePath2level) { - std::string u = it.first; - int n = it.second; - std::string shortName = replaceCharList(cut(u, n), {'/'}, '_'); - fFull2Short[unique2full[u]] = shortName; + std::string u = it.first; + int n = it.second; + std::string shortName = cut(u, n); + auto p = short2full.find(shortName); + if (p == short2full.end()) { + // no collision + short2full[shortName] = u; + } else { + // we have a collision, add the two paths to the collision set + have_collisions = true; + collisionSet.insert(u); + collisionSet.insert(p->second); + } } + for (const auto& s : collisionSet) + uniquePath2level[s]++; // increase level of colliding path } - - std::string replaceCharList(const std::string& str, const std::vector& ch1, char ch2) - { - auto beg = ch1.begin(); - auto end = ch1.end(); - std::string res = str; - for (size_t i = 0; i < str.length(); ++i) { - if (std::find(beg, end, str[i]) != end) res[i] = ch2; - } - return res; + + for (const auto& it : uniquePath2level) { + std::string u = it.first; + int n = it.second; + std::string shortName = replaceCharList(cut(u, n), {'/'}, '_'); + fFull2Short[unique2full[u]] = shortName; } - - public: - - PathBuilder() {} - virtual ~PathBuilder() {} - - // Return true for the first level of groups - bool pushLabel(const std::string& label) { fControlsLevel.push_back(label); return fControlsLevel.size() == 1;} - - // Return true for the last level of groups - bool popLabel() { fControlsLevel.pop_back(); return fControlsLevel.size() == 0; } - - std::string buildPath(const std::string& label) - { - std::string res = "/"; - for (size_t i = 0; i < fControlsLevel.size(); i++) { - res = res + fControlsLevel[i] + "/"; - } - res += label; - return replaceCharList(res, {' ', '#', '*', ',', '?', '[', ']', '{', '}', '(', ')'}, '_'); + } + + std::string replaceCharList(const std::string& str, const std::vector& ch1, + char ch2) + { + auto beg = ch1.begin(); + auto end = ch1.end(); + std::string res = str; + for (size_t i = 0; i < str.length(); ++i) { + if (std::find(beg, end, str[i]) != end) + res[i] = ch2; } - + return res; + } + + public: + PathBuilder() {} + virtual ~PathBuilder() {} + + // Return true for the first level of groups + bool pushLabel(const std::string& label) + { + fControlsLevel.push_back(label); + return fControlsLevel.size() == 1; + } + + // Return true for the last level of groups + bool popLabel() + { + fControlsLevel.pop_back(); + return fControlsLevel.size() == 0; + } + + std::string buildPath(const std::string& label) + { + std::string res = "/"; + for (size_t i = 0; i < fControlsLevel.size(); i++) { + res = res + fControlsLevel[i] + "/"; + } + res += label; + return replaceCharList( + res, {' ', '#', '*', ',', '?', '[', ']', '{', '}', '(', ')'}, '_'); + } }; #endif // __PathBuilder__ @@ -741,16 +765,16 @@ class FAUST_API PathBuilder { it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + EXCEPTION : As a special exception, you may create a larger work that contains this FAUST architecture section and distribute that work under terms of your choice, so long as this FAUST @@ -763,52 +787,53 @@ class FAUST_API PathBuilder { /*************************************************************************************** ValueConverter.h (GRAME, Copyright 2015-2019) - + Set of conversion objects used to map user interface values (for example a gui slider delivering values between 0 and 1) to faust values (for example a vslider between 20 and 20000) using a log scale. - + -- Utilities - + Range(lo,hi) : clip a value x between lo and hi - Interpolator(lo,hi,v1,v2) : Maps a value x between lo and hi to a value y between v1 and v2 - Interpolator3pt(lo,mi,hi,v1,vm,v2) : Map values between lo mid hi to values between v1 vm v2 - + Interpolator(lo,hi,v1,v2) : Maps a value x between lo and hi to a value y between v1 and +v2 Interpolator3pt(lo,mi,hi,v1,vm,v2) : Map values between lo mid hi to values between v1 +vm v2 + -- Value Converters - + ValueConverter::ui2faust(x) ValueConverter::faust2ui(x) - + -- ValueConverters used for sliders depending of the scale - + LinearValueConverter(umin, umax, fmin, fmax) LinearValueConverter2(lo, mi, hi, v1, vm, v2) using 2 segments LogValueConverter(umin, umax, fmin, fmax) ExpValueConverter(umin, umax, fmin, fmax) - + -- ValueConverters used for accelerometers based on 3 points - + AccUpConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 0 AccDownConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 1 AccUpDownConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 2 AccDownUpConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 3 - + -- lists of ZoneControl are used to implement accelerometers metadata for each axes - + ZoneControl(zone, valueConverter) : a zone with an accelerometer data converter - + -- ZoneReader are used to implement screencolor metadata - + ZoneReader(zone, valueConverter) : a zone with a data converter ****************************************************************************************/ +#include #include -#include // std::max + +#include // std::max #include #include -#include - //-------------------------------------------------------------------------------------- // Interpolator(lo,hi,v1,v2) @@ -819,458 +844,485 @@ class FAUST_API PathBuilder { // y = v1 - lo*coef + x*coef // y = offset + x*coef with offset = v1 - lo*coef //-------------------------------------------------------------------------------------- -class FAUST_API Interpolator { - - private: - - //-------------------------------------------------------------------------------------- - // Range(lo,hi) clip a value between lo and hi - //-------------------------------------------------------------------------------------- - struct Range - { - double fLo; - double fHi; - - Range(double x, double y) : fLo(std::min(x,y)), fHi(std::max(x,y)) {} - double operator()(double x) { return (xfHi) ? fHi : x; } - }; - - - Range fRange; - double fCoef; - double fOffset; - - public: - - Interpolator(double lo, double hi, double v1, double v2) : fRange(lo,hi) +class FAUST_API Interpolator +{ + private: + //-------------------------------------------------------------------------------------- + // Range(lo,hi) clip a value between lo and hi + //-------------------------------------------------------------------------------------- + struct Range { + double fLo; + double fHi; + + Range(double x, double y) + : fLo(std::min(x, y)), fHi(std::max(x, y)) { - if (hi != lo) { - // regular case - fCoef = (v2-v1)/(hi-lo); - fOffset = v1 - lo*fCoef; - } else { - // degenerate case, avoids division by zero - fCoef = 0; - fOffset = (v1+v2)/2; - } } - double operator()(double v) - { - double x = fRange(v); - return fOffset + x*fCoef; - } - - void getLowHigh(double& amin, double& amax) - { - amin = fRange.fLo; - amax = fRange.fHi; + double operator()(double x) { return (x < fLo) ? fLo : (x > fHi) ? fHi : x; } + }; + + Range fRange; + double fCoef; + double fOffset; + + public: + Interpolator(double lo, double hi, double v1, double v2) : fRange(lo, hi) + { + if (hi != lo) { + // regular case + fCoef = (v2 - v1) / (hi - lo); + fOffset = v1 - lo * fCoef; + } else { + // degenerate case, avoids division by zero + fCoef = 0; + fOffset = (v1 + v2) / 2; } + } + double operator()(double v) + { + double x = fRange(v); + return fOffset + x * fCoef; + } + + void getLowHigh(double& amin, double& amax) + { + amin = fRange.fLo; + amax = fRange.fHi; + } }; //-------------------------------------------------------------------------------------- // Interpolator3pt(lo,mi,hi,v1,vm,v2) // Map values between lo mid hi to values between v1 vm v2 //-------------------------------------------------------------------------------------- -class FAUST_API Interpolator3pt { - - private: - - Interpolator fSegment1; - Interpolator fSegment2; - double fMid; - - public: - - Interpolator3pt(double lo, double mi, double hi, double v1, double vm, double v2) : - fSegment1(lo, mi, v1, vm), - fSegment2(mi, hi, vm, v2), - fMid(mi) {} - double operator()(double x) { return (x < fMid) ? fSegment1(x) : fSegment2(x); } - - void getMappingValues(double& amin, double& amid, double& amax) - { - fSegment1.getLowHigh(amin, amid); - fSegment2.getLowHigh(amid, amax); - } +class FAUST_API Interpolator3pt +{ + private: + Interpolator fSegment1; + Interpolator fSegment2; + double fMid; + + public: + Interpolator3pt(double lo, double mi, double hi, double v1, double vm, double v2) + : fSegment1(lo, mi, v1, vm), fSegment2(mi, hi, vm, v2), fMid(mi) + { + } + double operator()(double x) { return (x < fMid) ? fSegment1(x) : fSegment2(x); } + + void getMappingValues(double& amin, double& amid, double& amax) + { + fSegment1.getLowHigh(amin, amid); + fSegment2.getLowHigh(amid, amax); + } }; //-------------------------------------------------------------------------------------- // Abstract ValueConverter class. Converts values between UI and Faust representations //-------------------------------------------------------------------------------------- -class FAUST_API ValueConverter { - - public: - - virtual ~ValueConverter() {} - virtual double ui2faust(double x) { return x; }; - virtual double faust2ui(double x) { return x; }; +class FAUST_API ValueConverter +{ + public: + virtual ~ValueConverter() {} + virtual double ui2faust(double x) { return x; }; + virtual double faust2ui(double x) { return x; }; }; //-------------------------------------------------------------------------------------- // A converter than can be updated //-------------------------------------------------------------------------------------- -class FAUST_API UpdatableValueConverter : public ValueConverter { - - protected: - - bool fActive; - - public: - - UpdatableValueConverter():fActive(true) - {} - virtual ~UpdatableValueConverter() - {} - - virtual void setMappingValues(double amin, double amid, double amax, double min, double init, double max) = 0; - virtual void getMappingValues(double& amin, double& amid, double& amax) = 0; - - void setActive(bool on_off) { fActive = on_off; } - bool getActive() { return fActive; } - +class FAUST_API UpdatableValueConverter : public ValueConverter +{ + protected: + bool fActive; + + public: + UpdatableValueConverter() : fActive(true) {} + virtual ~UpdatableValueConverter() {} + + virtual void setMappingValues(double amin, double amid, double amax, double min, + double init, double max) = 0; + virtual void getMappingValues(double& amin, double& amid, double& amax) = 0; + + void setActive(bool on_off) { fActive = on_off; } + bool getActive() { return fActive; } }; //-------------------------------------------------------------------------------------- // Linear conversion between ui and Faust values //-------------------------------------------------------------------------------------- -class FAUST_API LinearValueConverter : public ValueConverter { - - private: - - Interpolator fUI2F; - Interpolator fF2UI; - - public: - - LinearValueConverter(double umin, double umax, double fmin, double fmax) : - fUI2F(umin,umax,fmin,fmax), fF2UI(fmin,fmax,umin,umax) - {} - - LinearValueConverter() : fUI2F(0.,0.,0.,0.), fF2UI(0.,0.,0.,0.) - {} - virtual double ui2faust(double x) { return fUI2F(x); } - virtual double faust2ui(double x) { return fF2UI(x); } - +class FAUST_API LinearValueConverter : public ValueConverter +{ + private: + Interpolator fUI2F; + Interpolator fF2UI; + + public: + LinearValueConverter(double umin, double umax, double fmin, double fmax) + : fUI2F(umin, umax, fmin, fmax), fF2UI(fmin, fmax, umin, umax) + { + } + + LinearValueConverter() : fUI2F(0., 0., 0., 0.), fF2UI(0., 0., 0., 0.) {} + virtual double ui2faust(double x) { return fUI2F(x); } + virtual double faust2ui(double x) { return fF2UI(x); } }; //-------------------------------------------------------------------------------------- // Two segments linear conversion between ui and Faust values //-------------------------------------------------------------------------------------- -class FAUST_API LinearValueConverter2 : public UpdatableValueConverter { - - private: - - Interpolator3pt fUI2F; - Interpolator3pt fF2UI; - - public: - - LinearValueConverter2(double amin, double amid, double amax, double min, double init, double max) : - fUI2F(amin, amid, amax, min, init, max), fF2UI(min, init, max, amin, amid, amax) - {} - - LinearValueConverter2() : fUI2F(0.,0.,0.,0.,0.,0.), fF2UI(0.,0.,0.,0.,0.,0.) - {} - - virtual double ui2faust(double x) { return fUI2F(x); } - virtual double faust2ui(double x) { return fF2UI(x); } - - virtual void setMappingValues(double amin, double amid, double amax, double min, double init, double max) - { - fUI2F = Interpolator3pt(amin, amid, amax, min, init, max); - fF2UI = Interpolator3pt(min, init, max, amin, amid, amax); - } - - virtual void getMappingValues(double& amin, double& amid, double& amax) - { - fUI2F.getMappingValues(amin, amid, amax); - } - +class FAUST_API LinearValueConverter2 : public UpdatableValueConverter +{ + private: + Interpolator3pt fUI2F; + Interpolator3pt fF2UI; + + public: + LinearValueConverter2(double amin, double amid, double amax, double min, double init, + double max) + : fUI2F(amin, amid, amax, min, init, max), fF2UI(min, init, max, amin, amid, amax) + { + } + + LinearValueConverter2() : fUI2F(0., 0., 0., 0., 0., 0.), fF2UI(0., 0., 0., 0., 0., 0.) + { + } + + virtual double ui2faust(double x) { return fUI2F(x); } + virtual double faust2ui(double x) { return fF2UI(x); } + + virtual void setMappingValues(double amin, double amid, double amax, double min, + double init, double max) + { + fUI2F = Interpolator3pt(amin, amid, amax, min, init, max); + fF2UI = Interpolator3pt(min, init, max, amin, amid, amax); + } + + virtual void getMappingValues(double& amin, double& amid, double& amax) + { + fUI2F.getMappingValues(amin, amid, amax); + } }; //-------------------------------------------------------------------------------------- // Logarithmic conversion between ui and Faust values //-------------------------------------------------------------------------------------- -class FAUST_API LogValueConverter : public LinearValueConverter { - - public: - - LogValueConverter(double umin, double umax, double fmin, double fmax) : - LinearValueConverter(umin, umax, std::log(std::max(DBL_MIN, fmin)), std::log(std::max(DBL_MIN, fmax))) - {} - - virtual double ui2faust(double x) { return std::exp(LinearValueConverter::ui2faust(x)); } - virtual double faust2ui(double x) { return LinearValueConverter::faust2ui(std::log(std::max(x, DBL_MIN))); } - +class FAUST_API LogValueConverter : public LinearValueConverter +{ + public: + LogValueConverter(double umin, double umax, double fmin, double fmax) + : LinearValueConverter(umin, umax, std::log(std::max(DBL_MIN, fmin)), + std::log(std::max(DBL_MIN, fmax))) + { + } + + virtual double ui2faust(double x) + { + return std::exp(LinearValueConverter::ui2faust(x)); + } + virtual double faust2ui(double x) + { + return LinearValueConverter::faust2ui(std::log(std::max(x, DBL_MIN))); + } }; //-------------------------------------------------------------------------------------- // Exponential conversion between ui and Faust values //-------------------------------------------------------------------------------------- -class FAUST_API ExpValueConverter : public LinearValueConverter { - - public: - - ExpValueConverter(double umin, double umax, double fmin, double fmax) : - LinearValueConverter(umin, umax, std::min(DBL_MAX, std::exp(fmin)), std::min(DBL_MAX, std::exp(fmax))) - {} - - virtual double ui2faust(double x) { return std::log(LinearValueConverter::ui2faust(x)); } - virtual double faust2ui(double x) { return LinearValueConverter::faust2ui(std::min(DBL_MAX, std::exp(x))); } - +class FAUST_API ExpValueConverter : public LinearValueConverter +{ + public: + ExpValueConverter(double umin, double umax, double fmin, double fmax) + : LinearValueConverter(umin, umax, std::min(DBL_MAX, std::exp(fmin)), + std::min(DBL_MAX, std::exp(fmax))) + { + } + + virtual double ui2faust(double x) + { + return std::log(LinearValueConverter::ui2faust(x)); + } + virtual double faust2ui(double x) + { + return LinearValueConverter::faust2ui(std::min(DBL_MAX, std::exp(x))); + } }; //-------------------------------------------------------------------------------------- // Convert accelerometer or gyroscope values to Faust values // Using an Up curve (curve 0) //-------------------------------------------------------------------------------------- -class FAUST_API AccUpConverter : public UpdatableValueConverter { - - private: - - Interpolator3pt fA2F; - Interpolator3pt fF2A; - - public: - - AccUpConverter(double amin, double amid, double amax, double fmin, double fmid, double fmax) : - fA2F(amin,amid,amax,fmin,fmid,fmax), - fF2A(fmin,fmid,fmax,amin,amid,amax) - {} - - virtual double ui2faust(double x) { return fA2F(x); } - virtual double faust2ui(double x) { return fF2A(x); } - - virtual void setMappingValues(double amin, double amid, double amax, double fmin, double fmid, double fmax) - { - //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccUpConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax); - fA2F = Interpolator3pt(amin, amid, amax, fmin, fmid, fmax); - fF2A = Interpolator3pt(fmin, fmid, fmax, amin, amid, amax); - } - - virtual void getMappingValues(double& amin, double& amid, double& amax) - { - fA2F.getMappingValues(amin, amid, amax); - } - +class FAUST_API AccUpConverter : public UpdatableValueConverter +{ + private: + Interpolator3pt fA2F; + Interpolator3pt fF2A; + + public: + AccUpConverter(double amin, double amid, double amax, double fmin, double fmid, + double fmax) + : fA2F(amin, amid, amax, fmin, fmid, fmax) + , fF2A(fmin, fmid, fmax, amin, amid, amax) + { + } + + virtual double ui2faust(double x) { return fA2F(x); } + virtual double faust2ui(double x) { return fF2A(x); } + + virtual void setMappingValues(double amin, double amid, double amax, double fmin, + double fmid, double fmax) + { + //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccUpConverter update %f %f %f + //%f %f %f", amin,amid,amax,fmin,fmid,fmax); + fA2F = Interpolator3pt(amin, amid, amax, fmin, fmid, fmax); + fF2A = Interpolator3pt(fmin, fmid, fmax, amin, amid, amax); + } + + virtual void getMappingValues(double& amin, double& amid, double& amax) + { + fA2F.getMappingValues(amin, amid, amax); + } }; //-------------------------------------------------------------------------------------- // Convert accelerometer or gyroscope values to Faust values // Using a Down curve (curve 1) //-------------------------------------------------------------------------------------- -class FAUST_API AccDownConverter : public UpdatableValueConverter { - - private: - - Interpolator3pt fA2F; - Interpolator3pt fF2A; - - public: - - AccDownConverter(double amin, double amid, double amax, double fmin, double fmid, double fmax) : - fA2F(amin,amid,amax,fmax,fmid,fmin), - fF2A(fmin,fmid,fmax,amax,amid,amin) - {} - - virtual double ui2faust(double x) { return fA2F(x); } - virtual double faust2ui(double x) { return fF2A(x); } - - virtual void setMappingValues(double amin, double amid, double amax, double fmin, double fmid, double fmax) - { - //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccDownConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax); - fA2F = Interpolator3pt(amin, amid, amax, fmax, fmid, fmin); - fF2A = Interpolator3pt(fmin, fmid, fmax, amax, amid, amin); - } - - virtual void getMappingValues(double& amin, double& amid, double& amax) - { - fA2F.getMappingValues(amin, amid, amax); - } +class FAUST_API AccDownConverter : public UpdatableValueConverter +{ + private: + Interpolator3pt fA2F; + Interpolator3pt fF2A; + + public: + AccDownConverter(double amin, double amid, double amax, double fmin, double fmid, + double fmax) + : fA2F(amin, amid, amax, fmax, fmid, fmin) + , fF2A(fmin, fmid, fmax, amax, amid, amin) + { + } + + virtual double ui2faust(double x) { return fA2F(x); } + virtual double faust2ui(double x) { return fF2A(x); } + + virtual void setMappingValues(double amin, double amid, double amax, double fmin, + double fmid, double fmax) + { + //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccDownConverter update %f %f + //%f %f %f %f", amin,amid,amax,fmin,fmid,fmax); + fA2F = Interpolator3pt(amin, amid, amax, fmax, fmid, fmin); + fF2A = Interpolator3pt(fmin, fmid, fmax, amax, amid, amin); + } + + virtual void getMappingValues(double& amin, double& amid, double& amax) + { + fA2F.getMappingValues(amin, amid, amax); + } }; //-------------------------------------------------------------------------------------- // Convert accelerometer or gyroscope values to Faust values // Using an Up-Down curve (curve 2) //-------------------------------------------------------------------------------------- -class FAUST_API AccUpDownConverter : public UpdatableValueConverter { - - private: - - Interpolator3pt fA2F; - Interpolator fF2A; - - public: - - AccUpDownConverter(double amin, double amid, double amax, double fmin, double /*fmid*/, double fmax) : - fA2F(amin,amid,amax,fmin,fmax,fmin), - fF2A(fmin,fmax,amin,amax) // Special, pseudo inverse of a non monotonic function - {} - - virtual double ui2faust(double x) { return fA2F(x); } - virtual double faust2ui(double x) { return fF2A(x); } - - virtual void setMappingValues(double amin, double amid, double amax, double fmin, double /*fmid*/, double fmax) - { - //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccUpDownConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax); - fA2F = Interpolator3pt(amin, amid, amax, fmin, fmax, fmin); - fF2A = Interpolator(fmin, fmax, amin, amax); - } - - virtual void getMappingValues(double& amin, double& amid, double& amax) - { - fA2F.getMappingValues(amin, amid, amax); - } +class FAUST_API AccUpDownConverter : public UpdatableValueConverter +{ + private: + Interpolator3pt fA2F; + Interpolator fF2A; + + public: + AccUpDownConverter(double amin, double amid, double amax, double fmin, + double /*fmid*/, double fmax) + : fA2F(amin, amid, amax, fmin, fmax, fmin) + , fF2A(fmin, fmax, amin, + amax) // Special, pseudo inverse of a non monotonic function + { + } + + virtual double ui2faust(double x) { return fA2F(x); } + virtual double faust2ui(double x) { return fF2A(x); } + + virtual void setMappingValues(double amin, double amid, double amax, double fmin, + double /*fmid*/, double fmax) + { + //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccUpDownConverter update %f %f + //%f %f %f %f", amin,amid,amax,fmin,fmid,fmax); + fA2F = Interpolator3pt(amin, amid, amax, fmin, fmax, fmin); + fF2A = Interpolator(fmin, fmax, amin, amax); + } + + virtual void getMappingValues(double& amin, double& amid, double& amax) + { + fA2F.getMappingValues(amin, amid, amax); + } }; //-------------------------------------------------------------------------------------- // Convert accelerometer or gyroscope values to Faust values // Using a Down-Up curve (curve 3) //-------------------------------------------------------------------------------------- -class FAUST_API AccDownUpConverter : public UpdatableValueConverter { - - private: - - Interpolator3pt fA2F; - Interpolator fF2A; - - public: - - AccDownUpConverter(double amin, double amid, double amax, double fmin, double /*fmid*/, double fmax) : - fA2F(amin,amid,amax,fmax,fmin,fmax), - fF2A(fmin,fmax,amin,amax) // Special, pseudo inverse of a non monotonic function - {} - - virtual double ui2faust(double x) { return fA2F(x); } - virtual double faust2ui(double x) { return fF2A(x); } - - virtual void setMappingValues(double amin, double amid, double amax, double fmin, double /*fmid*/, double fmax) - { - //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccDownUpConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax); - fA2F = Interpolator3pt(amin, amid, amax, fmax, fmin, fmax); - fF2A = Interpolator(fmin, fmax, amin, amax); - } - - virtual void getMappingValues(double& amin, double& amid, double& amax) - { - fA2F.getMappingValues(amin, amid, amax); - } +class FAUST_API AccDownUpConverter : public UpdatableValueConverter +{ + private: + Interpolator3pt fA2F; + Interpolator fF2A; + + public: + AccDownUpConverter(double amin, double amid, double amax, double fmin, + double /*fmid*/, double fmax) + : fA2F(amin, amid, amax, fmax, fmin, fmax) + , fF2A(fmin, fmax, amin, + amax) // Special, pseudo inverse of a non monotonic function + { + } + + virtual double ui2faust(double x) { return fA2F(x); } + virtual double faust2ui(double x) { return fF2A(x); } + + virtual void setMappingValues(double amin, double amid, double amax, double fmin, + double /*fmid*/, double fmax) + { + //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccDownUpConverter update %f %f + //%f %f %f %f", amin,amid,amax,fmin,fmid,fmax); + fA2F = Interpolator3pt(amin, amid, amax, fmax, fmin, fmax); + fF2A = Interpolator(fmin, fmax, amin, amax); + } + + virtual void getMappingValues(double& amin, double& amid, double& amax) + { + fA2F.getMappingValues(amin, amid, amax); + } }; //-------------------------------------------------------------------------------------- // Base class for ZoneControl //-------------------------------------------------------------------------------------- -class FAUST_API ZoneControl { - - protected: - - FAUSTFLOAT* fZone; - - public: - - ZoneControl(FAUSTFLOAT* zone) : fZone(zone) {} - virtual ~ZoneControl() {} +class FAUST_API ZoneControl +{ + protected: + FAUSTFLOAT* fZone; - virtual void update(double /*v*/) const {} + public: + ZoneControl(FAUSTFLOAT* zone) : fZone(zone) {} + virtual ~ZoneControl() {} - virtual void setMappingValues(int /*curve*/, double /*amin*/, double /*amid*/, double /*amax*/, double /*min*/, double /*init*/, double /*max*/) {} - virtual void getMappingValues(double& /*amin*/, double& /*amid*/, double& /*amax*/) {} + virtual void update(double /*v*/) const {} - FAUSTFLOAT* getZone() { return fZone; } + virtual void setMappingValues(int /*curve*/, double /*amin*/, double /*amid*/, + double /*amax*/, double /*min*/, double /*init*/, + double /*max*/) + { + } + virtual void getMappingValues(double& /*amin*/, double& /*amid*/, double& /*amax*/) {} - virtual void setActive(bool /*on_off*/) {} - virtual bool getActive() { return false; } + FAUSTFLOAT* getZone() { return fZone; } - virtual int getCurve() { return -1; } + virtual void setActive(bool /*on_off*/) {} + virtual bool getActive() { return false; } + virtual int getCurve() { return -1; } }; //-------------------------------------------------------------------------------------- // Useful to implement accelerometers metadata as a list of ZoneControl for each axes //-------------------------------------------------------------------------------------- -class FAUST_API ConverterZoneControl : public ZoneControl { - - protected: - - ValueConverter* fValueConverter; - - public: - - ConverterZoneControl(FAUSTFLOAT* zone, ValueConverter* converter) : ZoneControl(zone), fValueConverter(converter) {} - virtual ~ConverterZoneControl() { delete fValueConverter; } // Assuming fValueConverter is not kept elsewhere... - - virtual void update(double v) const { *fZone = FAUSTFLOAT(fValueConverter->ui2faust(v)); } - - ValueConverter* getConverter() { return fValueConverter; } - +class FAUST_API ConverterZoneControl : public ZoneControl +{ + protected: + ValueConverter* fValueConverter; + + public: + ConverterZoneControl(FAUSTFLOAT* zone, ValueConverter* converter) + : ZoneControl(zone), fValueConverter(converter) + { + } + virtual ~ConverterZoneControl() + { + delete fValueConverter; + } // Assuming fValueConverter is not kept elsewhere... + + virtual void update(double v) const + { + *fZone = FAUSTFLOAT(fValueConverter->ui2faust(v)); + } + + ValueConverter* getConverter() { return fValueConverter; } }; //-------------------------------------------------------------------------------------- // Association of a zone and a four value converter, each one for each possible curve. // Useful to implement accelerometers metadata as a list of ZoneControl for each axes //-------------------------------------------------------------------------------------- -class FAUST_API CurveZoneControl : public ZoneControl { - - private: - - std::vector fValueConverters; - int fCurve; - - public: - - CurveZoneControl(FAUSTFLOAT* zone, int curve, double amin, double amid, double amax, double min, double init, double max) : ZoneControl(zone), fCurve(0) - { - assert(curve >= 0 && curve <= 3); - fValueConverters.push_back(new AccUpConverter(amin, amid, amax, min, init, max)); - fValueConverters.push_back(new AccDownConverter(amin, amid, amax, min, init, max)); - fValueConverters.push_back(new AccUpDownConverter(amin, amid, amax, min, init, max)); - fValueConverters.push_back(new AccDownUpConverter(amin, amid, amax, min, init, max)); - fCurve = curve; - } - virtual ~CurveZoneControl() - { - for (const auto& it : fValueConverters) { delete it; } - } - void update(double v) const { if (fValueConverters[fCurve]->getActive()) *fZone = FAUSTFLOAT(fValueConverters[fCurve]->ui2faust(v)); } - - void setMappingValues(int curve, double amin, double amid, double amax, double min, double init, double max) - { - fValueConverters[curve]->setMappingValues(amin, amid, amax, min, init, max); - fCurve = curve; - } - - void getMappingValues(double& amin, double& amid, double& amax) - { - fValueConverters[fCurve]->getMappingValues(amin, amid, amax); +class FAUST_API CurveZoneControl : public ZoneControl +{ + private: + std::vector fValueConverters; + int fCurve; + + public: + CurveZoneControl(FAUSTFLOAT* zone, int curve, double amin, double amid, double amax, + double min, double init, double max) + : ZoneControl(zone), fCurve(0) + { + assert(curve >= 0 && curve <= 3); + fValueConverters.push_back(new AccUpConverter(amin, amid, amax, min, init, max)); + fValueConverters.push_back( + new AccDownConverter(amin, amid, amax, min, init, max)); + fValueConverters.push_back( + new AccUpDownConverter(amin, amid, amax, min, init, max)); + fValueConverters.push_back( + new AccDownUpConverter(amin, amid, amax, min, init, max)); + fCurve = curve; + } + virtual ~CurveZoneControl() + { + for (const auto& it : fValueConverters) { + delete it; } - - void setActive(bool on_off) - { - for (const auto& it : fValueConverters) { it->setActive(on_off); } + } + void update(double v) const + { + if (fValueConverters[fCurve]->getActive()) + *fZone = FAUSTFLOAT(fValueConverters[fCurve]->ui2faust(v)); + } + + void setMappingValues(int curve, double amin, double amid, double amax, double min, + double init, double max) + { + fValueConverters[curve]->setMappingValues(amin, amid, amax, min, init, max); + fCurve = curve; + } + + void getMappingValues(double& amin, double& amid, double& amax) + { + fValueConverters[fCurve]->getMappingValues(amin, amid, amax); + } + + void setActive(bool on_off) + { + for (const auto& it : fValueConverters) { + it->setActive(on_off); } + } - int getCurve() { return fCurve; } + int getCurve() { return fCurve; } }; -class FAUST_API ZoneReader { - - private: - - FAUSTFLOAT* fZone; - Interpolator fInterpolator; - - public: +class FAUST_API ZoneReader +{ + private: + FAUSTFLOAT* fZone; + Interpolator fInterpolator; - ZoneReader(FAUSTFLOAT* zone, double lo, double hi) : fZone(zone), fInterpolator(lo, hi, 0, 255) {} + public: + ZoneReader(FAUSTFLOAT* zone, double lo, double hi) + : fZone(zone), fInterpolator(lo, hi, 0, 255) + { + } - virtual ~ZoneReader() {} - - int getValue() - { - return (fZone != nullptr) ? int(fInterpolator(*fZone)) : 127; - } + virtual ~ZoneReader() {} + int getValue() { return (fZone != nullptr) ? int(fInterpolator(*fZone)) : 127; } }; #endif @@ -1278,688 +1330,742 @@ class FAUST_API ZoneReader { typedef unsigned int uint; -class APIUI : public PathBuilder, public Meta, public UI +class APIUI + : public PathBuilder + , public Meta + , public UI { - public: - enum ItemType { kButton = 0, kCheckButton, kVSlider, kHSlider, kNumEntry, kHBargraph, kVBargraph }; - enum Type { kAcc = 0, kGyr = 1, kNoType }; - - protected: - - enum Mapping { kLin = 0, kLog = 1, kExp = 2 }; - - struct Item { - std::string fLabel; - std::string fShortname; - std::string fPath; - ValueConverter* fConversion; - FAUSTFLOAT* fZone; - FAUSTFLOAT fInit; - FAUSTFLOAT fMin; - FAUSTFLOAT fMax; - FAUSTFLOAT fStep; - ItemType fItemType; - - Item(const std::string& label, - const std::string& short_name, - const std::string& path, - ValueConverter* conversion, - FAUSTFLOAT* zone, - FAUSTFLOAT init, - FAUSTFLOAT min, - FAUSTFLOAT max, - FAUSTFLOAT step, - ItemType item_type) - :fLabel(label), fShortname(short_name), fPath(path), fConversion(conversion), - fZone(zone), fInit(init), fMin(min), fMax(max), fStep(step), fItemType(item_type) - {} - }; - std::vector fItems; - - std::vector > fMetaData; - std::vector fAcc[3]; - std::vector fGyr[3]; - - // Screen color control - // "...[screencolor:red]..." etc. - bool fHasScreenControl; // true if control screen color metadata - ZoneReader* fRedReader; - ZoneReader* fGreenReader; - ZoneReader* fBlueReader; - - // Current values controlled by metadata - std::string fCurrentUnit; - int fCurrentScale; - std::string fCurrentAcc; - std::string fCurrentGyr; - std::string fCurrentColor; - std::string fCurrentTooltip; - std::map fCurrentMetadata; - - // Add a generic parameter - virtual void addParameter(const char* label, - FAUSTFLOAT* zone, - FAUSTFLOAT init, - FAUSTFLOAT min, - FAUSTFLOAT max, - FAUSTFLOAT step, - ItemType type) + public: + enum ItemType { + kButton = 0, + kCheckButton, + kVSlider, + kHSlider, + kNumEntry, + kHBargraph, + kVBargraph + }; + enum Type { kAcc = 0, kGyr = 1, kNoType }; + + protected: + enum Mapping { kLin = 0, kLog = 1, kExp = 2 }; + + struct Item { + std::string fLabel; + std::string fShortname; + std::string fPath; + ValueConverter* fConversion; + FAUSTFLOAT* fZone; + FAUSTFLOAT fInit; + FAUSTFLOAT fMin; + FAUSTFLOAT fMax; + FAUSTFLOAT fStep; + ItemType fItemType; + + Item(const std::string& label, const std::string& short_name, + const std::string& path, ValueConverter* conversion, FAUSTFLOAT* zone, + FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step, + ItemType item_type) + : fLabel(label) + , fShortname(short_name) + , fPath(path) + , fConversion(conversion) + , fZone(zone) + , fInit(init) + , fMin(min) + , fMax(max) + , fStep(step) + , fItemType(item_type) { - std::string path = buildPath(label); - fFullPaths.push_back(path); - - // handle scale metadata - ValueConverter* converter = nullptr; - switch (fCurrentScale) { - case kLin: - converter = new LinearValueConverter(0, 1, min, max); - break; - case kLog: - converter = new LogValueConverter(0, 1, min, max); - break; - case kExp: - converter = new ExpValueConverter(0, 1, min, max); - break; - } - fCurrentScale = kLin; - - fItems.push_back(Item(label, "", path, converter, zone, init, min, max, step, type)); - - if (fCurrentAcc.size() > 0 && fCurrentGyr.size() > 0) { - fprintf(stderr, "warning : 'acc' and 'gyr' metadata used for the same %s parameter !!\n", label); - } + } + }; + std::vector fItems; + + std::vector > fMetaData; + std::vector fAcc[3]; + std::vector fGyr[3]; + + // Screen color control + // "...[screencolor:red]..." etc. + bool fHasScreenControl; // true if control screen color metadata + ZoneReader* fRedReader; + ZoneReader* fGreenReader; + ZoneReader* fBlueReader; + + // Current values controlled by metadata + std::string fCurrentUnit; + int fCurrentScale; + std::string fCurrentAcc; + std::string fCurrentGyr; + std::string fCurrentColor; + std::string fCurrentTooltip; + std::map fCurrentMetadata; + + // Add a generic parameter + virtual void addParameter(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, + FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step, + ItemType type) + { + std::string path = buildPath(label); + fFullPaths.push_back(path); + + // handle scale metadata + ValueConverter* converter = nullptr; + switch (fCurrentScale) { + case kLin: + converter = new LinearValueConverter(0, 1, min, max); + break; + case kLog: + converter = new LogValueConverter(0, 1, min, max); + break; + case kExp: + converter = new ExpValueConverter(0, 1, min, max); + break; + } + fCurrentScale = kLin; - // handle acc metadata "...[acc : ]..." - if (fCurrentAcc.size() > 0) { - std::istringstream iss(fCurrentAcc); - int axe, curve; - double amin, amid, amax; - iss >> axe >> curve >> amin >> amid >> amax; - - if ((0 <= axe) && (axe < 3) && - (0 <= curve) && (curve < 4) && - (amin < amax) && (amin <= amid) && (amid <= amax)) - { - fAcc[axe].push_back(new CurveZoneControl(zone, curve, amin, amid, amax, min, init, max)); - } else { - fprintf(stderr, "incorrect acc metadata : %s \n", fCurrentAcc.c_str()); - } - fCurrentAcc = ""; - } + fItems.push_back( + Item(label, "", path, converter, zone, init, min, max, step, type)); - // handle gyr metadata "...[gyr : ]..." - if (fCurrentGyr.size() > 0) { - std::istringstream iss(fCurrentGyr); - int axe, curve; - double amin, amid, amax; - iss >> axe >> curve >> amin >> amid >> amax; - - if ((0 <= axe) && (axe < 3) && - (0 <= curve) && (curve < 4) && - (amin < amax) && (amin <= amid) && (amid <= amax)) - { - fGyr[axe].push_back(new CurveZoneControl(zone, curve, amin, amid, amax, min, init, max)); - } else { - fprintf(stderr, "incorrect gyr metadata : %s \n", fCurrentGyr.c_str()); - } - fCurrentGyr = ""; - } + if (fCurrentAcc.size() > 0 && fCurrentGyr.size() > 0) { + fprintf( + stderr, + "warning : 'acc' and 'gyr' metadata used for the same %s parameter !!\n", + label); + } - // handle screencolor metadata "...[screencolor:red|green|blue|white]..." - if (fCurrentColor.size() > 0) { - if ((fCurrentColor == "red") && (fRedReader == nullptr)) { - fRedReader = new ZoneReader(zone, min, max); - fHasScreenControl = true; - } else if ((fCurrentColor == "green") && (fGreenReader == nullptr)) { - fGreenReader = new ZoneReader(zone, min, max); - fHasScreenControl = true; - } else if ((fCurrentColor == "blue") && (fBlueReader == nullptr)) { - fBlueReader = new ZoneReader(zone, min, max); - fHasScreenControl = true; - } else if ((fCurrentColor == "white") && (fRedReader == nullptr) && (fGreenReader == nullptr) && (fBlueReader == nullptr)) { - fRedReader = new ZoneReader(zone, min, max); - fGreenReader = new ZoneReader(zone, min, max); - fBlueReader = new ZoneReader(zone, min, max); - fHasScreenControl = true; - } else { - fprintf(stderr, "incorrect screencolor metadata : %s \n", fCurrentColor.c_str()); - } + // handle acc metadata "...[acc : ]..." + if (fCurrentAcc.size() > 0) { + std::istringstream iss(fCurrentAcc); + int axe, curve; + double amin, amid, amax; + iss >> axe >> curve >> amin >> amid >> amax; + + if ((0 <= axe) && (axe < 3) && (0 <= curve) && (curve < 4) && (amin < amax) + && (amin <= amid) && (amid <= amax)) { + fAcc[axe].push_back( + new CurveZoneControl(zone, curve, amin, amid, amax, min, init, max)); + } else { + fprintf(stderr, "incorrect acc metadata : %s \n", fCurrentAcc.c_str()); } - fCurrentColor = ""; - - fMetaData.push_back(fCurrentMetadata); - fCurrentMetadata.clear(); + fCurrentAcc = ""; } - int getZoneIndex(std::vector* table, int p, int val) - { - FAUSTFLOAT* zone = fItems[uint(p)].fZone; - for (size_t i = 0; i < table[val].size(); i++) { - if (zone == table[val][i]->getZone()) return int(i); + // handle gyr metadata "...[gyr : ]..." + if (fCurrentGyr.size() > 0) { + std::istringstream iss(fCurrentGyr); + int axe, curve; + double amin, amid, amax; + iss >> axe >> curve >> amin >> amid >> amax; + + if ((0 <= axe) && (axe < 3) && (0 <= curve) && (curve < 4) && (amin < amax) + && (amin <= amid) && (amid <= amax)) { + fGyr[axe].push_back( + new CurveZoneControl(zone, curve, amin, amid, amax, min, init, max)); + } else { + fprintf(stderr, "incorrect gyr metadata : %s \n", fCurrentGyr.c_str()); } - return -1; + fCurrentGyr = ""; } - void setConverter(std::vector* table, int p, int val, int curve, double amin, double amid, double amax) - { - int id1 = getZoneIndex(table, p, 0); - int id2 = getZoneIndex(table, p, 1); - int id3 = getZoneIndex(table, p, 2); - - // Deactivates everywhere.. - if (id1 != -1) table[0][uint(id1)]->setActive(false); - if (id2 != -1) table[1][uint(id2)]->setActive(false); - if (id3 != -1) table[2][uint(id3)]->setActive(false); - - if (val == -1) { // Means: no more mapping... - // So stay all deactivated... + // handle screencolor metadata "...[screencolor:red|green|blue|white]..." + if (fCurrentColor.size() > 0) { + if ((fCurrentColor == "red") && (fRedReader == nullptr)) { + fRedReader = new ZoneReader(zone, min, max); + fHasScreenControl = true; + } else if ((fCurrentColor == "green") && (fGreenReader == nullptr)) { + fGreenReader = new ZoneReader(zone, min, max); + fHasScreenControl = true; + } else if ((fCurrentColor == "blue") && (fBlueReader == nullptr)) { + fBlueReader = new ZoneReader(zone, min, max); + fHasScreenControl = true; + } else if ((fCurrentColor == "white") && (fRedReader == nullptr) + && (fGreenReader == nullptr) && (fBlueReader == nullptr)) { + fRedReader = new ZoneReader(zone, min, max); + fGreenReader = new ZoneReader(zone, min, max); + fBlueReader = new ZoneReader(zone, min, max); + fHasScreenControl = true; } else { - int id4 = getZoneIndex(table, p, val); - if (id4 != -1) { - // Reactivate the one we edit... - table[val][uint(id4)]->setMappingValues(curve, amin, amid, amax, fItems[uint(p)].fMin, fItems[uint(p)].fInit, fItems[uint(p)].fMax); - table[val][uint(id4)]->setActive(true); - } else { - // Allocate a new CurveZoneControl which is 'active' by default - FAUSTFLOAT* zone = fItems[uint(p)].fZone; - table[val].push_back(new CurveZoneControl(zone, curve, amin, amid, amax, fItems[uint(p)].fMin, fItems[uint(p)].fInit, fItems[uint(p)].fMax)); - } + fprintf(stderr, "incorrect screencolor metadata : %s \n", + fCurrentColor.c_str()); } } - - void getConverter(std::vector* table, int p, int& val, int& curve, double& amin, double& amid, double& amax) - { - int id1 = getZoneIndex(table, p, 0); - int id2 = getZoneIndex(table, p, 1); - int id3 = getZoneIndex(table, p, 2); - - if (id1 != -1) { - val = 0; - curve = table[val][uint(id1)]->getCurve(); - table[val][uint(id1)]->getMappingValues(amin, amid, amax); - } else if (id2 != -1) { - val = 1; - curve = table[val][uint(id2)]->getCurve(); - table[val][uint(id2)]->getMappingValues(amin, amid, amax); - } else if (id3 != -1) { - val = 2; - curve = table[val][uint(id3)]->getCurve(); - table[val][uint(id3)]->getMappingValues(amin, amid, amax); + fCurrentColor = ""; + + fMetaData.push_back(fCurrentMetadata); + fCurrentMetadata.clear(); + } + + int getZoneIndex(std::vector* table, int p, int val) + { + FAUSTFLOAT* zone = fItems[uint(p)].fZone; + for (size_t i = 0; i < table[val].size(); i++) { + if (zone == table[val][i]->getZone()) + return int(i); + } + return -1; + } + + void setConverter(std::vector* table, int p, int val, int curve, + double amin, double amid, double amax) + { + int id1 = getZoneIndex(table, p, 0); + int id2 = getZoneIndex(table, p, 1); + int id3 = getZoneIndex(table, p, 2); + + // Deactivates everywhere.. + if (id1 != -1) + table[0][uint(id1)]->setActive(false); + if (id2 != -1) + table[1][uint(id2)]->setActive(false); + if (id3 != -1) + table[2][uint(id3)]->setActive(false); + + if (val == -1) { // Means: no more mapping... + // So stay all deactivated... + } else { + int id4 = getZoneIndex(table, p, val); + if (id4 != -1) { + // Reactivate the one we edit... + table[val][uint(id4)]->setMappingValues( + curve, amin, amid, amax, fItems[uint(p)].fMin, fItems[uint(p)].fInit, + fItems[uint(p)].fMax); + table[val][uint(id4)]->setActive(true); } else { - val = -1; // No mapping - curve = 0; - amin = -100.; - amid = 0.; - amax = 100.; + // Allocate a new CurveZoneControl which is 'active' by default + FAUSTFLOAT* zone = fItems[uint(p)].fZone; + table[val].push_back(new CurveZoneControl( + zone, curve, amin, amid, amax, fItems[uint(p)].fMin, + fItems[uint(p)].fInit, fItems[uint(p)].fMax)); } } + } + + void getConverter(std::vector* table, int p, int& val, int& curve, + double& amin, double& amid, double& amax) + { + int id1 = getZoneIndex(table, p, 0); + int id2 = getZoneIndex(table, p, 1); + int id3 = getZoneIndex(table, p, 2); + + if (id1 != -1) { + val = 0; + curve = table[val][uint(id1)]->getCurve(); + table[val][uint(id1)]->getMappingValues(amin, amid, amax); + } else if (id2 != -1) { + val = 1; + curve = table[val][uint(id2)]->getCurve(); + table[val][uint(id2)]->getMappingValues(amin, amid, amax); + } else if (id3 != -1) { + val = 2; + curve = table[val][uint(id3)]->getCurve(); + table[val][uint(id3)]->getMappingValues(amin, amid, amax); + } else { + val = -1; // No mapping + curve = 0; + amin = -100.; + amid = 0.; + amax = 100.; + } + } + + public: + APIUI() + : fHasScreenControl(false) + , fRedReader(nullptr) + , fGreenReader(nullptr) + , fBlueReader(nullptr) + , fCurrentScale(kLin) + { + } + + virtual ~APIUI() + { + for (const auto& it : fItems) + delete it.fConversion; + for (int i = 0; i < 3; i++) { + for (const auto& it : fAcc[i]) + delete it; + for (const auto& it : fGyr[i]) + delete it; + } + delete fRedReader; + delete fGreenReader; + delete fBlueReader; + } - public: - - APIUI() : fHasScreenControl(false), fRedReader(nullptr), fGreenReader(nullptr), fBlueReader(nullptr), fCurrentScale(kLin) - {} + // -- widget's layouts - virtual ~APIUI() - { - for (const auto& it : fItems) delete it.fConversion; - for (int i = 0; i < 3; i++) { - for (const auto& it : fAcc[i]) delete it; - for (const auto& it : fGyr[i]) delete it; + virtual void openTabBox(const char* label) { pushLabel(label); } + virtual void openHorizontalBox(const char* label) { pushLabel(label); } + virtual void openVerticalBox(const char* label) { pushLabel(label); } + virtual void closeBox() + { + if (popLabel()) { + // Shortnames can be computed when all fullnames are known + computeShortNames(); + // Fill 'shortname' field for each item + for (const auto& it : fFull2Short) { + int index = getParamIndex(it.first.c_str()); + fItems[index].fShortname = it.second; } - delete fRedReader; - delete fGreenReader; - delete fBlueReader; } + } - // -- widget's layouts + // -- active widgets - virtual void openTabBox(const char* label) { pushLabel(label); } - virtual void openHorizontalBox(const char* label) { pushLabel(label); } - virtual void openVerticalBox(const char* label) { pushLabel(label); } - virtual void closeBox() - { - if (popLabel()) { - // Shortnames can be computed when all fullnames are known - computeShortNames(); - // Fill 'shortname' field for each item - for (const auto& it : fFull2Short) { - int index = getParamIndex(it.first.c_str()); - fItems[index].fShortname = it.second; - } - } - } + virtual void addButton(const char* label, FAUSTFLOAT* zone) + { + addParameter(label, zone, 0, 0, 1, 1, kButton); + } + + virtual void addCheckButton(const char* label, FAUSTFLOAT* zone) + { + addParameter(label, zone, 0, 0, 1, 1, kCheckButton); + } + + virtual void addVerticalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, + FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) + { + addParameter(label, zone, init, min, max, step, kVSlider); + } + + virtual void addHorizontalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, + FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) + { + addParameter(label, zone, init, min, max, step, kHSlider); + } + + virtual void addNumEntry(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, + FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) + { + addParameter(label, zone, init, min, max, step, kNumEntry); + } - // -- active widgets + // -- passive widgets - virtual void addButton(const char* label, FAUSTFLOAT* zone) - { - addParameter(label, zone, 0, 0, 1, 1, kButton); - } + virtual void addHorizontalBargraph(const char* label, FAUSTFLOAT* zone, + FAUSTFLOAT min, FAUSTFLOAT max) + { + addParameter(label, zone, min, min, max, (max - min) / 1000.0f, kHBargraph); + } - virtual void addCheckButton(const char* label, FAUSTFLOAT* zone) - { - addParameter(label, zone, 0, 0, 1, 1, kCheckButton); - } + virtual void addVerticalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT min, + FAUSTFLOAT max) + { + addParameter(label, zone, min, min, max, (max - min) / 1000.0f, kVBargraph); + } - virtual void addVerticalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) - { - addParameter(label, zone, init, min, max, step, kVSlider); - } + // -- soundfiles - virtual void addHorizontalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) - { - addParameter(label, zone, init, min, max, step, kHSlider); - } + virtual void addSoundfile(const char* /*label*/, const char* /*filename*/, + Soundfile** /*sf_zone*/) + { + } - virtual void addNumEntry(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) - { - addParameter(label, zone, init, min, max, step, kNumEntry); - } + // -- metadata declarations - // -- passive widgets + virtual void declare(FAUSTFLOAT* /*zone*/, const char* key, const char* val) + { + // Keep metadata + fCurrentMetadata[key] = val; - virtual void addHorizontalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT min, FAUSTFLOAT max) - { - addParameter(label, zone, min, min, max, (max-min)/1000.0f, kHBargraph); + if (strcmp(key, "scale") == 0) { + if (strcmp(val, "log") == 0) { + fCurrentScale = kLog; + } else if (strcmp(val, "exp") == 0) { + fCurrentScale = kExp; + } else { + fCurrentScale = kLin; + } + } else if (strcmp(key, "unit") == 0) { + fCurrentUnit = val; + } else if (strcmp(key, "acc") == 0) { + fCurrentAcc = val; + } else if (strcmp(key, "gyr") == 0) { + fCurrentGyr = val; + } else if (strcmp(key, "screencolor") == 0) { + fCurrentColor = val; // val = "red", "green", "blue" or "white" + } else if (strcmp(key, "tooltip") == 0) { + fCurrentTooltip = val; } + } - virtual void addVerticalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT min, FAUSTFLOAT max) - { - addParameter(label, zone, min, min, max, (max-min)/1000.0f, kVBargraph); - } + virtual void declare(const char* /*key*/, const char* /*val*/) {} - // -- soundfiles + //------------------------------------------------------------------------------- + // Simple API part + //------------------------------------------------------------------------------- - virtual void addSoundfile(const char* /*label*/, const char* /*filename*/, Soundfile** /*sf_zone*/) {} + /** + * Return the number of parameters in the UI. + * + * @return the number of parameters + */ + int getParamsCount() { return int(fItems.size()); } - // -- metadata declarations + /** + * Return the param index. + * + * @param str - the UI parameter label/shortname/path + * + * @return the param index + */ + int getParamIndex(const char* str) + { + std::string path = std::string(str); + auto it = find_if(fItems.begin(), fItems.end(), [=](const Item& it) { + return (it.fLabel == path) || (it.fShortname == path) || (it.fPath == path); + }); + return (it != fItems.end()) ? int(it - fItems.begin()) : -1; + } - virtual void declare(FAUSTFLOAT* /*zone*/, const char* key, const char* val) - { - // Keep metadata - fCurrentMetadata[key] = val; - - if (strcmp(key, "scale") == 0) { - if (strcmp(val, "log") == 0) { - fCurrentScale = kLog; - } else if (strcmp(val, "exp") == 0) { - fCurrentScale = kExp; - } else { - fCurrentScale = kLin; - } - } else if (strcmp(key, "unit") == 0) { - fCurrentUnit = val; - } else if (strcmp(key, "acc") == 0) { - fCurrentAcc = val; - } else if (strcmp(key, "gyr") == 0) { - fCurrentGyr = val; - } else if (strcmp(key, "screencolor") == 0) { - fCurrentColor = val; // val = "red", "green", "blue" or "white" - } else if (strcmp(key, "tooltip") == 0) { - fCurrentTooltip = val; - } - } + /** + * Return the param label. + * + * @param p - the UI parameter index + * + * @return the param label + */ + const char* getParamLabel(int p) { return fItems[uint(p)].fLabel.c_str(); } - virtual void declare(const char* /*key*/, const char* /*val*/) - {} - - //------------------------------------------------------------------------------- - // Simple API part - //------------------------------------------------------------------------------- - - /** - * Return the number of parameters in the UI. - * - * @return the number of parameters - */ - int getParamsCount() { return int(fItems.size()); } - - /** - * Return the param index. - * - * @param str - the UI parameter label/shortname/path - * - * @return the param index - */ - int getParamIndex(const char* str) - { - std::string path = std::string(str); - auto it = find_if(fItems.begin(), fItems.end(), - [=](const Item& it) { return (it.fLabel == path) || (it.fShortname == path) || (it.fPath == path); }); - return (it != fItems.end()) ? int(it - fItems.begin()) : -1; - } - - /** - * Return the param label. - * - * @param p - the UI parameter index - * - * @return the param label - */ - const char* getParamLabel(int p) { return fItems[uint(p)].fLabel.c_str(); } - - /** - * Return the param shortname. - * - * @param p - the UI parameter index - * - * @return the param shortname - */ - const char* getParamShortname(int p) { return fItems[uint(p)].fShortname.c_str(); } - - /** - * Return the param path. - * - * @param p - the UI parameter index - * - * @return the param path - */ - const char* getParamAddress(int p) { return fItems[uint(p)].fPath.c_str(); } - - /** - * Return the param metadata. - * - * @param p - the UI parameter index - * - * @return the param metadata as a map - */ - std::map getMetadata(int p) - { - std::map res; - std::map metadata = fMetaData[uint(p)]; - for (const auto& it : metadata) { - res[it.first.c_str()] = it.second.c_str(); - } - return res; - } + /** + * Return the param shortname. + * + * @param p - the UI parameter index + * + * @return the param shortname + */ + const char* getParamShortname(int p) { return fItems[uint(p)].fShortname.c_str(); } - /** - * Return the param metadata value. - * - * @param p - the UI parameter index - * @param key - the UI parameter index - * - * @return the param metadata value associate to the key - */ - const char* getMetadata(int p, const char* key) - { - return (fMetaData[uint(p)].find(key) != fMetaData[uint(p)].end()) ? fMetaData[uint(p)][key].c_str() : ""; - } - - /** - * Return the param minimum value. - * - * @param p - the UI parameter index - * - * @return the param minimum value - */ - FAUSTFLOAT getParamMin(int p) { return fItems[uint(p)].fMin; } - - /** - * Return the param maximum value. - * - * @param p - the UI parameter index - * - * @return the param maximum value - */ - FAUSTFLOAT getParamMax(int p) { return fItems[uint(p)].fMax; } - - /** - * Return the param step value. - * - * @param p - the UI parameter index - * - * @return the param step value - */ - FAUSTFLOAT getParamStep(int p) { return fItems[uint(p)].fStep; } - - /** - * Return the param init value. - * - * @param p - the UI parameter index - * - * @return the param init value - */ - FAUSTFLOAT getParamInit(int p) { return fItems[uint(p)].fInit; } - - /** - * Return the param memory zone. - * - * @param p - the UI parameter index - * - * @return the param memory zone. - */ - FAUSTFLOAT* getParamZone(int p) { return fItems[uint(p)].fZone; } - - /** - * Return the param value. - * - * @param p - the UI parameter index - * - * @return the param value. - */ - FAUSTFLOAT getParamValue(int p) { return *fItems[uint(p)].fZone; } - - /** - * Return the param value. - * - * @param str - the UI parameter label/shortname/path - * - * @return the param value. - */ - FAUSTFLOAT getParamValue(const char* str) - { - int index = getParamIndex(str); - if (index >= 0) { - return getParamValue(index); - } else { - fprintf(stderr, "getParamValue : '%s' not found\n", (str == nullptr ? "NULL" : str)); - return FAUSTFLOAT(0); - } - } + /** + * Return the param path. + * + * @param p - the UI parameter index + * + * @return the param path + */ + const char* getParamAddress(int p) { return fItems[uint(p)].fPath.c_str(); } - /** - * Set the param value. - * - * @param p - the UI parameter index - * @param v - the UI parameter value - * - */ - void setParamValue(int p, FAUSTFLOAT v) { *fItems[uint(p)].fZone = v; } - - /** - * Set the param value. - * - * @param p - the UI parameter label/shortname/path - * @param v - the UI parameter value - * - */ - void setParamValue(const char* path, FAUSTFLOAT v) - { - int index = getParamIndex(path); - if (index >= 0) { - setParamValue(index, v); - } else { - fprintf(stderr, "setParamValue : '%s' not found\n", (path == nullptr ? "NULL" : path)); - } + /** + * Return the param metadata. + * + * @param p - the UI parameter index + * + * @return the param metadata as a map + */ + std::map getMetadata(int p) + { + std::map res; + std::map metadata = fMetaData[uint(p)]; + for (const auto& it : metadata) { + res[it.first.c_str()] = it.second.c_str(); } + return res; + } - double getParamRatio(int p) { return fItems[uint(p)].fConversion->faust2ui(*fItems[uint(p)].fZone); } - void setParamRatio(int p, double r) { *fItems[uint(p)].fZone = FAUSTFLOAT(fItems[uint(p)].fConversion->ui2faust(r)); } + /** + * Return the param metadata value. + * + * @param p - the UI parameter index + * @param key - the UI parameter index + * + * @return the param metadata value associate to the key + */ + const char* getMetadata(int p, const char* key) + { + return (fMetaData[uint(p)].find(key) != fMetaData[uint(p)].end()) + ? fMetaData[uint(p)][key].c_str() + : ""; + } - double value2ratio(int p, double r) { return fItems[uint(p)].fConversion->faust2ui(r); } - double ratio2value(int p, double r) { return fItems[uint(p)].fConversion->ui2faust(r); } + /** + * Return the param minimum value. + * + * @param p - the UI parameter index + * + * @return the param minimum value + */ + FAUSTFLOAT getParamMin(int p) { return fItems[uint(p)].fMin; } - /** - * Return the control type (kAcc, kGyr, or -1) for a given parameter. - * - * @param p - the UI parameter index - * - * @return the type - */ - Type getParamType(int p) - { - if (p >= 0) { - if (getZoneIndex(fAcc, p, 0) != -1 - || getZoneIndex(fAcc, p, 1) != -1 - || getZoneIndex(fAcc, p, 2) != -1) { - return kAcc; - } else if (getZoneIndex(fGyr, p, 0) != -1 - || getZoneIndex(fGyr, p, 1) != -1 - || getZoneIndex(fGyr, p, 2) != -1) { - return kGyr; - } - } - return kNoType; - } + /** + * Return the param maximum value. + * + * @param p - the UI parameter index + * + * @return the param maximum value + */ + FAUSTFLOAT getParamMax(int p) { return fItems[uint(p)].fMax; } - /** - * Return the Item type (kButton = 0, kCheckButton, kVSlider, kHSlider, kNumEntry, kHBargraph, kVBargraph) for a given parameter. - * - * @param p - the UI parameter index - * - * @return the Item type - */ - ItemType getParamItemType(int p) - { - return fItems[uint(p)].fItemType; - } + /** + * Return the param step value. + * + * @param p - the UI parameter index + * + * @return the param step value + */ + FAUSTFLOAT getParamStep(int p) { return fItems[uint(p)].fStep; } - /** - * Set a new value coming from an accelerometer, propagate it to all relevant FAUSTFLOAT* zones. - * - * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer - * @param value - the new value - * - */ - void propagateAcc(int acc, double value) - { - for (size_t i = 0; i < fAcc[acc].size(); i++) { - fAcc[acc][i]->update(value); - } - } + /** + * Return the param init value. + * + * @param p - the UI parameter index + * + * @return the param init value + */ + FAUSTFLOAT getParamInit(int p) { return fItems[uint(p)].fInit; } - /** - * Used to edit accelerometer curves and mapping. Set curve and related mapping for a given UI parameter. - * - * @param p - the UI parameter index - * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer (-1 means "no mapping") - * @param curve - between 0 and 3 (0: up, 1: down, 2: up and down, 2: down and up) - * @param amin - mapping 'min' point - * @param amid - mapping 'middle' point - * @param amax - mapping 'max' point - * - */ - void setAccConverter(int p, int acc, int curve, double amin, double amid, double amax) - { - setConverter(fAcc, p, acc, curve, amin, amid, amax); - } + /** + * Return the param memory zone. + * + * @param p - the UI parameter index + * + * @return the param memory zone. + */ + FAUSTFLOAT* getParamZone(int p) { return fItems[uint(p)].fZone; } - /** - * Used to edit gyroscope curves and mapping. Set curve and related mapping for a given UI parameter. - * - * @param p - the UI parameter index - * @param gyr - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope (-1 means "no mapping") - * @param curve - between 0 and 3 (0: up, 1: down, 2: up and down, 2: down and up) - * @param amin - mapping 'min' point - * @param amid - mapping 'middle' point - * @param amax - mapping 'max' point - * - */ - void setGyrConverter(int p, int gyr, int curve, double amin, double amid, double amax) - { - setConverter(fGyr, p, gyr, curve, amin, amid, amax); - } + /** + * Return the param value. + * + * @param p - the UI parameter index + * + * @return the param value. + */ + FAUSTFLOAT getParamValue(int p) { return *fItems[uint(p)].fZone; } - /** - * Used to edit accelerometer curves and mapping. Get curve and related mapping for a given UI parameter. - * - * @param p - the UI parameter index - * @param acc - the acc value to be retrieved (-1 means "no mapping") - * @param curve - the curve value to be retrieved (between 0 and 3) - * @param amin - the amin value to be retrieved - * @param amid - the amid value to be retrieved - * @param amax - the amax value to be retrieved - * - */ - void getAccConverter(int p, int& acc, int& curve, double& amin, double& amid, double& amax) - { - getConverter(fAcc, p, acc, curve, amin, amid, amax); + /** + * Return the param value. + * + * @param str - the UI parameter label/shortname/path + * + * @return the param value. + */ + FAUSTFLOAT getParamValue(const char* str) + { + int index = getParamIndex(str); + if (index >= 0) { + return getParamValue(index); + } else { + fprintf(stderr, "getParamValue : '%s' not found\n", + (str == nullptr ? "NULL" : str)); + return FAUSTFLOAT(0); } + } - /** - * Used to edit gyroscope curves and mapping. Get curve and related mapping for a given UI parameter. - * - * @param p - the UI parameter index - * @param gyr - the gyr value to be retrieved (-1 means "no mapping") - * @param curve - the curve value to be retrieved (between 0 and 3) - * @param amin - the amin value to be retrieved - * @param amid - the amid value to be retrieved - * @param amax - the amax value to be retrieved - * - */ - void getGyrConverter(int p, int& gyr, int& curve, double& amin, double& amid, double& amax) - { - getConverter(fGyr, p, gyr, curve, amin, amid, amax); + /** + * Set the param value. + * + * @param p - the UI parameter index + * @param v - the UI parameter value + * + */ + void setParamValue(int p, FAUSTFLOAT v) { *fItems[uint(p)].fZone = v; } + + /** + * Set the param value. + * + * @param p - the UI parameter label/shortname/path + * @param v - the UI parameter value + * + */ + void setParamValue(const char* path, FAUSTFLOAT v) + { + int index = getParamIndex(path); + if (index >= 0) { + setParamValue(index, v); + } else { + fprintf(stderr, "setParamValue : '%s' not found\n", + (path == nullptr ? "NULL" : path)); } + } + + double getParamRatio(int p) + { + return fItems[uint(p)].fConversion->faust2ui(*fItems[uint(p)].fZone); + } + void setParamRatio(int p, double r) + { + *fItems[uint(p)].fZone = FAUSTFLOAT(fItems[uint(p)].fConversion->ui2faust(r)); + } + + double value2ratio(int p, double r) + { + return fItems[uint(p)].fConversion->faust2ui(r); + } + double ratio2value(int p, double r) + { + return fItems[uint(p)].fConversion->ui2faust(r); + } - /** - * Set a new value coming from an gyroscope, propagate it to all relevant FAUSTFLOAT* zones. - * - * @param gyr - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope - * @param value - the new value - * - */ - void propagateGyr(int gyr, double value) - { - for (size_t i = 0; i < fGyr[gyr].size(); i++) { - fGyr[gyr][i]->update(value); + /** + * Return the control type (kAcc, kGyr, or -1) for a given parameter. + * + * @param p - the UI parameter index + * + * @return the type + */ + Type getParamType(int p) + { + if (p >= 0) { + if (getZoneIndex(fAcc, p, 0) != -1 || getZoneIndex(fAcc, p, 1) != -1 + || getZoneIndex(fAcc, p, 2) != -1) { + return kAcc; + } else if (getZoneIndex(fGyr, p, 0) != -1 || getZoneIndex(fGyr, p, 1) != -1 + || getZoneIndex(fGyr, p, 2) != -1) { + return kGyr; } } + return kNoType; + } - /** - * Get the number of FAUSTFLOAT* zones controlled with the accelerometer. - * - * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer - * @return the number of zones - * - */ - int getAccCount(int acc) - { - return (acc >= 0 && acc < 3) ? int(fAcc[acc].size()) : 0; - } + /** + * Return the Item type (kButton = 0, kCheckButton, kVSlider, kHSlider, kNumEntry, + * kHBargraph, kVBargraph) for a given parameter. + * + * @param p - the UI parameter index + * + * @return the Item type + */ + ItemType getParamItemType(int p) { return fItems[uint(p)].fItemType; } - /** - * Get the number of FAUSTFLOAT* zones controlled with the gyroscope. - * - * @param gyr - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope - * @param the number of zones - * - */ - int getGyrCount(int gyr) - { - return (gyr >= 0 && gyr < 3) ? int(fGyr[gyr].size()) : 0; + /** + * Set a new value coming from an accelerometer, propagate it to all relevant + * FAUSTFLOAT* zones. + * + * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer + * @param value - the new value + * + */ + void propagateAcc(int acc, double value) + { + for (size_t i = 0; i < fAcc[acc].size(); i++) { + fAcc[acc][i]->update(value); } + } - /** - * Get the requested screen color. - * - * -1 means no screen color control (no screencolor metadata found) - * otherwise return 0x00RRGGBB a ready to use color - * - */ - int getScreenColor() - { - if (fHasScreenControl) { - int r = (fRedReader) ? fRedReader->getValue() : 0; - int g = (fGreenReader) ? fGreenReader->getValue() : 0; - int b = (fBlueReader) ? fBlueReader->getValue() : 0; - return (r<<16) | (g<<8) | b; - } else { - return -1; - } + /** + * Used to edit accelerometer curves and mapping. Set curve and related mapping for a + * given UI parameter. + * + * @param p - the UI parameter index + * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer + * (-1 means "no mapping") + * @param curve - between 0 and 3 (0: up, 1: down, 2: up and down, 2: down and up) + * @param amin - mapping 'min' point + * @param amid - mapping 'middle' point + * @param amax - mapping 'max' point + * + */ + void setAccConverter(int p, int acc, int curve, double amin, double amid, double amax) + { + setConverter(fAcc, p, acc, curve, amin, amid, amax); + } + + /** + * Used to edit gyroscope curves and mapping. Set curve and related mapping for a + * given UI parameter. + * + * @param p - the UI parameter index + * @param gyr - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope (-1 means "no + * mapping") + * @param curve - between 0 and 3 (0: up, 1: down, 2: up and down, 2: down and up) + * @param amin - mapping 'min' point + * @param amid - mapping 'middle' point + * @param amax - mapping 'max' point + * + */ + void setGyrConverter(int p, int gyr, int curve, double amin, double amid, double amax) + { + setConverter(fGyr, p, gyr, curve, amin, amid, amax); + } + + /** + * Used to edit accelerometer curves and mapping. Get curve and related mapping for a + * given UI parameter. + * + * @param p - the UI parameter index + * @param acc - the acc value to be retrieved (-1 means "no mapping") + * @param curve - the curve value to be retrieved (between 0 and 3) + * @param amin - the amin value to be retrieved + * @param amid - the amid value to be retrieved + * @param amax - the amax value to be retrieved + * + */ + void getAccConverter(int p, int& acc, int& curve, double& amin, double& amid, + double& amax) + { + getConverter(fAcc, p, acc, curve, amin, amid, amax); + } + + /** + * Used to edit gyroscope curves and mapping. Get curve and related mapping for a + * given UI parameter. + * + * @param p - the UI parameter index + * @param gyr - the gyr value to be retrieved (-1 means "no mapping") + * @param curve - the curve value to be retrieved (between 0 and 3) + * @param amin - the amin value to be retrieved + * @param amid - the amid value to be retrieved + * @param amax - the amax value to be retrieved + * + */ + void getGyrConverter(int p, int& gyr, int& curve, double& amin, double& amid, + double& amax) + { + getConverter(fGyr, p, gyr, curve, amin, amid, amax); + } + + /** + * Set a new value coming from an gyroscope, propagate it to all relevant FAUSTFLOAT* + * zones. + * + * @param gyr - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope + * @param value - the new value + * + */ + void propagateGyr(int gyr, double value) + { + for (size_t i = 0; i < fGyr[gyr].size(); i++) { + fGyr[gyr][i]->update(value); } + } + + /** + * Get the number of FAUSTFLOAT* zones controlled with the accelerometer. + * + * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer + * @return the number of zones + * + */ + int getAccCount(int acc) { return (acc >= 0 && acc < 3) ? int(fAcc[acc].size()) : 0; } + + /** + * Get the number of FAUSTFLOAT* zones controlled with the gyroscope. + * + * @param gyr - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope + * @param the number of zones + * + */ + int getGyrCount(int gyr) { return (gyr >= 0 && gyr < 3) ? int(fGyr[gyr].size()) : 0; } + /** + * Get the requested screen color. + * + * -1 means no screen color control (no screencolor metadata found) + * otherwise return 0x00RRGGBB a ready to use color + * + */ + int getScreenColor() + { + if (fHasScreenControl) { + int r = (fRedReader) ? fRedReader->getValue() : 0; + int g = (fGreenReader) ? fGreenReader->getValue() : 0; + int b = (fBlueReader) ? fBlueReader->getValue() : 0; + return (r << 16) | (g << 8) | b; + } else { + return -1; + } + } }; #endif @@ -1972,23 +2078,23 @@ class APIUI : public PathBuilder, public Meta, public UI // FAUST Generated Code //---------------------------------------------------------------------------- - #ifndef FAUSTFLOAT #define FAUSTFLOAT float -#endif +#endif + +#include #include #include #include -#include -#ifndef FAUSTCLASS +#ifndef FAUSTCLASS #define FAUSTCLASS tonedsp #endif -#ifdef __APPLE__ +#ifdef __APPLE__ #define exp10f __exp10f -#define exp10 __exp10 +#define exp10 __exp10 #endif #if defined(_WIN32) @@ -1997,241 +2103,305 @@ class APIUI : public PathBuilder, public Meta, public UI #define RESTRICT __restrict__ #endif -class tonedspSIG0 { - - private: - - int iVec0[2]; - int iRec0[2]; - - public: - - int getNumInputstonedspSIG0() { - return 0; - } - int getNumOutputstonedspSIG0() { - return 1; - } - - void instanceInittonedspSIG0(int /*sample_rate*/) { - for (int l0 = 0; l0 < 2; l0 = l0 + 1) { - iVec0[l0] = 0; - } - for (int l1 = 0; l1 < 2; l1 = l1 + 1) { - iRec0[l1] = 0; - } - } - - void filltonedspSIG0(int count, float* table) { - for (int i1 = 0; i1 < count; i1 = i1 + 1) { - iVec0[0] = 1; - iRec0[0] = (iVec0[1] + iRec0[1]) % 65536; - table[i1] = std::sin(9.58738e-05f * float(iRec0[0])); - iVec0[1] = iVec0[0]; - iRec0[1] = iRec0[0]; - } - } - +class tonedspSIG0 +{ + private: + int iVec0[2]; + int iRec0[2]; + + public: + int getNumInputstonedspSIG0() { return 0; } + int getNumOutputstonedspSIG0() { return 1; } + + void instanceInittonedspSIG0(int /*sample_rate*/) + { + for (int l0 = 0; l0 < 2; l0 = l0 + 1) { + iVec0[l0] = 0; + } + for (int l1 = 0; l1 < 2; l1 = l1 + 1) { + iRec0[l1] = 0; + } + } + + void filltonedspSIG0(int count, float* table) + { + for (int i1 = 0; i1 < count; i1 = i1 + 1) { + iVec0[0] = 1; + iRec0[0] = (iVec0[1] + iRec0[1]) % 65536; + table[i1] = std::sin(9.58738e-05f * float(iRec0[0])); + iVec0[1] = iVec0[0]; + iRec0[1] = iRec0[0]; + } + } }; -static tonedspSIG0* newtonedspSIG0() { return (tonedspSIG0*)new tonedspSIG0(); } -static void deletetonedspSIG0(tonedspSIG0* dsp) { delete dsp; } +static tonedspSIG0* newtonedspSIG0() +{ + return (tonedspSIG0*)new tonedspSIG0(); +} +static void deletetonedspSIG0(tonedspSIG0* dsp) +{ + delete dsp; +} static float ftbl0tonedspSIG0[65536]; -class tonedsp : public dsp { - - private: - - int fSampleRate; - float fConst0; - float fConst1; - FAUSTFLOAT fHslider0; - FAUSTFLOAT fHslider1; - float fRec1[2]; - float fConst2; - float fConst3; - FAUSTFLOAT fButton0; - float fVec1[2]; - int iRec2[2]; - float fConst4; - FAUSTFLOAT fHslider2; - float fConst5; - float fRec3[2]; - float fRec4[2]; - float fConst6; - float fRec5[2]; - float fConst7; - float fRec6[2]; - float fConst8; - float fRec7[2]; - float fConst9; - float fRec8[2]; - float fConst10; - - public: - - void metadata(Meta* m) { - m->declare("basics.lib/name", "Faust Basic Element Library"); - m->declare("basics.lib/version", "0.8"); - m->declare("compile_options", "-a faust2header.cpp -lang cpp -i -inpl -cn tonedsp -es 1 -mcd 16 -single -ftz 0"); - m->declare("envelopes.lib/ar:author", "Yann Orlarey, Stéphane Letz"); - m->declare("envelopes.lib/author", "GRAME"); - m->declare("envelopes.lib/copyright", "GRAME"); - m->declare("envelopes.lib/license", "LGPL with exception"); - m->declare("envelopes.lib/name", "Faust Envelope Library"); - m->declare("envelopes.lib/version", "0.2"); - m->declare("filename", "tonedsp.dsp"); - m->declare("maths.lib/author", "GRAME"); - m->declare("maths.lib/copyright", "GRAME"); - m->declare("maths.lib/license", "LGPL with exception"); - m->declare("maths.lib/name", "Faust Math Library"); - m->declare("maths.lib/version", "2.5"); - m->declare("name", "tonedsp"); - m->declare("oscillators.lib/name", "Faust Oscillator Library"); - m->declare("oscillators.lib/version", "0.3"); - m->declare("platform.lib/name", "Generic Platform Library"); - m->declare("platform.lib/version", "0.2"); - m->declare("signals.lib/name", "Faust Signal Routing Library"); - m->declare("signals.lib/version", "0.3"); - m->declare("synths.lib/additiveDrum:author", "Romain Michon"); - m->declare("synths.lib/name", "Faust Synthesizer Library"); - m->declare("synths.lib/version", "0.1"); - } - - virtual int getNumInputs() { - return 0; - } - virtual int getNumOutputs() { - return 1; - } - - static void classInit(int sample_rate) { - tonedspSIG0* sig0 = newtonedspSIG0(); - sig0->instanceInittonedspSIG0(sample_rate); - sig0->filltonedspSIG0(65536, ftbl0tonedspSIG0); - deletetonedspSIG0(sig0); - } - - virtual void instanceConstants(int sample_rate) { - fSampleRate = sample_rate; - fConst0 = std::min(1.92e+05f, std::max(1.0f, float(fSampleRate))); - fConst1 = 1.0f / fConst0; - fConst2 = std::max(1.0f, 0.001f * fConst0); - fConst3 = 1.0f / fConst2; - fConst4 = 44.1f / fConst0; - fConst5 = 1.0f - fConst4; - fConst6 = 0.8666667f * fConst0; - fConst7 = 0.73333335f * fConst0; - fConst8 = 0.6f * fConst0; - fConst9 = 0.46666667f * fConst0; - fConst10 = 0.33333334f * fConst0; - } - - virtual void instanceResetUserInterface() { - fHslider0 = FAUSTFLOAT(4e+02f); - fHslider1 = FAUSTFLOAT(0.0f); - fButton0 = FAUSTFLOAT(0.0f); - fHslider2 = FAUSTFLOAT(2.5f); - } - - virtual void instanceClear() { - for (int l2 = 0; l2 < 2; l2 = l2 + 1) { - fRec1[l2] = 0.0f; - } - for (int l3 = 0; l3 < 2; l3 = l3 + 1) { - fVec1[l3] = 0.0f; - } - for (int l4 = 0; l4 < 2; l4 = l4 + 1) { - iRec2[l4] = 0; - } - for (int l5 = 0; l5 < 2; l5 = l5 + 1) { - fRec3[l5] = 0.0f; - } - for (int l6 = 0; l6 < 2; l6 = l6 + 1) { - fRec4[l6] = 0.0f; - } - for (int l7 = 0; l7 < 2; l7 = l7 + 1) { - fRec5[l7] = 0.0f; - } - for (int l8 = 0; l8 < 2; l8 = l8 + 1) { - fRec6[l8] = 0.0f; - } - for (int l9 = 0; l9 < 2; l9 = l9 + 1) { - fRec7[l9] = 0.0f; - } - for (int l10 = 0; l10 < 2; l10 = l10 + 1) { - fRec8[l10] = 0.0f; - } - } - - virtual void init(int sample_rate) { - classInit(sample_rate); - instanceInit(sample_rate); - } - virtual void instanceInit(int sample_rate) { - instanceConstants(sample_rate); - instanceResetUserInterface(); - instanceClear(); - } - - virtual tonedsp* clone() { - return new tonedsp(); - } - - virtual int getSampleRate() { - return fSampleRate; - } - - virtual void buildUserInterface(UI* ui_interface) { - ui_interface->openVerticalBox("tonedsp"); - ui_interface->addHorizontalSlider("freq", &fHslider0, FAUSTFLOAT(4e+02f), FAUSTFLOAT(5e+01f), FAUSTFLOAT(2e+03f), FAUSTFLOAT(0.01f)); - ui_interface->addButton("gate", &fButton0); - ui_interface->declare(&fHslider2, "acc", "0 0 -10 0 10"); - ui_interface->addHorizontalSlider("res", &fHslider2, FAUSTFLOAT(2.5f), FAUSTFLOAT(0.01f), FAUSTFLOAT(5.0f), FAUSTFLOAT(0.01f)); - ui_interface->addHorizontalSlider("y", &fHslider1, FAUSTFLOAT(0.0f), FAUSTFLOAT(0.0f), FAUSTFLOAT(1.0f), FAUSTFLOAT(0.01f)); - ui_interface->closeBox(); - } - - virtual void compute(int count, FAUSTFLOAT** /*inputs*/, FAUSTFLOAT** outputs) { - FAUSTFLOAT* output0 = outputs[0]; - float fSlow0 = float(fHslider0); - float fSlow1 = float(fHslider1); - float fSlow2 = fConst1 * fSlow0 * (0.8333333f * fSlow1 + 1.0f); - float fSlow3 = float(fButton0); - float fSlow4 = fConst4 * float(fHslider2); - float fSlow5 = fConst1 * fSlow0 * (1.6666666f * fSlow1 + 1.0f); - float fSlow6 = fConst1 * fSlow0 * (2.5f * fSlow1 + 1.0f); - float fSlow7 = fConst1 * fSlow0 * (3.3333333f * fSlow1 + 1.0f); - float fSlow8 = fConst1 * fSlow0 * (4.1666665f * fSlow1 + 1.0f); - float fSlow9 = fConst1 * fSlow0 * (5.0f * fSlow1 + 1.0f); - for (int i0 = 0; i0 < count; i0 = i0 + 1) { - fRec1[0] = fSlow2 + (fRec1[1] - std::floor(fSlow2 + fRec1[1])); - fVec1[0] = fSlow3; - iRec2[0] = (iRec2[1] + (iRec2[1] > 0)) * (fSlow3 <= fVec1[1]) + (fSlow3 > fVec1[1]); - float fTemp0 = float(iRec2[0]); - float fTemp1 = fConst3 * fTemp0; - float fTemp2 = fConst2 - fTemp0; - fRec3[0] = fSlow4 + fConst5 * fRec3[1]; - fRec4[0] = fSlow5 + (fRec4[1] - std::floor(fSlow5 + fRec4[1])); - fRec5[0] = fSlow6 + (fRec5[1] - std::floor(fSlow6 + fRec5[1])); - fRec6[0] = fSlow7 + (fRec6[1] - std::floor(fSlow7 + fRec6[1])); - fRec7[0] = fSlow8 + (fRec7[1] - std::floor(fSlow8 + fRec7[1])); - fRec8[0] = fSlow9 + (fRec8[1] - std::floor(fSlow9 + fRec8[1])); - output0[i0] = FAUSTFLOAT(0.05f * (0.44444445f * ftbl0tonedspSIG0[int(65536.0f * fRec1[0])] * std::max(0.0f, std::min(fTemp1, fTemp2 / std::max(1.0f, fConst0 * fRec3[0]) + 1.0f)) + ftbl0tonedspSIG0[int(65536.0f * fRec4[0])] * (0.0f - 0.11111111f * std::max(0.0f, std::min(fTemp1, fTemp2 / std::max(1.0f, fConst6 * fRec3[0]) + 1.0f))) + ftbl0tonedspSIG0[int(65536.0f * fRec5[0])] * (0.0f - 0.6666667f * std::max(0.0f, std::min(fTemp1, fTemp2 / std::max(1.0f, fConst7 * fRec3[0]) + 1.0f))) + ftbl0tonedspSIG0[int(65536.0f * fRec6[0])] * (0.0f - 1.2222222f * std::max(0.0f, std::min(fTemp1, fTemp2 / std::max(1.0f, fConst8 * fRec3[0]) + 1.0f))) + ftbl0tonedspSIG0[int(65536.0f * fRec7[0])] * (0.0f - 1.7777778f * std::max(0.0f, std::min(fTemp1, fTemp2 / std::max(1.0f, fConst9 * fRec3[0]) + 1.0f))) + ftbl0tonedspSIG0[int(65536.0f * fRec8[0])] * (0.0f - 2.3333333f * std::max(0.0f, std::min(fTemp1, fTemp2 / std::max(1.0f, fConst10 * fRec3[0]) + 1.0f))))); - fRec1[1] = fRec1[0]; - fVec1[1] = fVec1[0]; - iRec2[1] = iRec2[0]; - fRec3[1] = fRec3[0]; - fRec4[1] = fRec4[0]; - fRec5[1] = fRec5[0]; - fRec6[1] = fRec6[0]; - fRec7[1] = fRec7[0]; - fRec8[1] = fRec8[0]; - } - } - +class tonedsp : public dsp +{ + private: + int fSampleRate; + float fConst0; + float fConst1; + FAUSTFLOAT fHslider0; + FAUSTFLOAT fHslider1; + float fRec1[2]; + float fConst2; + float fConst3; + FAUSTFLOAT fButton0; + float fVec1[2]; + int iRec2[2]; + float fConst4; + FAUSTFLOAT fHslider2; + float fConst5; + float fRec3[2]; + float fRec4[2]; + float fConst6; + float fRec5[2]; + float fConst7; + float fRec6[2]; + float fConst8; + float fRec7[2]; + float fConst9; + float fRec8[2]; + float fConst10; + + public: + void metadata(Meta* m) + { + m->declare("basics.lib/name", "Faust Basic Element Library"); + m->declare("basics.lib/version", "0.8"); + m->declare("compile_options", + "-a faust2header.cpp -lang cpp -i -inpl -cn tonedsp -es 1 -mcd 16 " + "-single -ftz 0"); + m->declare("envelopes.lib/ar:author", "Yann Orlarey, Stéphane Letz"); + m->declare("envelopes.lib/author", "GRAME"); + m->declare("envelopes.lib/copyright", "GRAME"); + m->declare("envelopes.lib/license", "LGPL with exception"); + m->declare("envelopes.lib/name", "Faust Envelope Library"); + m->declare("envelopes.lib/version", "0.2"); + m->declare("filename", "tonedsp.dsp"); + m->declare("maths.lib/author", "GRAME"); + m->declare("maths.lib/copyright", "GRAME"); + m->declare("maths.lib/license", "LGPL with exception"); + m->declare("maths.lib/name", "Faust Math Library"); + m->declare("maths.lib/version", "2.5"); + m->declare("name", "tonedsp"); + m->declare("oscillators.lib/name", "Faust Oscillator Library"); + m->declare("oscillators.lib/version", "0.3"); + m->declare("platform.lib/name", "Generic Platform Library"); + m->declare("platform.lib/version", "0.2"); + m->declare("signals.lib/name", "Faust Signal Routing Library"); + m->declare("signals.lib/version", "0.3"); + m->declare("synths.lib/additiveDrum:author", "Romain Michon"); + m->declare("synths.lib/name", "Faust Synthesizer Library"); + m->declare("synths.lib/version", "0.1"); + } + + virtual int getNumInputs() { return 0; } + virtual int getNumOutputs() { return 1; } + + static void classInit(int sample_rate) + { + tonedspSIG0* sig0 = newtonedspSIG0(); + sig0->instanceInittonedspSIG0(sample_rate); + sig0->filltonedspSIG0(65536, ftbl0tonedspSIG0); + deletetonedspSIG0(sig0); + } + + virtual void instanceConstants(int sample_rate) + { + fSampleRate = sample_rate; + fConst0 = std::min(1.92e+05f, std::max(1.0f, float(fSampleRate))); + fConst1 = 1.0f / fConst0; + fConst2 = std::max(1.0f, 0.001f * fConst0); + fConst3 = 1.0f / fConst2; + fConst4 = 44.1f / fConst0; + fConst5 = 1.0f - fConst4; + fConst6 = 0.8666667f * fConst0; + fConst7 = 0.73333335f * fConst0; + fConst8 = 0.6f * fConst0; + fConst9 = 0.46666667f * fConst0; + fConst10 = 0.33333334f * fConst0; + } + + virtual void instanceResetUserInterface() + { + fHslider0 = FAUSTFLOAT(4e+02f); + fHslider1 = FAUSTFLOAT(0.0f); + fButton0 = FAUSTFLOAT(0.0f); + fHslider2 = FAUSTFLOAT(2.5f); + } + + virtual void instanceClear() + { + for (int l2 = 0; l2 < 2; l2 = l2 + 1) { + fRec1[l2] = 0.0f; + } + for (int l3 = 0; l3 < 2; l3 = l3 + 1) { + fVec1[l3] = 0.0f; + } + for (int l4 = 0; l4 < 2; l4 = l4 + 1) { + iRec2[l4] = 0; + } + for (int l5 = 0; l5 < 2; l5 = l5 + 1) { + fRec3[l5] = 0.0f; + } + for (int l6 = 0; l6 < 2; l6 = l6 + 1) { + fRec4[l6] = 0.0f; + } + for (int l7 = 0; l7 < 2; l7 = l7 + 1) { + fRec5[l7] = 0.0f; + } + for (int l8 = 0; l8 < 2; l8 = l8 + 1) { + fRec6[l8] = 0.0f; + } + for (int l9 = 0; l9 < 2; l9 = l9 + 1) { + fRec7[l9] = 0.0f; + } + for (int l10 = 0; l10 < 2; l10 = l10 + 1) { + fRec8[l10] = 0.0f; + } + } + + virtual void init(int sample_rate) + { + classInit(sample_rate); + instanceInit(sample_rate); + } + virtual void instanceInit(int sample_rate) + { + instanceConstants(sample_rate); + instanceResetUserInterface(); + instanceClear(); + } + + virtual tonedsp* clone() { return new tonedsp(); } + + virtual int getSampleRate() { return fSampleRate; } + + virtual void buildUserInterface(UI* ui_interface) + { + ui_interface->openVerticalBox("tonedsp"); + ui_interface->addHorizontalSlider("freq", &fHslider0, FAUSTFLOAT(4e+02f), + FAUSTFLOAT(5e+01f), FAUSTFLOAT(2e+03f), + FAUSTFLOAT(0.01f)); + ui_interface->addButton("gate", &fButton0); + ui_interface->declare(&fHslider2, "acc", "0 0 -10 0 10"); + ui_interface->addHorizontalSlider("res", &fHslider2, FAUSTFLOAT(2.5f), + FAUSTFLOAT(0.01f), FAUSTFLOAT(5.0f), + FAUSTFLOAT(0.01f)); + ui_interface->addHorizontalSlider("y", &fHslider1, FAUSTFLOAT(0.0f), + FAUSTFLOAT(0.0f), FAUSTFLOAT(1.0f), + FAUSTFLOAT(0.01f)); + ui_interface->closeBox(); + } + + virtual void compute(int count, FAUSTFLOAT** /*inputs*/, FAUSTFLOAT** outputs) + { + FAUSTFLOAT* output0 = outputs[0]; + float fSlow0 = float(fHslider0); + float fSlow1 = float(fHslider1); + float fSlow2 = fConst1 * fSlow0 * (0.8333333f * fSlow1 + 1.0f); + float fSlow3 = float(fButton0); + float fSlow4 = fConst4 * float(fHslider2); + float fSlow5 = fConst1 * fSlow0 * (1.6666666f * fSlow1 + 1.0f); + float fSlow6 = fConst1 * fSlow0 * (2.5f * fSlow1 + 1.0f); + float fSlow7 = fConst1 * fSlow0 * (3.3333333f * fSlow1 + 1.0f); + float fSlow8 = fConst1 * fSlow0 * (4.1666665f * fSlow1 + 1.0f); + float fSlow9 = fConst1 * fSlow0 * (5.0f * fSlow1 + 1.0f); + for (int i0 = 0; i0 < count; i0 = i0 + 1) { + fRec1[0] = fSlow2 + (fRec1[1] - std::floor(fSlow2 + fRec1[1])); + fVec1[0] = fSlow3; + iRec2[0] = + (iRec2[1] + (iRec2[1] > 0)) * (fSlow3 <= fVec1[1]) + (fSlow3 > fVec1[1]); + float fTemp0 = float(iRec2[0]); + float fTemp1 = fConst3 * fTemp0; + float fTemp2 = fConst2 - fTemp0; + fRec3[0] = fSlow4 + fConst5 * fRec3[1]; + fRec4[0] = fSlow5 + (fRec4[1] - std::floor(fSlow5 + fRec4[1])); + fRec5[0] = fSlow6 + (fRec5[1] - std::floor(fSlow6 + fRec5[1])); + fRec6[0] = fSlow7 + (fRec6[1] - std::floor(fSlow7 + fRec6[1])); + fRec7[0] = fSlow8 + (fRec7[1] - std::floor(fSlow8 + fRec7[1])); + fRec8[0] = fSlow9 + (fRec8[1] - std::floor(fSlow9 + fRec8[1])); + output0[i0] = FAUSTFLOAT( + 0.05f + * (0.44444445f * ftbl0tonedspSIG0[int(65536.0f * fRec1[0])] + * std::max( + 0.0f, + std::min( + fTemp1, + fTemp2 / std::max(1.0f, fConst0 * fRec3[0]) + 1.0f)) + + ftbl0tonedspSIG0[int(65536.0f * fRec4[0])] + * (0.0f + - 0.11111111f + * std::max( + 0.0f, + std::min( + fTemp1, fTemp2 + / std::max( + 1.0f, fConst6 * fRec3[0]) + + 1.0f))) + + ftbl0tonedspSIG0[int(65536.0f * fRec5[0])] + * (0.0f + - 0.6666667f + * std::max( + 0.0f, + std::min( + fTemp1, fTemp2 + / std::max( + 1.0f, fConst7 * fRec3[0]) + + 1.0f))) + + ftbl0tonedspSIG0[int(65536.0f * fRec6[0])] + * (0.0f + - 1.2222222f + * std::max( + 0.0f, + std::min( + fTemp1, fTemp2 + / std::max( + 1.0f, fConst8 * fRec3[0]) + + 1.0f))) + + ftbl0tonedspSIG0[int(65536.0f * fRec7[0])] + * (0.0f + - 1.7777778f + * std::max( + 0.0f, + std::min( + fTemp1, fTemp2 + / std::max( + 1.0f, fConst9 * fRec3[0]) + + 1.0f))) + + ftbl0tonedspSIG0[int(65536.0f * fRec8[0])] + * (0.0f + - 2.3333333f + * std::max( + 0.0f, + std::min( + fTemp1, fTemp2 + / std::max( + 1.0f, fConst10 * fRec3[0]) + + 1.0f))))); + fRec1[1] = fRec1[0]; + fVec1[1] = fVec1[0]; + iRec2[1] = iRec2[0]; + fRec3[1] = fRec3[0]; + fRec4[1] = fRec4[0]; + fRec5[1] = fRec5[0]; + fRec6[1] = fRec6[0]; + fRec7[1] = fRec7[0]; + fRec8[1] = fRec8[0]; + } + } }; - #endif diff --git a/src/volumedsp.h b/src/volumedsp.h index f3df212..88db980 100644 --- a/src/volumedsp.h +++ b/src/volumedsp.h @@ -4,11 +4,12 @@ license: "MIT Style STK-4.2" name: "volume" version: "1.0" Code generated with Faust 2.41.1 (https://faust.grame.fr) -Compilation options: -a faust2header.cpp -lang cpp -i -inpl -cn volumedsp -es 1 -mcd 16 -single -ftz 0 +Compilation options: -a faust2header.cpp -lang cpp -i -inpl -cn volumedsp -es 1 -mcd 16 +-single -ftz 0 ------------------------------------------------------------ */ -#ifndef __volumedsp_H__ -#define __volumedsp_H__ +#ifndef __volumedsp_H__ +#define __volumedsp_H__ // NOTE: ANY INCLUDE-GUARD HERE MUST BE DERIVED FROM THE CLASS NAME // @@ -25,16 +26,16 @@ Compilation options: -a faust2header.cpp -lang cpp -i -inpl -cn volumedsp -es 1 it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + EXCEPTION : As a special exception, you may create a larger work that contains this FAUST architecture section and distribute that work under terms of your choice, so long as this FAUST @@ -73,29 +74,29 @@ Compilation options: -a faust2header.cpp -lang cpp -i -inpl -cn volumedsp -es 1 #define FAUSTVERSION "2.41.1" -// Use FAUST_API for code that is part of the external API but is also compiled in faust and libfaust -// Use LIBFAUST_API for code that is compiled in faust and libfaust +// Use FAUST_API for code that is part of the external API but is also compiled in faust +// and libfaust Use LIBFAUST_API for code that is compiled in faust and libfaust #ifdef _WIN32 - #pragma warning (disable: 4251) - #ifdef FAUST_EXE - #define FAUST_API - #define LIBFAUST_API - #elif FAUST_LIB - #define FAUST_API __declspec(dllexport) - #define LIBFAUST_API __declspec(dllexport) - #else - #define FAUST_API - #define LIBFAUST_API - #endif +#pragma warning(disable : 4251) +#ifdef FAUST_EXE +#define FAUST_API +#define LIBFAUST_API +#elif FAUST_LIB +#define FAUST_API __declspec(dllexport) +#define LIBFAUST_API __declspec(dllexport) #else - #ifdef FAUST_EXE - #define FAUST_API - #define LIBFAUST_API - #else - #define FAUST_API __attribute__((visibility("default"))) - #define LIBFAUST_API __attribute__((visibility("default"))) - #endif +#define FAUST_API +#define LIBFAUST_API +#endif +#else +#ifdef FAUST_EXE +#define FAUST_API +#define LIBFAUST_API +#else +#define FAUST_API __attribute__((visibility("default"))) +#define LIBFAUST_API __attribute__((visibility("default"))) +#endif #endif #endif @@ -112,15 +113,14 @@ struct FAUST_API Meta; */ struct FAUST_API dsp_memory_manager { - virtual ~dsp_memory_manager() {} - + /** * Inform the Memory Manager with the number of expected memory zones. * @param count - the number of expected memory zones */ virtual void begin(size_t /*count*/) {} - + /** * Give the Memory Manager information on a given memory zone. * @param size - the size in bytes of the memory zone @@ -128,151 +128,167 @@ struct FAUST_API dsp_memory_manager { * @param writes - the number of Write access to the zone used to compute one frame */ virtual void info(size_t /*size*/, size_t /*reads*/, size_t /*writes*/) {} - + /** * Inform the Memory Manager that all memory zones have been described, * to possibly start a 'compute the best allocation strategy' step. */ virtual void end() {} - + /** * Allocate a memory zone. * @param size - the memory zone size in bytes */ virtual void* allocate(size_t size) = 0; - + /** * Destroy a memory zone. * @param ptr - the memory zone pointer to be deallocated */ virtual void destroy(void* ptr) = 0; - }; /** -* Signal processor definition. -*/ - -class FAUST_API dsp { - - public: - - dsp() {} - virtual ~dsp() {} - - /* Return instance number of audio inputs */ - virtual int getNumInputs() = 0; - - /* Return instance number of audio outputs */ - virtual int getNumOutputs() = 0; - - /** - * Trigger the ui_interface parameter with instance specific calls - * to 'openTabBox', 'addButton', 'addVerticalSlider'... in order to build the UI. - * - * @param ui_interface - the user interface builder - */ - virtual void buildUserInterface(UI* ui_interface) = 0; - - /* Return the sample rate currently used by the instance */ - virtual int getSampleRate() = 0; - - /** - * Global init, calls the following methods: - * - static class 'classInit': static tables initialization - * - 'instanceInit': constants and instance state initialization - * - * @param sample_rate - the sampling rate in Hz - */ - virtual void init(int sample_rate) = 0; - - /** - * Init instance state - * - * @param sample_rate - the sampling rate in Hz - */ - virtual void instanceInit(int sample_rate) = 0; - - /** - * Init instance constant state - * - * @param sample_rate - the sampling rate in Hz - */ - virtual void instanceConstants(int sample_rate) = 0; - - /* Init default control parameters values */ - virtual void instanceResetUserInterface() = 0; - - /* Init instance state (like delay lines...) but keep the control parameter values */ - virtual void instanceClear() = 0; - - /** - * Return a clone of the instance. - * - * @return a copy of the instance on success, otherwise a null pointer. - */ - virtual dsp* clone() = 0; - - /** - * Trigger the Meta* parameter with instance specific calls to 'declare' (key, value) metadata. - * - * @param m - the Meta* meta user - */ - virtual void metadata(Meta* m) = 0; - - /** - * DSP instance computation, to be called with successive in/out audio buffers. - * - * @param count - the number of frames to compute - * @param inputs - the input audio buffers as an array of non-interleaved FAUSTFLOAT samples (eiher float, double or quad) - * @param outputs - the output audio buffers as an array of non-interleaved FAUSTFLOAT samples (eiher float, double or quad) - * - */ - virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) = 0; - - /** - * DSP instance computation: alternative method to be used by subclasses. - * - * @param date_usec - the timestamp in microsec given by audio driver. - * @param count - the number of frames to compute - * @param inputs - the input audio buffers as an array of non-interleaved FAUSTFLOAT samples (either float, double or quad) - * @param outputs - the output audio buffers as an array of non-interleaved FAUSTFLOAT samples (either float, double or quad) - * - */ - virtual void compute(double /*date_usec*/, int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { compute(count, inputs, outputs); } - -}; - -/** - * Generic DSP decorator. + * Signal processor definition. */ -class FAUST_API decorator_dsp : public dsp { +class FAUST_API dsp +{ + public: + dsp() {} + virtual ~dsp() {} + + /* Return instance number of audio inputs */ + virtual int getNumInputs() = 0; + + /* Return instance number of audio outputs */ + virtual int getNumOutputs() = 0; + + /** + * Trigger the ui_interface parameter with instance specific calls + * to 'openTabBox', 'addButton', 'addVerticalSlider'... in order to build the UI. + * + * @param ui_interface - the user interface builder + */ + virtual void buildUserInterface(UI* ui_interface) = 0; + + /* Return the sample rate currently used by the instance */ + virtual int getSampleRate() = 0; + + /** + * Global init, calls the following methods: + * - static class 'classInit': static tables initialization + * - 'instanceInit': constants and instance state initialization + * + * @param sample_rate - the sampling rate in Hz + */ + virtual void init(int sample_rate) = 0; + + /** + * Init instance state + * + * @param sample_rate - the sampling rate in Hz + */ + virtual void instanceInit(int sample_rate) = 0; - protected: + /** + * Init instance constant state + * + * @param sample_rate - the sampling rate in Hz + */ + virtual void instanceConstants(int sample_rate) = 0; - dsp* fDSP; + /* Init default control parameters values */ + virtual void instanceResetUserInterface() = 0; + + /* Init instance state (like delay lines...) but keep the control parameter values */ + virtual void instanceClear() = 0; + + /** + * Return a clone of the instance. + * + * @return a copy of the instance on success, otherwise a null pointer. + */ + virtual dsp* clone() = 0; - public: + /** + * Trigger the Meta* parameter with instance specific calls to 'declare' (key, value) + * metadata. + * + * @param m - the Meta* meta user + */ + virtual void metadata(Meta* m) = 0; - decorator_dsp(dsp* dsp = nullptr):fDSP(dsp) {} - virtual ~decorator_dsp() { delete fDSP; } + /** + * DSP instance computation, to be called with successive in/out audio buffers. + * + * @param count - the number of frames to compute + * @param inputs - the input audio buffers as an array of non-interleaved FAUSTFLOAT + * samples (eiher float, double or quad) + * @param outputs - the output audio buffers as an array of non-interleaved FAUSTFLOAT + * samples (eiher float, double or quad) + * + */ + virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) = 0; - virtual int getNumInputs() { return fDSP->getNumInputs(); } - virtual int getNumOutputs() { return fDSP->getNumOutputs(); } - virtual void buildUserInterface(UI* ui_interface) { fDSP->buildUserInterface(ui_interface); } - virtual int getSampleRate() { return fDSP->getSampleRate(); } - virtual void init(int sample_rate) { fDSP->init(sample_rate); } - virtual void instanceInit(int sample_rate) { fDSP->instanceInit(sample_rate); } - virtual void instanceConstants(int sample_rate) { fDSP->instanceConstants(sample_rate); } - virtual void instanceResetUserInterface() { fDSP->instanceResetUserInterface(); } - virtual void instanceClear() { fDSP->instanceClear(); } - virtual decorator_dsp* clone() { return new decorator_dsp(fDSP->clone()); } - virtual void metadata(Meta* m) { fDSP->metadata(m); } - // Beware: subclasses usually have to overload the two 'compute' methods - virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { fDSP->compute(count, inputs, outputs); } - virtual void compute(double date_usec, int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { fDSP->compute(date_usec, count, inputs, outputs); } - + /** + * DSP instance computation: alternative method to be used by subclasses. + * + * @param date_usec - the timestamp in microsec given by audio driver. + * @param count - the number of frames to compute + * @param inputs - the input audio buffers as an array of non-interleaved FAUSTFLOAT + * samples (either float, double or quad) + * @param outputs - the output audio buffers as an array of non-interleaved FAUSTFLOAT + * samples (either float, double or quad) + * + */ + virtual void compute(double /*date_usec*/, int count, FAUSTFLOAT** inputs, + FAUSTFLOAT** outputs) + { + compute(count, inputs, outputs); + } +}; + +/** + * Generic DSP decorator. + */ + +class FAUST_API decorator_dsp : public dsp +{ + protected: + dsp* fDSP; + + public: + decorator_dsp(dsp* dsp = nullptr) : fDSP(dsp) {} + virtual ~decorator_dsp() { delete fDSP; } + + virtual int getNumInputs() { return fDSP->getNumInputs(); } + virtual int getNumOutputs() { return fDSP->getNumOutputs(); } + virtual void buildUserInterface(UI* ui_interface) + { + fDSP->buildUserInterface(ui_interface); + } + virtual int getSampleRate() { return fDSP->getSampleRate(); } + virtual void init(int sample_rate) { fDSP->init(sample_rate); } + virtual void instanceInit(int sample_rate) { fDSP->instanceInit(sample_rate); } + virtual void instanceConstants(int sample_rate) + { + fDSP->instanceConstants(sample_rate); + } + virtual void instanceResetUserInterface() { fDSP->instanceResetUserInterface(); } + virtual void instanceClear() { fDSP->instanceClear(); } + virtual decorator_dsp* clone() { return new decorator_dsp(fDSP->clone()); } + virtual void metadata(Meta* m) { fDSP->metadata(m); } + // Beware: subclasses usually have to overload the two 'compute' methods + virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) + { + fDSP->compute(count, inputs, outputs); + } + virtual void compute(double date_usec, int count, FAUSTFLOAT** inputs, + FAUSTFLOAT** outputs) + { + fDSP->compute(date_usec, count, inputs, outputs); + } }; /** @@ -280,85 +296,76 @@ class FAUST_API decorator_dsp : public dsp { * to create DSP instances from a compiled DSP program. */ -class FAUST_API dsp_factory { - - protected: - - // So that to force sub-classes to use deleteDSPFactory(dsp_factory* factory); - virtual ~dsp_factory() {} - - public: - - virtual std::string getName() = 0; - virtual std::string getSHAKey() = 0; - virtual std::string getDSPCode() = 0; - virtual std::string getCompileOptions() = 0; - virtual std::vector getLibraryList() = 0; - virtual std::vector getIncludePathnames() = 0; - - virtual dsp* createDSPInstance() = 0; - - virtual void setMemoryManager(dsp_memory_manager* manager) = 0; - virtual dsp_memory_manager* getMemoryManager() = 0; - +class FAUST_API dsp_factory +{ + protected: + // So that to force sub-classes to use deleteDSPFactory(dsp_factory* factory); + virtual ~dsp_factory() {} + + public: + virtual std::string getName() = 0; + virtual std::string getSHAKey() = 0; + virtual std::string getDSPCode() = 0; + virtual std::string getCompileOptions() = 0; + virtual std::vector getLibraryList() = 0; + virtual std::vector getIncludePathnames() = 0; + + virtual dsp* createDSPInstance() = 0; + + virtual void setMemoryManager(dsp_memory_manager* manager) = 0; + virtual dsp_memory_manager* getMemoryManager() = 0; }; // Denormal handling -#if defined (__SSE__) +#if defined(__SSE__) #include #endif -class FAUST_API ScopedNoDenormals { - - private: - - intptr_t fpsr; - - void setFpStatusRegister(intptr_t fpsr_aux) noexcept - { - #if defined (__arm64__) || defined (__aarch64__) - asm volatile("msr fpcr, %0" : : "ri" (fpsr_aux)); - #elif defined (__SSE__) - _mm_setcsr(static_cast(fpsr_aux)); - #endif - } - - void getFpStatusRegister() noexcept - { - #if defined (__arm64__) || defined (__aarch64__) - asm volatile("mrs %0, fpcr" : "=r" (fpsr)); - #elif defined ( __SSE__) - fpsr = static_cast(_mm_getcsr()); - #endif - } - - public: - - ScopedNoDenormals() noexcept - { - #if defined (__arm64__) || defined (__aarch64__) - intptr_t mask = (1 << 24 /* FZ */); - #else - #if defined(__SSE__) - #if defined(__SSE2__) - intptr_t mask = 0x8040; - #else - intptr_t mask = 0x8000; - #endif - #else - intptr_t mask = 0x0000; - #endif - #endif - getFpStatusRegister(); - setFpStatusRegister(fpsr | mask); - } - - ~ScopedNoDenormals() noexcept - { - setFpStatusRegister(fpsr); - } +class FAUST_API ScopedNoDenormals +{ + private: + intptr_t fpsr; + + void setFpStatusRegister(intptr_t fpsr_aux) noexcept + { +#if defined(__arm64__) || defined(__aarch64__) + asm volatile("msr fpcr, %0" : : "ri"(fpsr_aux)); +#elif defined(__SSE__) + _mm_setcsr(static_cast(fpsr_aux)); +#endif + } + + void getFpStatusRegister() noexcept + { +#if defined(__arm64__) || defined(__aarch64__) + asm volatile("mrs %0, fpcr" : "=r"(fpsr)); +#elif defined(__SSE__) + fpsr = static_cast(_mm_getcsr()); +#endif + } + + public: + ScopedNoDenormals() noexcept + { +#if defined(__arm64__) || defined(__aarch64__) + intptr_t mask = (1 << 24 /* FZ */); +#else +#if defined(__SSE__) +#if defined(__SSE2__) + intptr_t mask = 0x8040; +#else + intptr_t mask = 0x8000; +#endif +#else + intptr_t mask = 0x0000; +#endif +#endif + getFpStatusRegister(); + setFpStatusRegister(fpsr | mask); + } + ~ScopedNoDenormals() noexcept { setFpStatusRegister(fpsr); } }; #define AVOIDDENORMALS ScopedNoDenormals(); @@ -393,11 +400,12 @@ architecture section is not modified. #ifndef API_UI_H #define API_UI_H +#include + +#include #include #include #include -#include -#include /************************** BEGIN meta.h ******************************* FAUST Architecture File @@ -407,16 +415,16 @@ architecture section is not modified. it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + EXCEPTION : As a special exception, you may create a larger work that contains this FAUST architecture section and distribute that work under terms of your choice, so long as this FAUST @@ -426,9 +434,9 @@ architecture section is not modified. #ifndef __meta__ #define __meta__ - /** - The base class of Meta handler to be used in dsp::metadata(Meta* m) method to retrieve (key, value) metadata. + The base class of Meta handler to be used in dsp::metadata(Meta* m) method to retrieve + (key, value) metadata. */ struct FAUST_API Meta { virtual ~Meta() {} @@ -445,16 +453,16 @@ struct FAUST_API Meta { it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + EXCEPTION : As a special exception, you may create a larger work that contains this FAUST architecture section and distribute that work under terms of your choice, so long as this FAUST @@ -464,7 +472,6 @@ struct FAUST_API Meta { #ifndef __UI_H__ #define __UI_H__ - #ifndef FAUSTFLOAT #define FAUSTFLOAT float #endif @@ -478,40 +485,45 @@ struct FAUST_API Meta { struct Soundfile; -template +template struct FAUST_API UIReal { - UIReal() {} virtual ~UIReal() {} - + // -- widget's layouts - - virtual void openTabBox(const char* label) = 0; + + virtual void openTabBox(const char* label) = 0; virtual void openHorizontalBox(const char* label) = 0; - virtual void openVerticalBox(const char* label) = 0; - virtual void closeBox() = 0; - + virtual void openVerticalBox(const char* label) = 0; + virtual void closeBox() = 0; + // -- active widgets - - virtual void addButton(const char* label, REAL* zone) = 0; + + virtual void addButton(const char* label, REAL* zone) = 0; virtual void addCheckButton(const char* label, REAL* zone) = 0; - virtual void addVerticalSlider(const char* label, REAL* zone, REAL init, REAL min, REAL max, REAL step) = 0; - virtual void addHorizontalSlider(const char* label, REAL* zone, REAL init, REAL min, REAL max, REAL step) = 0; - virtual void addNumEntry(const char* label, REAL* zone, REAL init, REAL min, REAL max, REAL step) = 0; - + virtual void addVerticalSlider(const char* label, REAL* zone, REAL init, REAL min, + REAL max, REAL step) = 0; + virtual void addHorizontalSlider(const char* label, REAL* zone, REAL init, REAL min, + REAL max, REAL step) = 0; + virtual void addNumEntry(const char* label, REAL* zone, REAL init, REAL min, REAL max, + REAL step) = 0; + // -- passive widgets - - virtual void addHorizontalBargraph(const char* label, REAL* zone, REAL min, REAL max) = 0; - virtual void addVerticalBargraph(const char* label, REAL* zone, REAL min, REAL max) = 0; - + + virtual void addHorizontalBargraph(const char* label, REAL* zone, REAL min, + REAL max) = 0; + virtual void addVerticalBargraph(const char* label, REAL* zone, REAL min, + REAL max) = 0; + // -- soundfiles - - virtual void addSoundfile(const char* /*label*/, const char* /*filename*/, Soundfile** /*sf_zone*/) = 0; - + + virtual void addSoundfile(const char* /*label*/, const char* /*filename*/, + Soundfile** /*sf_zone*/) = 0; + // -- metadata declarations - + virtual void declare(REAL* /*zone*/, const char* /*key*/, const char* /*val*/) {} - + // To be used by LLVM client virtual int sizeOfFAUSTFLOAT() { return sizeof(FAUSTFLOAT); } }; @@ -531,16 +543,16 @@ struct FAUST_API UI : public UIReal { it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + EXCEPTION : As a special exception, you may create a larger work that contains this FAUST architecture section and distribute that work under terms of your choice, so long as this FAUST @@ -550,187 +562,199 @@ struct FAUST_API UI : public UIReal { #ifndef __PathBuilder__ #define __PathBuilder__ -#include -#include -#include -#include #include +#include #include - +#include +#include +#include /******************************************************************************* * PathBuilder : Faust User Interface * Helper class to build complete hierarchical path for UI items. ******************************************************************************/ -class FAUST_API PathBuilder { - - protected: - - std::vector fControlsLevel; - std::vector fFullPaths; - std::map fFull2Short; // filled by computeShortNames() - - /** - * @brief check if a character is acceptable for an ID - * - * @param c - * @return true is the character is acceptable for an ID - */ - bool isIDChar(char c) const - { - return ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) || ((c >= '0') && (c <= '9')); - } - - /** - * @brief remove all "/0x00" parts - * - * @param src - * @return modified string - */ - std::string remove0x00(const std::string& src) const - { - return std::regex_replace(src, std::regex("/0x00"), ""); - } - - /** - * @brief replace all non ID char with '_' (one '_' may replace several non ID char) - * - * @param src - * @return modified string - */ - std::string str2ID(const std::string& src) const - { - std::string dst; - bool need_underscore = false; - for (char c : src) { - if (isIDChar(c) || (c == '/')) { - if (need_underscore) { - dst.push_back('_'); - need_underscore = false; - } - dst.push_back(c); - } else { - need_underscore = true; +class FAUST_API PathBuilder +{ + protected: + std::vector fControlsLevel; + std::vector fFullPaths; + std::map fFull2Short; // filled by computeShortNames() + + /** + * @brief check if a character is acceptable for an ID + * + * @param c + * @return true is the character is acceptable for an ID + */ + bool isIDChar(char c) const + { + return ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) + || ((c >= '0') && (c <= '9')); + } + + /** + * @brief remove all "/0x00" parts + * + * @param src + * @return modified string + */ + std::string remove0x00(const std::string& src) const + { + return std::regex_replace(src, std::regex("/0x00"), ""); + } + + /** + * @brief replace all non ID char with '_' (one '_' may replace several non ID char) + * + * @param src + * @return modified string + */ + std::string str2ID(const std::string& src) const + { + std::string dst; + bool need_underscore = false; + for (char c : src) { + if (isIDChar(c) || (c == '/')) { + if (need_underscore) { + dst.push_back('_'); + need_underscore = false; } + dst.push_back(c); + } else { + need_underscore = true; } - return dst; } - - /** - * @brief Keep only the last n slash-parts - * - * @param src - * @param n : 1 indicates the last slash-part - * @return modified string - */ - std::string cut(const std::string& src, int n) const - { - std::string rdst; - for (int i = int(src.length())-1; i >= 0; i--) { - char c = src[i]; - if (c != '/') { - rdst.push_back(c); - } else if (n == 1) { - std::string dst; - for (int j = int(rdst.length())-1; j >= 0; j--) { - dst.push_back(rdst[j]); - } - return dst; - } else { - n--; - rdst.push_back(c); + return dst; + } + + /** + * @brief Keep only the last n slash-parts + * + * @param src + * @param n : 1 indicates the last slash-part + * @return modified string + */ + std::string cut(const std::string& src, int n) const + { + std::string rdst; + for (int i = int(src.length()) - 1; i >= 0; i--) { + char c = src[i]; + if (c != '/') { + rdst.push_back(c); + } else if (n == 1) { + std::string dst; + for (int j = int(rdst.length()) - 1; j >= 0; j--) { + dst.push_back(rdst[j]); } + return dst; + } else { + n--; + rdst.push_back(c); } - return src; } - - void addFullPath(const std::string& label) { fFullPaths.push_back(buildPath(label)); } - - /** - * @brief Compute the mapping between full path and short names - */ - void computeShortNames() - { - std::vector uniquePaths; // all full paths transformed but made unique with a prefix - std::map unique2full; // all full paths transformed but made unique with a prefix - char num_buffer[16]; - int pnum = 0; - - for (const auto& s : fFullPaths) { - sprintf(num_buffer, "%d", pnum++); - std::string u = "/P" + std::string(num_buffer) + str2ID(remove0x00(s)); - uniquePaths.push_back(u); - unique2full[u] = s; // remember the full path associated to a unique path - } - - std::map uniquePath2level; // map path to level - for (const auto& s : uniquePaths) uniquePath2level[s] = 1; // we init all levels to 1 - bool have_collisions = true; - - while (have_collisions) { - // compute collision list - std::set collisionSet; - std::map short2full; - have_collisions = false; - for (const auto& it : uniquePath2level) { - std::string u = it.first; - int n = it.second; - std::string shortName = cut(u, n); - auto p = short2full.find(shortName); - if (p == short2full.end()) { - // no collision - short2full[shortName] = u; - } else { - // we have a collision, add the two paths to the collision set - have_collisions = true; - collisionSet.insert(u); - collisionSet.insert(p->second); - } - } - for (const auto& s : collisionSet) uniquePath2level[s]++; // increase level of colliding path - } - + return src; + } + + void addFullPath(const std::string& label) { fFullPaths.push_back(buildPath(label)); } + + /** + * @brief Compute the mapping between full path and short names + */ + void computeShortNames() + { + std::vector + uniquePaths; // all full paths transformed but made unique with a prefix + std::map + unique2full; // all full paths transformed but made unique with a prefix + char num_buffer[16]; + int pnum = 0; + + for (const auto& s : fFullPaths) { + sprintf(num_buffer, "%d", pnum++); + std::string u = "/P" + std::string(num_buffer) + str2ID(remove0x00(s)); + uniquePaths.push_back(u); + unique2full[u] = s; // remember the full path associated to a unique path + } + + std::map uniquePath2level; // map path to level + for (const auto& s : uniquePaths) + uniquePath2level[s] = 1; // we init all levels to 1 + bool have_collisions = true; + + while (have_collisions) { + // compute collision list + std::set collisionSet; + std::map short2full; + have_collisions = false; for (const auto& it : uniquePath2level) { - std::string u = it.first; - int n = it.second; - std::string shortName = replaceCharList(cut(u, n), {'/'}, '_'); - fFull2Short[unique2full[u]] = shortName; + std::string u = it.first; + int n = it.second; + std::string shortName = cut(u, n); + auto p = short2full.find(shortName); + if (p == short2full.end()) { + // no collision + short2full[shortName] = u; + } else { + // we have a collision, add the two paths to the collision set + have_collisions = true; + collisionSet.insert(u); + collisionSet.insert(p->second); + } } + for (const auto& s : collisionSet) + uniquePath2level[s]++; // increase level of colliding path } - - std::string replaceCharList(const std::string& str, const std::vector& ch1, char ch2) - { - auto beg = ch1.begin(); - auto end = ch1.end(); - std::string res = str; - for (size_t i = 0; i < str.length(); ++i) { - if (std::find(beg, end, str[i]) != end) res[i] = ch2; - } - return res; + + for (const auto& it : uniquePath2level) { + std::string u = it.first; + int n = it.second; + std::string shortName = replaceCharList(cut(u, n), {'/'}, '_'); + fFull2Short[unique2full[u]] = shortName; } - - public: - - PathBuilder() {} - virtual ~PathBuilder() {} - - // Return true for the first level of groups - bool pushLabel(const std::string& label) { fControlsLevel.push_back(label); return fControlsLevel.size() == 1;} - - // Return true for the last level of groups - bool popLabel() { fControlsLevel.pop_back(); return fControlsLevel.size() == 0; } - - std::string buildPath(const std::string& label) - { - std::string res = "/"; - for (size_t i = 0; i < fControlsLevel.size(); i++) { - res = res + fControlsLevel[i] + "/"; - } - res += label; - return replaceCharList(res, {' ', '#', '*', ',', '?', '[', ']', '{', '}', '(', ')'}, '_'); + } + + std::string replaceCharList(const std::string& str, const std::vector& ch1, + char ch2) + { + auto beg = ch1.begin(); + auto end = ch1.end(); + std::string res = str; + for (size_t i = 0; i < str.length(); ++i) { + if (std::find(beg, end, str[i]) != end) + res[i] = ch2; } - + return res; + } + + public: + PathBuilder() {} + virtual ~PathBuilder() {} + + // Return true for the first level of groups + bool pushLabel(const std::string& label) + { + fControlsLevel.push_back(label); + return fControlsLevel.size() == 1; + } + + // Return true for the last level of groups + bool popLabel() + { + fControlsLevel.pop_back(); + return fControlsLevel.size() == 0; + } + + std::string buildPath(const std::string& label) + { + std::string res = "/"; + for (size_t i = 0; i < fControlsLevel.size(); i++) { + res = res + fControlsLevel[i] + "/"; + } + res += label; + return replaceCharList( + res, {' ', '#', '*', ',', '?', '[', ']', '{', '}', '(', ')'}, '_'); + } }; #endif // __PathBuilder__ @@ -743,16 +767,16 @@ class FAUST_API PathBuilder { it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + EXCEPTION : As a special exception, you may create a larger work that contains this FAUST architecture section and distribute that work under terms of your choice, so long as this FAUST @@ -765,52 +789,53 @@ class FAUST_API PathBuilder { /*************************************************************************************** ValueConverter.h (GRAME, Copyright 2015-2019) - + Set of conversion objects used to map user interface values (for example a gui slider delivering values between 0 and 1) to faust values (for example a vslider between 20 and 20000) using a log scale. - + -- Utilities - + Range(lo,hi) : clip a value x between lo and hi - Interpolator(lo,hi,v1,v2) : Maps a value x between lo and hi to a value y between v1 and v2 - Interpolator3pt(lo,mi,hi,v1,vm,v2) : Map values between lo mid hi to values between v1 vm v2 - + Interpolator(lo,hi,v1,v2) : Maps a value x between lo and hi to a value y between v1 and +v2 Interpolator3pt(lo,mi,hi,v1,vm,v2) : Map values between lo mid hi to values between v1 +vm v2 + -- Value Converters - + ValueConverter::ui2faust(x) ValueConverter::faust2ui(x) - + -- ValueConverters used for sliders depending of the scale - + LinearValueConverter(umin, umax, fmin, fmax) LinearValueConverter2(lo, mi, hi, v1, vm, v2) using 2 segments LogValueConverter(umin, umax, fmin, fmax) ExpValueConverter(umin, umax, fmin, fmax) - + -- ValueConverters used for accelerometers based on 3 points - + AccUpConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 0 AccDownConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 1 AccUpDownConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 2 AccDownUpConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 3 - + -- lists of ZoneControl are used to implement accelerometers metadata for each axes - + ZoneControl(zone, valueConverter) : a zone with an accelerometer data converter - + -- ZoneReader are used to implement screencolor metadata - + ZoneReader(zone, valueConverter) : a zone with a data converter ****************************************************************************************/ +#include #include -#include // std::max + +#include // std::max #include #include -#include - //-------------------------------------------------------------------------------------- // Interpolator(lo,hi,v1,v2) @@ -821,458 +846,485 @@ class FAUST_API PathBuilder { // y = v1 - lo*coef + x*coef // y = offset + x*coef with offset = v1 - lo*coef //-------------------------------------------------------------------------------------- -class FAUST_API Interpolator { - - private: - - //-------------------------------------------------------------------------------------- - // Range(lo,hi) clip a value between lo and hi - //-------------------------------------------------------------------------------------- - struct Range - { - double fLo; - double fHi; - - Range(double x, double y) : fLo(std::min(x,y)), fHi(std::max(x,y)) {} - double operator()(double x) { return (xfHi) ? fHi : x; } - }; - - - Range fRange; - double fCoef; - double fOffset; - - public: - - Interpolator(double lo, double hi, double v1, double v2) : fRange(lo,hi) +class FAUST_API Interpolator +{ + private: + //-------------------------------------------------------------------------------------- + // Range(lo,hi) clip a value between lo and hi + //-------------------------------------------------------------------------------------- + struct Range { + double fLo; + double fHi; + + Range(double x, double y) + : fLo(std::min(x, y)), fHi(std::max(x, y)) { - if (hi != lo) { - // regular case - fCoef = (v2-v1)/(hi-lo); - fOffset = v1 - lo*fCoef; - } else { - // degenerate case, avoids division by zero - fCoef = 0; - fOffset = (v1+v2)/2; - } } - double operator()(double v) - { - double x = fRange(v); - return fOffset + x*fCoef; - } - - void getLowHigh(double& amin, double& amax) - { - amin = fRange.fLo; - amax = fRange.fHi; + double operator()(double x) { return (x < fLo) ? fLo : (x > fHi) ? fHi : x; } + }; + + Range fRange; + double fCoef; + double fOffset; + + public: + Interpolator(double lo, double hi, double v1, double v2) : fRange(lo, hi) + { + if (hi != lo) { + // regular case + fCoef = (v2 - v1) / (hi - lo); + fOffset = v1 - lo * fCoef; + } else { + // degenerate case, avoids division by zero + fCoef = 0; + fOffset = (v1 + v2) / 2; } + } + double operator()(double v) + { + double x = fRange(v); + return fOffset + x * fCoef; + } + + void getLowHigh(double& amin, double& amax) + { + amin = fRange.fLo; + amax = fRange.fHi; + } }; //-------------------------------------------------------------------------------------- // Interpolator3pt(lo,mi,hi,v1,vm,v2) // Map values between lo mid hi to values between v1 vm v2 //-------------------------------------------------------------------------------------- -class FAUST_API Interpolator3pt { - - private: - - Interpolator fSegment1; - Interpolator fSegment2; - double fMid; - - public: - - Interpolator3pt(double lo, double mi, double hi, double v1, double vm, double v2) : - fSegment1(lo, mi, v1, vm), - fSegment2(mi, hi, vm, v2), - fMid(mi) {} - double operator()(double x) { return (x < fMid) ? fSegment1(x) : fSegment2(x); } - - void getMappingValues(double& amin, double& amid, double& amax) - { - fSegment1.getLowHigh(amin, amid); - fSegment2.getLowHigh(amid, amax); - } +class FAUST_API Interpolator3pt +{ + private: + Interpolator fSegment1; + Interpolator fSegment2; + double fMid; + + public: + Interpolator3pt(double lo, double mi, double hi, double v1, double vm, double v2) + : fSegment1(lo, mi, v1, vm), fSegment2(mi, hi, vm, v2), fMid(mi) + { + } + double operator()(double x) { return (x < fMid) ? fSegment1(x) : fSegment2(x); } + + void getMappingValues(double& amin, double& amid, double& amax) + { + fSegment1.getLowHigh(amin, amid); + fSegment2.getLowHigh(amid, amax); + } }; //-------------------------------------------------------------------------------------- // Abstract ValueConverter class. Converts values between UI and Faust representations //-------------------------------------------------------------------------------------- -class FAUST_API ValueConverter { - - public: - - virtual ~ValueConverter() {} - virtual double ui2faust(double x) { return x; }; - virtual double faust2ui(double x) { return x; }; +class FAUST_API ValueConverter +{ + public: + virtual ~ValueConverter() {} + virtual double ui2faust(double x) { return x; }; + virtual double faust2ui(double x) { return x; }; }; //-------------------------------------------------------------------------------------- // A converter than can be updated //-------------------------------------------------------------------------------------- -class FAUST_API UpdatableValueConverter : public ValueConverter { - - protected: - - bool fActive; - - public: - - UpdatableValueConverter():fActive(true) - {} - virtual ~UpdatableValueConverter() - {} - - virtual void setMappingValues(double amin, double amid, double amax, double min, double init, double max) = 0; - virtual void getMappingValues(double& amin, double& amid, double& amax) = 0; - - void setActive(bool on_off) { fActive = on_off; } - bool getActive() { return fActive; } - +class FAUST_API UpdatableValueConverter : public ValueConverter +{ + protected: + bool fActive; + + public: + UpdatableValueConverter() : fActive(true) {} + virtual ~UpdatableValueConverter() {} + + virtual void setMappingValues(double amin, double amid, double amax, double min, + double init, double max) = 0; + virtual void getMappingValues(double& amin, double& amid, double& amax) = 0; + + void setActive(bool on_off) { fActive = on_off; } + bool getActive() { return fActive; } }; //-------------------------------------------------------------------------------------- // Linear conversion between ui and Faust values //-------------------------------------------------------------------------------------- -class FAUST_API LinearValueConverter : public ValueConverter { - - private: - - Interpolator fUI2F; - Interpolator fF2UI; - - public: - - LinearValueConverter(double umin, double umax, double fmin, double fmax) : - fUI2F(umin,umax,fmin,fmax), fF2UI(fmin,fmax,umin,umax) - {} - - LinearValueConverter() : fUI2F(0.,0.,0.,0.), fF2UI(0.,0.,0.,0.) - {} - virtual double ui2faust(double x) { return fUI2F(x); } - virtual double faust2ui(double x) { return fF2UI(x); } - +class FAUST_API LinearValueConverter : public ValueConverter +{ + private: + Interpolator fUI2F; + Interpolator fF2UI; + + public: + LinearValueConverter(double umin, double umax, double fmin, double fmax) + : fUI2F(umin, umax, fmin, fmax), fF2UI(fmin, fmax, umin, umax) + { + } + + LinearValueConverter() : fUI2F(0., 0., 0., 0.), fF2UI(0., 0., 0., 0.) {} + virtual double ui2faust(double x) { return fUI2F(x); } + virtual double faust2ui(double x) { return fF2UI(x); } }; //-------------------------------------------------------------------------------------- // Two segments linear conversion between ui and Faust values //-------------------------------------------------------------------------------------- -class FAUST_API LinearValueConverter2 : public UpdatableValueConverter { - - private: - - Interpolator3pt fUI2F; - Interpolator3pt fF2UI; - - public: - - LinearValueConverter2(double amin, double amid, double amax, double min, double init, double max) : - fUI2F(amin, amid, amax, min, init, max), fF2UI(min, init, max, amin, amid, amax) - {} - - LinearValueConverter2() : fUI2F(0.,0.,0.,0.,0.,0.), fF2UI(0.,0.,0.,0.,0.,0.) - {} - - virtual double ui2faust(double x) { return fUI2F(x); } - virtual double faust2ui(double x) { return fF2UI(x); } - - virtual void setMappingValues(double amin, double amid, double amax, double min, double init, double max) - { - fUI2F = Interpolator3pt(amin, amid, amax, min, init, max); - fF2UI = Interpolator3pt(min, init, max, amin, amid, amax); - } - - virtual void getMappingValues(double& amin, double& amid, double& amax) - { - fUI2F.getMappingValues(amin, amid, amax); - } - +class FAUST_API LinearValueConverter2 : public UpdatableValueConverter +{ + private: + Interpolator3pt fUI2F; + Interpolator3pt fF2UI; + + public: + LinearValueConverter2(double amin, double amid, double amax, double min, double init, + double max) + : fUI2F(amin, amid, amax, min, init, max), fF2UI(min, init, max, amin, amid, amax) + { + } + + LinearValueConverter2() : fUI2F(0., 0., 0., 0., 0., 0.), fF2UI(0., 0., 0., 0., 0., 0.) + { + } + + virtual double ui2faust(double x) { return fUI2F(x); } + virtual double faust2ui(double x) { return fF2UI(x); } + + virtual void setMappingValues(double amin, double amid, double amax, double min, + double init, double max) + { + fUI2F = Interpolator3pt(amin, amid, amax, min, init, max); + fF2UI = Interpolator3pt(min, init, max, amin, amid, amax); + } + + virtual void getMappingValues(double& amin, double& amid, double& amax) + { + fUI2F.getMappingValues(amin, amid, amax); + } }; //-------------------------------------------------------------------------------------- // Logarithmic conversion between ui and Faust values //-------------------------------------------------------------------------------------- -class FAUST_API LogValueConverter : public LinearValueConverter { - - public: - - LogValueConverter(double umin, double umax, double fmin, double fmax) : - LinearValueConverter(umin, umax, std::log(std::max(DBL_MIN, fmin)), std::log(std::max(DBL_MIN, fmax))) - {} - - virtual double ui2faust(double x) { return std::exp(LinearValueConverter::ui2faust(x)); } - virtual double faust2ui(double x) { return LinearValueConverter::faust2ui(std::log(std::max(x, DBL_MIN))); } - +class FAUST_API LogValueConverter : public LinearValueConverter +{ + public: + LogValueConverter(double umin, double umax, double fmin, double fmax) + : LinearValueConverter(umin, umax, std::log(std::max(DBL_MIN, fmin)), + std::log(std::max(DBL_MIN, fmax))) + { + } + + virtual double ui2faust(double x) + { + return std::exp(LinearValueConverter::ui2faust(x)); + } + virtual double faust2ui(double x) + { + return LinearValueConverter::faust2ui(std::log(std::max(x, DBL_MIN))); + } }; //-------------------------------------------------------------------------------------- // Exponential conversion between ui and Faust values //-------------------------------------------------------------------------------------- -class FAUST_API ExpValueConverter : public LinearValueConverter { - - public: - - ExpValueConverter(double umin, double umax, double fmin, double fmax) : - LinearValueConverter(umin, umax, std::min(DBL_MAX, std::exp(fmin)), std::min(DBL_MAX, std::exp(fmax))) - {} - - virtual double ui2faust(double x) { return std::log(LinearValueConverter::ui2faust(x)); } - virtual double faust2ui(double x) { return LinearValueConverter::faust2ui(std::min(DBL_MAX, std::exp(x))); } - +class FAUST_API ExpValueConverter : public LinearValueConverter +{ + public: + ExpValueConverter(double umin, double umax, double fmin, double fmax) + : LinearValueConverter(umin, umax, std::min(DBL_MAX, std::exp(fmin)), + std::min(DBL_MAX, std::exp(fmax))) + { + } + + virtual double ui2faust(double x) + { + return std::log(LinearValueConverter::ui2faust(x)); + } + virtual double faust2ui(double x) + { + return LinearValueConverter::faust2ui(std::min(DBL_MAX, std::exp(x))); + } }; //-------------------------------------------------------------------------------------- // Convert accelerometer or gyroscope values to Faust values // Using an Up curve (curve 0) //-------------------------------------------------------------------------------------- -class FAUST_API AccUpConverter : public UpdatableValueConverter { - - private: - - Interpolator3pt fA2F; - Interpolator3pt fF2A; - - public: - - AccUpConverter(double amin, double amid, double amax, double fmin, double fmid, double fmax) : - fA2F(amin,amid,amax,fmin,fmid,fmax), - fF2A(fmin,fmid,fmax,amin,amid,amax) - {} - - virtual double ui2faust(double x) { return fA2F(x); } - virtual double faust2ui(double x) { return fF2A(x); } - - virtual void setMappingValues(double amin, double amid, double amax, double fmin, double fmid, double fmax) - { - //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccUpConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax); - fA2F = Interpolator3pt(amin, amid, amax, fmin, fmid, fmax); - fF2A = Interpolator3pt(fmin, fmid, fmax, amin, amid, amax); - } - - virtual void getMappingValues(double& amin, double& amid, double& amax) - { - fA2F.getMappingValues(amin, amid, amax); - } - +class FAUST_API AccUpConverter : public UpdatableValueConverter +{ + private: + Interpolator3pt fA2F; + Interpolator3pt fF2A; + + public: + AccUpConverter(double amin, double amid, double amax, double fmin, double fmid, + double fmax) + : fA2F(amin, amid, amax, fmin, fmid, fmax) + , fF2A(fmin, fmid, fmax, amin, amid, amax) + { + } + + virtual double ui2faust(double x) { return fA2F(x); } + virtual double faust2ui(double x) { return fF2A(x); } + + virtual void setMappingValues(double amin, double amid, double amax, double fmin, + double fmid, double fmax) + { + //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccUpConverter update %f %f %f + //%f %f %f", amin,amid,amax,fmin,fmid,fmax); + fA2F = Interpolator3pt(amin, amid, amax, fmin, fmid, fmax); + fF2A = Interpolator3pt(fmin, fmid, fmax, amin, amid, amax); + } + + virtual void getMappingValues(double& amin, double& amid, double& amax) + { + fA2F.getMappingValues(amin, amid, amax); + } }; //-------------------------------------------------------------------------------------- // Convert accelerometer or gyroscope values to Faust values // Using a Down curve (curve 1) //-------------------------------------------------------------------------------------- -class FAUST_API AccDownConverter : public UpdatableValueConverter { - - private: - - Interpolator3pt fA2F; - Interpolator3pt fF2A; - - public: - - AccDownConverter(double amin, double amid, double amax, double fmin, double fmid, double fmax) : - fA2F(amin,amid,amax,fmax,fmid,fmin), - fF2A(fmin,fmid,fmax,amax,amid,amin) - {} - - virtual double ui2faust(double x) { return fA2F(x); } - virtual double faust2ui(double x) { return fF2A(x); } - - virtual void setMappingValues(double amin, double amid, double amax, double fmin, double fmid, double fmax) - { - //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccDownConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax); - fA2F = Interpolator3pt(amin, amid, amax, fmax, fmid, fmin); - fF2A = Interpolator3pt(fmin, fmid, fmax, amax, amid, amin); - } - - virtual void getMappingValues(double& amin, double& amid, double& amax) - { - fA2F.getMappingValues(amin, amid, amax); - } +class FAUST_API AccDownConverter : public UpdatableValueConverter +{ + private: + Interpolator3pt fA2F; + Interpolator3pt fF2A; + + public: + AccDownConverter(double amin, double amid, double amax, double fmin, double fmid, + double fmax) + : fA2F(amin, amid, amax, fmax, fmid, fmin) + , fF2A(fmin, fmid, fmax, amax, amid, amin) + { + } + + virtual double ui2faust(double x) { return fA2F(x); } + virtual double faust2ui(double x) { return fF2A(x); } + + virtual void setMappingValues(double amin, double amid, double amax, double fmin, + double fmid, double fmax) + { + //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccDownConverter update %f %f + //%f %f %f %f", amin,amid,amax,fmin,fmid,fmax); + fA2F = Interpolator3pt(amin, amid, amax, fmax, fmid, fmin); + fF2A = Interpolator3pt(fmin, fmid, fmax, amax, amid, amin); + } + + virtual void getMappingValues(double& amin, double& amid, double& amax) + { + fA2F.getMappingValues(amin, amid, amax); + } }; //-------------------------------------------------------------------------------------- // Convert accelerometer or gyroscope values to Faust values // Using an Up-Down curve (curve 2) //-------------------------------------------------------------------------------------- -class FAUST_API AccUpDownConverter : public UpdatableValueConverter { - - private: - - Interpolator3pt fA2F; - Interpolator fF2A; - - public: - - AccUpDownConverter(double amin, double amid, double amax, double fmin, double /*fmid*/, double fmax) : - fA2F(amin,amid,amax,fmin,fmax,fmin), - fF2A(fmin,fmax,amin,amax) // Special, pseudo inverse of a non monotonic function - {} - - virtual double ui2faust(double x) { return fA2F(x); } - virtual double faust2ui(double x) { return fF2A(x); } - - virtual void setMappingValues(double amin, double amid, double amax, double fmin, double /*fmid*/, double fmax) - { - //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccUpDownConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax); - fA2F = Interpolator3pt(amin, amid, amax, fmin, fmax, fmin); - fF2A = Interpolator(fmin, fmax, amin, amax); - } - - virtual void getMappingValues(double& amin, double& amid, double& amax) - { - fA2F.getMappingValues(amin, amid, amax); - } +class FAUST_API AccUpDownConverter : public UpdatableValueConverter +{ + private: + Interpolator3pt fA2F; + Interpolator fF2A; + + public: + AccUpDownConverter(double amin, double amid, double amax, double fmin, + double /*fmid*/, double fmax) + : fA2F(amin, amid, amax, fmin, fmax, fmin) + , fF2A(fmin, fmax, amin, + amax) // Special, pseudo inverse of a non monotonic function + { + } + + virtual double ui2faust(double x) { return fA2F(x); } + virtual double faust2ui(double x) { return fF2A(x); } + + virtual void setMappingValues(double amin, double amid, double amax, double fmin, + double /*fmid*/, double fmax) + { + //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccUpDownConverter update %f %f + //%f %f %f %f", amin,amid,amax,fmin,fmid,fmax); + fA2F = Interpolator3pt(amin, amid, amax, fmin, fmax, fmin); + fF2A = Interpolator(fmin, fmax, amin, amax); + } + + virtual void getMappingValues(double& amin, double& amid, double& amax) + { + fA2F.getMappingValues(amin, amid, amax); + } }; //-------------------------------------------------------------------------------------- // Convert accelerometer or gyroscope values to Faust values // Using a Down-Up curve (curve 3) //-------------------------------------------------------------------------------------- -class FAUST_API AccDownUpConverter : public UpdatableValueConverter { - - private: - - Interpolator3pt fA2F; - Interpolator fF2A; - - public: - - AccDownUpConverter(double amin, double amid, double amax, double fmin, double /*fmid*/, double fmax) : - fA2F(amin,amid,amax,fmax,fmin,fmax), - fF2A(fmin,fmax,amin,amax) // Special, pseudo inverse of a non monotonic function - {} - - virtual double ui2faust(double x) { return fA2F(x); } - virtual double faust2ui(double x) { return fF2A(x); } - - virtual void setMappingValues(double amin, double amid, double amax, double fmin, double /*fmid*/, double fmax) - { - //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccDownUpConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax); - fA2F = Interpolator3pt(amin, amid, amax, fmax, fmin, fmax); - fF2A = Interpolator(fmin, fmax, amin, amax); - } - - virtual void getMappingValues(double& amin, double& amid, double& amax) - { - fA2F.getMappingValues(amin, amid, amax); - } +class FAUST_API AccDownUpConverter : public UpdatableValueConverter +{ + private: + Interpolator3pt fA2F; + Interpolator fF2A; + + public: + AccDownUpConverter(double amin, double amid, double amax, double fmin, + double /*fmid*/, double fmax) + : fA2F(amin, amid, amax, fmax, fmin, fmax) + , fF2A(fmin, fmax, amin, + amax) // Special, pseudo inverse of a non monotonic function + { + } + + virtual double ui2faust(double x) { return fA2F(x); } + virtual double faust2ui(double x) { return fF2A(x); } + + virtual void setMappingValues(double amin, double amid, double amax, double fmin, + double /*fmid*/, double fmax) + { + //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccDownUpConverter update %f %f + //%f %f %f %f", amin,amid,amax,fmin,fmid,fmax); + fA2F = Interpolator3pt(amin, amid, amax, fmax, fmin, fmax); + fF2A = Interpolator(fmin, fmax, amin, amax); + } + + virtual void getMappingValues(double& amin, double& amid, double& amax) + { + fA2F.getMappingValues(amin, amid, amax); + } }; //-------------------------------------------------------------------------------------- // Base class for ZoneControl //-------------------------------------------------------------------------------------- -class FAUST_API ZoneControl { - - protected: - - FAUSTFLOAT* fZone; - - public: - - ZoneControl(FAUSTFLOAT* zone) : fZone(zone) {} - virtual ~ZoneControl() {} +class FAUST_API ZoneControl +{ + protected: + FAUSTFLOAT* fZone; - virtual void update(double /*v*/) const {} + public: + ZoneControl(FAUSTFLOAT* zone) : fZone(zone) {} + virtual ~ZoneControl() {} - virtual void setMappingValues(int /*curve*/, double /*amin*/, double /*amid*/, double /*amax*/, double /*min*/, double /*init*/, double /*max*/) {} - virtual void getMappingValues(double& /*amin*/, double& /*amid*/, double& /*amax*/) {} + virtual void update(double /*v*/) const {} - FAUSTFLOAT* getZone() { return fZone; } + virtual void setMappingValues(int /*curve*/, double /*amin*/, double /*amid*/, + double /*amax*/, double /*min*/, double /*init*/, + double /*max*/) + { + } + virtual void getMappingValues(double& /*amin*/, double& /*amid*/, double& /*amax*/) {} - virtual void setActive(bool /*on_off*/) {} - virtual bool getActive() { return false; } + FAUSTFLOAT* getZone() { return fZone; } - virtual int getCurve() { return -1; } + virtual void setActive(bool /*on_off*/) {} + virtual bool getActive() { return false; } + virtual int getCurve() { return -1; } }; //-------------------------------------------------------------------------------------- // Useful to implement accelerometers metadata as a list of ZoneControl for each axes //-------------------------------------------------------------------------------------- -class FAUST_API ConverterZoneControl : public ZoneControl { - - protected: - - ValueConverter* fValueConverter; - - public: - - ConverterZoneControl(FAUSTFLOAT* zone, ValueConverter* converter) : ZoneControl(zone), fValueConverter(converter) {} - virtual ~ConverterZoneControl() { delete fValueConverter; } // Assuming fValueConverter is not kept elsewhere... - - virtual void update(double v) const { *fZone = FAUSTFLOAT(fValueConverter->ui2faust(v)); } - - ValueConverter* getConverter() { return fValueConverter; } - +class FAUST_API ConverterZoneControl : public ZoneControl +{ + protected: + ValueConverter* fValueConverter; + + public: + ConverterZoneControl(FAUSTFLOAT* zone, ValueConverter* converter) + : ZoneControl(zone), fValueConverter(converter) + { + } + virtual ~ConverterZoneControl() + { + delete fValueConverter; + } // Assuming fValueConverter is not kept elsewhere... + + virtual void update(double v) const + { + *fZone = FAUSTFLOAT(fValueConverter->ui2faust(v)); + } + + ValueConverter* getConverter() { return fValueConverter; } }; //-------------------------------------------------------------------------------------- // Association of a zone and a four value converter, each one for each possible curve. // Useful to implement accelerometers metadata as a list of ZoneControl for each axes //-------------------------------------------------------------------------------------- -class FAUST_API CurveZoneControl : public ZoneControl { - - private: - - std::vector fValueConverters; - int fCurve; - - public: - - CurveZoneControl(FAUSTFLOAT* zone, int curve, double amin, double amid, double amax, double min, double init, double max) : ZoneControl(zone), fCurve(0) - { - assert(curve >= 0 && curve <= 3); - fValueConverters.push_back(new AccUpConverter(amin, amid, amax, min, init, max)); - fValueConverters.push_back(new AccDownConverter(amin, amid, amax, min, init, max)); - fValueConverters.push_back(new AccUpDownConverter(amin, amid, amax, min, init, max)); - fValueConverters.push_back(new AccDownUpConverter(amin, amid, amax, min, init, max)); - fCurve = curve; - } - virtual ~CurveZoneControl() - { - for (const auto& it : fValueConverters) { delete it; } - } - void update(double v) const { if (fValueConverters[fCurve]->getActive()) *fZone = FAUSTFLOAT(fValueConverters[fCurve]->ui2faust(v)); } - - void setMappingValues(int curve, double amin, double amid, double amax, double min, double init, double max) - { - fValueConverters[curve]->setMappingValues(amin, amid, amax, min, init, max); - fCurve = curve; - } - - void getMappingValues(double& amin, double& amid, double& amax) - { - fValueConverters[fCurve]->getMappingValues(amin, amid, amax); +class FAUST_API CurveZoneControl : public ZoneControl +{ + private: + std::vector fValueConverters; + int fCurve; + + public: + CurveZoneControl(FAUSTFLOAT* zone, int curve, double amin, double amid, double amax, + double min, double init, double max) + : ZoneControl(zone), fCurve(0) + { + assert(curve >= 0 && curve <= 3); + fValueConverters.push_back(new AccUpConverter(amin, amid, amax, min, init, max)); + fValueConverters.push_back( + new AccDownConverter(amin, amid, amax, min, init, max)); + fValueConverters.push_back( + new AccUpDownConverter(amin, amid, amax, min, init, max)); + fValueConverters.push_back( + new AccDownUpConverter(amin, amid, amax, min, init, max)); + fCurve = curve; + } + virtual ~CurveZoneControl() + { + for (const auto& it : fValueConverters) { + delete it; } - - void setActive(bool on_off) - { - for (const auto& it : fValueConverters) { it->setActive(on_off); } + } + void update(double v) const + { + if (fValueConverters[fCurve]->getActive()) + *fZone = FAUSTFLOAT(fValueConverters[fCurve]->ui2faust(v)); + } + + void setMappingValues(int curve, double amin, double amid, double amax, double min, + double init, double max) + { + fValueConverters[curve]->setMappingValues(amin, amid, amax, min, init, max); + fCurve = curve; + } + + void getMappingValues(double& amin, double& amid, double& amax) + { + fValueConverters[fCurve]->getMappingValues(amin, amid, amax); + } + + void setActive(bool on_off) + { + for (const auto& it : fValueConverters) { + it->setActive(on_off); } + } - int getCurve() { return fCurve; } + int getCurve() { return fCurve; } }; -class FAUST_API ZoneReader { - - private: - - FAUSTFLOAT* fZone; - Interpolator fInterpolator; - - public: - - ZoneReader(FAUSTFLOAT* zone, double lo, double hi) : fZone(zone), fInterpolator(lo, hi, 0, 255) {} +class FAUST_API ZoneReader +{ + private: + FAUSTFLOAT* fZone; + Interpolator fInterpolator; - virtual ~ZoneReader() {} + public: + ZoneReader(FAUSTFLOAT* zone, double lo, double hi) + : fZone(zone), fInterpolator(lo, hi, 0, 255) + { + } - int getValue() - { - return (fZone != nullptr) ? int(fInterpolator(*fZone)) : 127; - } + virtual ~ZoneReader() {} + int getValue() { return (fZone != nullptr) ? int(fInterpolator(*fZone)) : 127; } }; #endif @@ -1280,563 +1332,617 @@ class FAUST_API ZoneReader { typedef unsigned int uint; -class APIUI : public PathBuilder, public Meta, public UI +class APIUI + : public PathBuilder + , public Meta + , public UI { - public: - enum ItemType { kButton = 0, kCheckButton, kVSlider, kHSlider, kNumEntry, kHBargraph, kVBargraph }; - enum Type { kAcc = 0, kGyr = 1, kNoType }; - - protected: - - enum Mapping { kLin = 0, kLog = 1, kExp = 2 }; - - struct Item { - std::string fLabel; - std::string fShortname; - std::string fPath; - ValueConverter* fConversion; - FAUSTFLOAT* fZone; - FAUSTFLOAT fInit; - FAUSTFLOAT fMin; - FAUSTFLOAT fMax; - FAUSTFLOAT fStep; - ItemType fItemType; - - Item(const std::string& label, - const std::string& short_name, - const std::string& path, - ValueConverter* conversion, - FAUSTFLOAT* zone, - FAUSTFLOAT init, - FAUSTFLOAT min, - FAUSTFLOAT max, - FAUSTFLOAT step, - ItemType item_type) - :fLabel(label), fShortname(short_name), fPath(path), fConversion(conversion), - fZone(zone), fInit(init), fMin(min), fMax(max), fStep(step), fItemType(item_type) - {} - }; - std::vector fItems; - - std::vector > fMetaData; - std::vector fAcc[3]; - std::vector fGyr[3]; - - // Screen color control - // "...[screencolor:red]..." etc. - bool fHasScreenControl; // true if control screen color metadata - ZoneReader* fRedReader; - ZoneReader* fGreenReader; - ZoneReader* fBlueReader; - - // Current values controlled by metadata - std::string fCurrentUnit; - int fCurrentScale; - std::string fCurrentAcc; - std::string fCurrentGyr; - std::string fCurrentColor; - std::string fCurrentTooltip; - std::map fCurrentMetadata; - - // Add a generic parameter - virtual void addParameter(const char* label, - FAUSTFLOAT* zone, - FAUSTFLOAT init, - FAUSTFLOAT min, - FAUSTFLOAT max, - FAUSTFLOAT step, - ItemType type) + public: + enum ItemType { + kButton = 0, + kCheckButton, + kVSlider, + kHSlider, + kNumEntry, + kHBargraph, + kVBargraph + }; + enum Type { kAcc = 0, kGyr = 1, kNoType }; + + protected: + enum Mapping { kLin = 0, kLog = 1, kExp = 2 }; + + struct Item { + std::string fLabel; + std::string fShortname; + std::string fPath; + ValueConverter* fConversion; + FAUSTFLOAT* fZone; + FAUSTFLOAT fInit; + FAUSTFLOAT fMin; + FAUSTFLOAT fMax; + FAUSTFLOAT fStep; + ItemType fItemType; + + Item(const std::string& label, const std::string& short_name, + const std::string& path, ValueConverter* conversion, FAUSTFLOAT* zone, + FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step, + ItemType item_type) + : fLabel(label) + , fShortname(short_name) + , fPath(path) + , fConversion(conversion) + , fZone(zone) + , fInit(init) + , fMin(min) + , fMax(max) + , fStep(step) + , fItemType(item_type) { - std::string path = buildPath(label); - fFullPaths.push_back(path); - - // handle scale metadata - ValueConverter* converter = nullptr; - switch (fCurrentScale) { - case kLin: - converter = new LinearValueConverter(0, 1, min, max); - break; - case kLog: - converter = new LogValueConverter(0, 1, min, max); - break; - case kExp: - converter = new ExpValueConverter(0, 1, min, max); - break; - } - fCurrentScale = kLin; - - fItems.push_back(Item(label, "", path, converter, zone, init, min, max, step, type)); - - if (fCurrentAcc.size() > 0 && fCurrentGyr.size() > 0) { - fprintf(stderr, "warning : 'acc' and 'gyr' metadata used for the same %s parameter !!\n", label); - } - - // handle acc metadata "...[acc : ]..." - if (fCurrentAcc.size() > 0) { - std::istringstream iss(fCurrentAcc); - int axe, curve; - double amin, amid, amax; - iss >> axe >> curve >> amin >> amid >> amax; - - if ((0 <= axe) && (axe < 3) && - (0 <= curve) && (curve < 4) && - (amin < amax) && (amin <= amid) && (amid <= amax)) - { - fAcc[axe].push_back(new CurveZoneControl(zone, curve, amin, amid, amax, min, init, max)); - } else { - fprintf(stderr, "incorrect acc metadata : %s \n", fCurrentAcc.c_str()); - } - fCurrentAcc = ""; - } - - // handle gyr metadata "...[gyr : ]..." - if (fCurrentGyr.size() > 0) { - std::istringstream iss(fCurrentGyr); - int axe, curve; - double amin, amid, amax; - iss >> axe >> curve >> amin >> amid >> amax; - - if ((0 <= axe) && (axe < 3) && - (0 <= curve) && (curve < 4) && - (amin < amax) && (amin <= amid) && (amid <= amax)) - { - fGyr[axe].push_back(new CurveZoneControl(zone, curve, amin, amid, amax, min, init, max)); - } else { - fprintf(stderr, "incorrect gyr metadata : %s \n", fCurrentGyr.c_str()); - } - fCurrentGyr = ""; - } - - // handle screencolor metadata "...[screencolor:red|green|blue|white]..." - if (fCurrentColor.size() > 0) { - if ((fCurrentColor == "red") && (fRedReader == nullptr)) { - fRedReader = new ZoneReader(zone, min, max); - fHasScreenControl = true; - } else if ((fCurrentColor == "green") && (fGreenReader == nullptr)) { - fGreenReader = new ZoneReader(zone, min, max); - fHasScreenControl = true; - } else if ((fCurrentColor == "blue") && (fBlueReader == nullptr)) { - fBlueReader = new ZoneReader(zone, min, max); - fHasScreenControl = true; - } else if ((fCurrentColor == "white") && (fRedReader == nullptr) && (fGreenReader == nullptr) && (fBlueReader == nullptr)) { - fRedReader = new ZoneReader(zone, min, max); - fGreenReader = new ZoneReader(zone, min, max); - fBlueReader = new ZoneReader(zone, min, max); - fHasScreenControl = true; - } else { - fprintf(stderr, "incorrect screencolor metadata : %s \n", fCurrentColor.c_str()); - } - } - fCurrentColor = ""; - - fMetaData.push_back(fCurrentMetadata); - fCurrentMetadata.clear(); } - - int getZoneIndex(std::vector* table, int p, int val) - { - FAUSTFLOAT* zone = fItems[uint(p)].fZone; - for (size_t i = 0; i < table[val].size(); i++) { - if (zone == table[val][i]->getZone()) return int(i); - } - return -1; + }; + std::vector fItems; + + std::vector > fMetaData; + std::vector fAcc[3]; + std::vector fGyr[3]; + + // Screen color control + // "...[screencolor:red]..." etc. + bool fHasScreenControl; // true if control screen color metadata + ZoneReader* fRedReader; + ZoneReader* fGreenReader; + ZoneReader* fBlueReader; + + // Current values controlled by metadata + std::string fCurrentUnit; + int fCurrentScale; + std::string fCurrentAcc; + std::string fCurrentGyr; + std::string fCurrentColor; + std::string fCurrentTooltip; + std::map fCurrentMetadata; + + // Add a generic parameter + virtual void addParameter(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, + FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step, + ItemType type) + { + std::string path = buildPath(label); + fFullPaths.push_back(path); + + // handle scale metadata + ValueConverter* converter = nullptr; + switch (fCurrentScale) { + case kLin: + converter = new LinearValueConverter(0, 1, min, max); + break; + case kLog: + converter = new LogValueConverter(0, 1, min, max); + break; + case kExp: + converter = new ExpValueConverter(0, 1, min, max); + break; } + fCurrentScale = kLin; - void setConverter(std::vector* table, int p, int val, int curve, double amin, double amid, double amax) - { - int id1 = getZoneIndex(table, p, 0); - int id2 = getZoneIndex(table, p, 1); - int id3 = getZoneIndex(table, p, 2); + fItems.push_back( + Item(label, "", path, converter, zone, init, min, max, step, type)); - // Deactivates everywhere.. - if (id1 != -1) table[0][uint(id1)]->setActive(false); - if (id2 != -1) table[1][uint(id2)]->setActive(false); - if (id3 != -1) table[2][uint(id3)]->setActive(false); - - if (val == -1) { // Means: no more mapping... - // So stay all deactivated... - } else { - int id4 = getZoneIndex(table, p, val); - if (id4 != -1) { - // Reactivate the one we edit... - table[val][uint(id4)]->setMappingValues(curve, amin, amid, amax, fItems[uint(p)].fMin, fItems[uint(p)].fInit, fItems[uint(p)].fMax); - table[val][uint(id4)]->setActive(true); - } else { - // Allocate a new CurveZoneControl which is 'active' by default - FAUSTFLOAT* zone = fItems[uint(p)].fZone; - table[val].push_back(new CurveZoneControl(zone, curve, amin, amid, amax, fItems[uint(p)].fMin, fItems[uint(p)].fInit, fItems[uint(p)].fMax)); - } - } + if (fCurrentAcc.size() > 0 && fCurrentGyr.size() > 0) { + fprintf( + stderr, + "warning : 'acc' and 'gyr' metadata used for the same %s parameter !!\n", + label); } - void getConverter(std::vector* table, int p, int& val, int& curve, double& amin, double& amid, double& amax) - { - int id1 = getZoneIndex(table, p, 0); - int id2 = getZoneIndex(table, p, 1); - int id3 = getZoneIndex(table, p, 2); - - if (id1 != -1) { - val = 0; - curve = table[val][uint(id1)]->getCurve(); - table[val][uint(id1)]->getMappingValues(amin, amid, amax); - } else if (id2 != -1) { - val = 1; - curve = table[val][uint(id2)]->getCurve(); - table[val][uint(id2)]->getMappingValues(amin, amid, amax); - } else if (id3 != -1) { - val = 2; - curve = table[val][uint(id3)]->getCurve(); - table[val][uint(id3)]->getMappingValues(amin, amid, amax); + // handle acc metadata "...[acc : ]..." + if (fCurrentAcc.size() > 0) { + std::istringstream iss(fCurrentAcc); + int axe, curve; + double amin, amid, amax; + iss >> axe >> curve >> amin >> amid >> amax; + + if ((0 <= axe) && (axe < 3) && (0 <= curve) && (curve < 4) && (amin < amax) + && (amin <= amid) && (amid <= amax)) { + fAcc[axe].push_back( + new CurveZoneControl(zone, curve, amin, amid, amax, min, init, max)); } else { - val = -1; // No mapping - curve = 0; - amin = -100.; - amid = 0.; - amax = 100.; + fprintf(stderr, "incorrect acc metadata : %s \n", fCurrentAcc.c_str()); } + fCurrentAcc = ""; } - public: - - APIUI() : fHasScreenControl(false), fRedReader(nullptr), fGreenReader(nullptr), fBlueReader(nullptr), fCurrentScale(kLin) - {} - - virtual ~APIUI() - { - for (const auto& it : fItems) delete it.fConversion; - for (int i = 0; i < 3; i++) { - for (const auto& it : fAcc[i]) delete it; - for (const auto& it : fGyr[i]) delete it; + // handle gyr metadata "...[gyr : ]..." + if (fCurrentGyr.size() > 0) { + std::istringstream iss(fCurrentGyr); + int axe, curve; + double amin, amid, amax; + iss >> axe >> curve >> amin >> amid >> amax; + + if ((0 <= axe) && (axe < 3) && (0 <= curve) && (curve < 4) && (amin < amax) + && (amin <= amid) && (amid <= amax)) { + fGyr[axe].push_back( + new CurveZoneControl(zone, curve, amin, amid, amax, min, init, max)); + } else { + fprintf(stderr, "incorrect gyr metadata : %s \n", fCurrentGyr.c_str()); } - delete fRedReader; - delete fGreenReader; - delete fBlueReader; + fCurrentGyr = ""; } - // -- widget's layouts - - virtual void openTabBox(const char* label) { pushLabel(label); } - virtual void openHorizontalBox(const char* label) { pushLabel(label); } - virtual void openVerticalBox(const char* label) { pushLabel(label); } - virtual void closeBox() - { - if (popLabel()) { - // Shortnames can be computed when all fullnames are known - computeShortNames(); - // Fill 'shortname' field for each item - for (const auto& it : fFull2Short) { - int index = getParamIndex(it.first.c_str()); - fItems[index].fShortname = it.second; - } + // handle screencolor metadata "...[screencolor:red|green|blue|white]..." + if (fCurrentColor.size() > 0) { + if ((fCurrentColor == "red") && (fRedReader == nullptr)) { + fRedReader = new ZoneReader(zone, min, max); + fHasScreenControl = true; + } else if ((fCurrentColor == "green") && (fGreenReader == nullptr)) { + fGreenReader = new ZoneReader(zone, min, max); + fHasScreenControl = true; + } else if ((fCurrentColor == "blue") && (fBlueReader == nullptr)) { + fBlueReader = new ZoneReader(zone, min, max); + fHasScreenControl = true; + } else if ((fCurrentColor == "white") && (fRedReader == nullptr) + && (fGreenReader == nullptr) && (fBlueReader == nullptr)) { + fRedReader = new ZoneReader(zone, min, max); + fGreenReader = new ZoneReader(zone, min, max); + fBlueReader = new ZoneReader(zone, min, max); + fHasScreenControl = true; + } else { + fprintf(stderr, "incorrect screencolor metadata : %s \n", + fCurrentColor.c_str()); } } - - // -- active widgets - - virtual void addButton(const char* label, FAUSTFLOAT* zone) - { - addParameter(label, zone, 0, 0, 1, 1, kButton); - } - - virtual void addCheckButton(const char* label, FAUSTFLOAT* zone) - { - addParameter(label, zone, 0, 0, 1, 1, kCheckButton); + fCurrentColor = ""; + + fMetaData.push_back(fCurrentMetadata); + fCurrentMetadata.clear(); + } + + int getZoneIndex(std::vector* table, int p, int val) + { + FAUSTFLOAT* zone = fItems[uint(p)].fZone; + for (size_t i = 0; i < table[val].size(); i++) { + if (zone == table[val][i]->getZone()) + return int(i); } - - virtual void addVerticalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) - { - addParameter(label, zone, init, min, max, step, kVSlider); + return -1; + } + + void setConverter(std::vector* table, int p, int val, int curve, + double amin, double amid, double amax) + { + int id1 = getZoneIndex(table, p, 0); + int id2 = getZoneIndex(table, p, 1); + int id3 = getZoneIndex(table, p, 2); + + // Deactivates everywhere.. + if (id1 != -1) + table[0][uint(id1)]->setActive(false); + if (id2 != -1) + table[1][uint(id2)]->setActive(false); + if (id3 != -1) + table[2][uint(id3)]->setActive(false); + + if (val == -1) { // Means: no more mapping... + // So stay all deactivated... + } else { + int id4 = getZoneIndex(table, p, val); + if (id4 != -1) { + // Reactivate the one we edit... + table[val][uint(id4)]->setMappingValues( + curve, amin, amid, amax, fItems[uint(p)].fMin, fItems[uint(p)].fInit, + fItems[uint(p)].fMax); + table[val][uint(id4)]->setActive(true); + } else { + // Allocate a new CurveZoneControl which is 'active' by default + FAUSTFLOAT* zone = fItems[uint(p)].fZone; + table[val].push_back(new CurveZoneControl( + zone, curve, amin, amid, amax, fItems[uint(p)].fMin, + fItems[uint(p)].fInit, fItems[uint(p)].fMax)); + } } - - virtual void addHorizontalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) - { - addParameter(label, zone, init, min, max, step, kHSlider); + } + + void getConverter(std::vector* table, int p, int& val, int& curve, + double& amin, double& amid, double& amax) + { + int id1 = getZoneIndex(table, p, 0); + int id2 = getZoneIndex(table, p, 1); + int id3 = getZoneIndex(table, p, 2); + + if (id1 != -1) { + val = 0; + curve = table[val][uint(id1)]->getCurve(); + table[val][uint(id1)]->getMappingValues(amin, amid, amax); + } else if (id2 != -1) { + val = 1; + curve = table[val][uint(id2)]->getCurve(); + table[val][uint(id2)]->getMappingValues(amin, amid, amax); + } else if (id3 != -1) { + val = 2; + curve = table[val][uint(id3)]->getCurve(); + table[val][uint(id3)]->getMappingValues(amin, amid, amax); + } else { + val = -1; // No mapping + curve = 0; + amin = -100.; + amid = 0.; + amax = 100.; } - - virtual void addNumEntry(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) - { - addParameter(label, zone, init, min, max, step, kNumEntry); + } + + public: + APIUI() + : fHasScreenControl(false) + , fRedReader(nullptr) + , fGreenReader(nullptr) + , fBlueReader(nullptr) + , fCurrentScale(kLin) + { + } + + virtual ~APIUI() + { + for (const auto& it : fItems) + delete it.fConversion; + for (int i = 0; i < 3; i++) { + for (const auto& it : fAcc[i]) + delete it; + for (const auto& it : fGyr[i]) + delete it; } + delete fRedReader; + delete fGreenReader; + delete fBlueReader; + } - // -- passive widgets - - virtual void addHorizontalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT min, FAUSTFLOAT max) - { - addParameter(label, zone, min, min, max, (max-min)/1000.0f, kHBargraph); - } + // -- widget's layouts - virtual void addVerticalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT min, FAUSTFLOAT max) - { - addParameter(label, zone, min, min, max, (max-min)/1000.0f, kVBargraph); + virtual void openTabBox(const char* label) { pushLabel(label); } + virtual void openHorizontalBox(const char* label) { pushLabel(label); } + virtual void openVerticalBox(const char* label) { pushLabel(label); } + virtual void closeBox() + { + if (popLabel()) { + // Shortnames can be computed when all fullnames are known + computeShortNames(); + // Fill 'shortname' field for each item + for (const auto& it : fFull2Short) { + int index = getParamIndex(it.first.c_str()); + fItems[index].fShortname = it.second; + } } + } - // -- soundfiles + // -- active widgets - virtual void addSoundfile(const char* /*label*/, const char* /*filename*/, Soundfile** /*sf_zone*/) {} + virtual void addButton(const char* label, FAUSTFLOAT* zone) + { + addParameter(label, zone, 0, 0, 1, 1, kButton); + } + + virtual void addCheckButton(const char* label, FAUSTFLOAT* zone) + { + addParameter(label, zone, 0, 0, 1, 1, kCheckButton); + } + + virtual void addVerticalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, + FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) + { + addParameter(label, zone, init, min, max, step, kVSlider); + } + + virtual void addHorizontalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, + FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) + { + addParameter(label, zone, init, min, max, step, kHSlider); + } + + virtual void addNumEntry(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, + FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) + { + addParameter(label, zone, init, min, max, step, kNumEntry); + } - // -- metadata declarations + // -- passive widgets - virtual void declare(FAUSTFLOAT* /*zone*/, const char* key, const char* val) - { - // Keep metadata - fCurrentMetadata[key] = val; - - if (strcmp(key, "scale") == 0) { - if (strcmp(val, "log") == 0) { - fCurrentScale = kLog; - } else if (strcmp(val, "exp") == 0) { - fCurrentScale = kExp; - } else { - fCurrentScale = kLin; - } - } else if (strcmp(key, "unit") == 0) { - fCurrentUnit = val; - } else if (strcmp(key, "acc") == 0) { - fCurrentAcc = val; - } else if (strcmp(key, "gyr") == 0) { - fCurrentGyr = val; - } else if (strcmp(key, "screencolor") == 0) { - fCurrentColor = val; // val = "red", "green", "blue" or "white" - } else if (strcmp(key, "tooltip") == 0) { - fCurrentTooltip = val; - } - } + virtual void addHorizontalBargraph(const char* label, FAUSTFLOAT* zone, + FAUSTFLOAT min, FAUSTFLOAT max) + { + addParameter(label, zone, min, min, max, (max - min) / 1000.0f, kHBargraph); + } - virtual void declare(const char* /*key*/, const char* /*val*/) - {} + virtual void addVerticalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT min, + FAUSTFLOAT max) + { + addParameter(label, zone, min, min, max, (max - min) / 1000.0f, kVBargraph); + } - //------------------------------------------------------------------------------- - // Simple API part - //------------------------------------------------------------------------------- - int getParamsCount() { return int(fItems.size()); } + // -- soundfiles - int getParamIndex(const char* path_aux) - { - std::string path = std::string(path_aux); - auto it = find_if(fItems.begin(), fItems.end(), - [=](const Item& it) { return (it.fLabel == path) || (it.fShortname == path) || (it.fPath == path); }); - return (it != fItems.end()) ? int(it - fItems.begin()) : -1; - } - - const char* getParamLabel(int p) { return fItems[uint(p)].fLabel.c_str(); } - const char* getParamShortname(int p) { return fItems[uint(p)].fShortname.c_str(); } - const char* getParamAddress(int p) { return fItems[uint(p)].fPath.c_str(); } - - std::map getMetadata(int p) - { - std::map res; - std::map metadata = fMetaData[uint(p)]; - for (const auto& it : metadata) { - res[it.first.c_str()] = it.second.c_str(); - } - return res; - } + virtual void addSoundfile(const char* /*label*/, const char* /*filename*/, + Soundfile** /*sf_zone*/) + { + } - const char* getMetadata(int p, const char* key) - { - return (fMetaData[uint(p)].find(key) != fMetaData[uint(p)].end()) ? fMetaData[uint(p)][key].c_str() : ""; - } - FAUSTFLOAT getParamMin(int p) { return fItems[uint(p)].fMin; } - FAUSTFLOAT getParamMax(int p) { return fItems[uint(p)].fMax; } - FAUSTFLOAT getParamStep(int p) { return fItems[uint(p)].fStep; } - FAUSTFLOAT getParamInit(int p) { return fItems[uint(p)].fInit; } + // -- metadata declarations - FAUSTFLOAT* getParamZone(int p) { return fItems[uint(p)].fZone; } + virtual void declare(FAUSTFLOAT* /*zone*/, const char* key, const char* val) + { + // Keep metadata + fCurrentMetadata[key] = val; - FAUSTFLOAT getParamValue(int p) { return *fItems[uint(p)].fZone; } - FAUSTFLOAT getParamValue(const char* path) - { - int index = getParamIndex(path); - if (index >= 0) { - return getParamValue(index); + if (strcmp(key, "scale") == 0) { + if (strcmp(val, "log") == 0) { + fCurrentScale = kLog; + } else if (strcmp(val, "exp") == 0) { + fCurrentScale = kExp; } else { - fprintf(stderr, "getParamValue : '%s' not found\n", (path == nullptr ? "NULL" : path)); - return FAUSTFLOAT(0); + fCurrentScale = kLin; } + } else if (strcmp(key, "unit") == 0) { + fCurrentUnit = val; + } else if (strcmp(key, "acc") == 0) { + fCurrentAcc = val; + } else if (strcmp(key, "gyr") == 0) { + fCurrentGyr = val; + } else if (strcmp(key, "screencolor") == 0) { + fCurrentColor = val; // val = "red", "green", "blue" or "white" + } else if (strcmp(key, "tooltip") == 0) { + fCurrentTooltip = val; } - - void setParamValue(int p, FAUSTFLOAT v) { *fItems[uint(p)].fZone = v; } - void setParamValue(const char* path, FAUSTFLOAT v) - { - int index = getParamIndex(path); - if (index >= 0) { - setParamValue(index, v); - } else { - fprintf(stderr, "setParamValue : '%s' not found\n", (path == nullptr ? "NULL" : path)); - } + } + + virtual void declare(const char* /*key*/, const char* /*val*/) {} + + //------------------------------------------------------------------------------- + // Simple API part + //------------------------------------------------------------------------------- + int getParamsCount() { return int(fItems.size()); } + + int getParamIndex(const char* path_aux) + { + std::string path = std::string(path_aux); + auto it = find_if(fItems.begin(), fItems.end(), [=](const Item& it) { + return (it.fLabel == path) || (it.fShortname == path) || (it.fPath == path); + }); + return (it != fItems.end()) ? int(it - fItems.begin()) : -1; + } + + const char* getParamLabel(int p) { return fItems[uint(p)].fLabel.c_str(); } + const char* getParamShortname(int p) { return fItems[uint(p)].fShortname.c_str(); } + const char* getParamAddress(int p) { return fItems[uint(p)].fPath.c_str(); } + + std::map getMetadata(int p) + { + std::map res; + std::map metadata = fMetaData[uint(p)]; + for (const auto& it : metadata) { + res[it.first.c_str()] = it.second.c_str(); } - - double getParamRatio(int p) { return fItems[uint(p)].fConversion->faust2ui(*fItems[uint(p)].fZone); } - void setParamRatio(int p, double r) { *fItems[uint(p)].fZone = FAUSTFLOAT(fItems[uint(p)].fConversion->ui2faust(r)); } - - double value2ratio(int p, double r) { return fItems[uint(p)].fConversion->faust2ui(r); } - double ratio2value(int p, double r) { return fItems[uint(p)].fConversion->ui2faust(r); } - - /** - * Return the control type (kAcc, kGyr, or -1) for a given parameter. - * - * @param p - the UI parameter index - * - * @return the type - */ - Type getParamType(int p) - { - if (p >= 0) { - if (getZoneIndex(fAcc, p, 0) != -1 - || getZoneIndex(fAcc, p, 1) != -1 - || getZoneIndex(fAcc, p, 2) != -1) { - return kAcc; - } else if (getZoneIndex(fGyr, p, 0) != -1 - || getZoneIndex(fGyr, p, 1) != -1 - || getZoneIndex(fGyr, p, 2) != -1) { - return kGyr; - } - } - return kNoType; + return res; + } + + const char* getMetadata(int p, const char* key) + { + return (fMetaData[uint(p)].find(key) != fMetaData[uint(p)].end()) + ? fMetaData[uint(p)][key].c_str() + : ""; + } + FAUSTFLOAT getParamMin(int p) { return fItems[uint(p)].fMin; } + FAUSTFLOAT getParamMax(int p) { return fItems[uint(p)].fMax; } + FAUSTFLOAT getParamStep(int p) { return fItems[uint(p)].fStep; } + FAUSTFLOAT getParamInit(int p) { return fItems[uint(p)].fInit; } + + FAUSTFLOAT* getParamZone(int p) { return fItems[uint(p)].fZone; } + + FAUSTFLOAT getParamValue(int p) { return *fItems[uint(p)].fZone; } + FAUSTFLOAT getParamValue(const char* path) + { + int index = getParamIndex(path); + if (index >= 0) { + return getParamValue(index); + } else { + fprintf(stderr, "getParamValue : '%s' not found\n", + (path == nullptr ? "NULL" : path)); + return FAUSTFLOAT(0); } - - /** - * Return the Item type (kButton = 0, kCheckButton, kVSlider, kHSlider, kNumEntry, kHBargraph, kVBargraph) for a given parameter. - * - * @param p - the UI parameter index - * - * @return the Item type - */ - ItemType getParamItemType(int p) - { - return fItems[uint(p)].fItemType; + } + + void setParamValue(int p, FAUSTFLOAT v) { *fItems[uint(p)].fZone = v; } + void setParamValue(const char* path, FAUSTFLOAT v) + { + int index = getParamIndex(path); + if (index >= 0) { + setParamValue(index, v); + } else { + fprintf(stderr, "setParamValue : '%s' not found\n", + (path == nullptr ? "NULL" : path)); } + } + + double getParamRatio(int p) + { + return fItems[uint(p)].fConversion->faust2ui(*fItems[uint(p)].fZone); + } + void setParamRatio(int p, double r) + { + *fItems[uint(p)].fZone = FAUSTFLOAT(fItems[uint(p)].fConversion->ui2faust(r)); + } + + double value2ratio(int p, double r) + { + return fItems[uint(p)].fConversion->faust2ui(r); + } + double ratio2value(int p, double r) + { + return fItems[uint(p)].fConversion->ui2faust(r); + } - /** - * Set a new value coming from an accelerometer, propagate it to all relevant FAUSTFLOAT* zones. - * - * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer - * @param value - the new value - * - */ - void propagateAcc(int acc, double value) - { - for (size_t i = 0; i < fAcc[acc].size(); i++) { - fAcc[acc][i]->update(value); + /** + * Return the control type (kAcc, kGyr, or -1) for a given parameter. + * + * @param p - the UI parameter index + * + * @return the type + */ + Type getParamType(int p) + { + if (p >= 0) { + if (getZoneIndex(fAcc, p, 0) != -1 || getZoneIndex(fAcc, p, 1) != -1 + || getZoneIndex(fAcc, p, 2) != -1) { + return kAcc; + } else if (getZoneIndex(fGyr, p, 0) != -1 || getZoneIndex(fGyr, p, 1) != -1 + || getZoneIndex(fGyr, p, 2) != -1) { + return kGyr; } } + return kNoType; + } - /** - * Used to edit accelerometer curves and mapping. Set curve and related mapping for a given UI parameter. - * - * @param p - the UI parameter index - * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer (-1 means "no mapping") - * @param curve - between 0 and 3 - * @param amin - mapping 'min' point - * @param amid - mapping 'middle' point - * @param amax - mapping 'max' point - * - */ - void setAccConverter(int p, int acc, int curve, double amin, double amid, double amax) - { - setConverter(fAcc, p, acc, curve, amin, amid, amax); - } + /** + * Return the Item type (kButton = 0, kCheckButton, kVSlider, kHSlider, kNumEntry, + * kHBargraph, kVBargraph) for a given parameter. + * + * @param p - the UI parameter index + * + * @return the Item type + */ + ItemType getParamItemType(int p) { return fItems[uint(p)].fItemType; } - /** - * Used to edit gyroscope curves and mapping. Set curve and related mapping for a given UI parameter. - * - * @param p - the UI parameter index - * @param gyr - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope (-1 means "no mapping") - * @param curve - between 0 and 3 - * @param amin - mapping 'min' point - * @param amid - mapping 'middle' point - * @param amax - mapping 'max' point - * - */ - void setGyrConverter(int p, int gyr, int curve, double amin, double amid, double amax) - { - setConverter(fGyr, p, gyr, curve, amin, amid, amax); + /** + * Set a new value coming from an accelerometer, propagate it to all relevant + * FAUSTFLOAT* zones. + * + * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer + * @param value - the new value + * + */ + void propagateAcc(int acc, double value) + { + for (size_t i = 0; i < fAcc[acc].size(); i++) { + fAcc[acc][i]->update(value); } + } - /** - * Used to edit accelerometer curves and mapping. Get curve and related mapping for a given UI parameter. - * - * @param p - the UI parameter index - * @param acc - the acc value to be retrieved (-1 means "no mapping") - * @param curve - the curve value to be retrieved - * @param amin - the amin value to be retrieved - * @param amid - the amid value to be retrieved - * @param amax - the amax value to be retrieved - * - */ - void getAccConverter(int p, int& acc, int& curve, double& amin, double& amid, double& amax) - { - getConverter(fAcc, p, acc, curve, amin, amid, amax); - } + /** + * Used to edit accelerometer curves and mapping. Set curve and related mapping for a + * given UI parameter. + * + * @param p - the UI parameter index + * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer + * (-1 means "no mapping") + * @param curve - between 0 and 3 + * @param amin - mapping 'min' point + * @param amid - mapping 'middle' point + * @param amax - mapping 'max' point + * + */ + void setAccConverter(int p, int acc, int curve, double amin, double amid, double amax) + { + setConverter(fAcc, p, acc, curve, amin, amid, amax); + } - /** - * Used to edit gyroscope curves and mapping. Get curve and related mapping for a given UI parameter. - * - * @param p - the UI parameter index - * @param gyr - the gyr value to be retrieved (-1 means "no mapping") - * @param curve - the curve value to be retrieved - * @param amin - the amin value to be retrieved - * @param amid - the amid value to be retrieved - * @param amax - the amax value to be retrieved - * - */ - void getGyrConverter(int p, int& gyr, int& curve, double& amin, double& amid, double& amax) - { - getConverter(fGyr, p, gyr, curve, amin, amid, amax); - } + /** + * Used to edit gyroscope curves and mapping. Set curve and related mapping for a + * given UI parameter. + * + * @param p - the UI parameter index + * @param gyr - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope (-1 means "no + * mapping") + * @param curve - between 0 and 3 + * @param amin - mapping 'min' point + * @param amid - mapping 'middle' point + * @param amax - mapping 'max' point + * + */ + void setGyrConverter(int p, int gyr, int curve, double amin, double amid, double amax) + { + setConverter(fGyr, p, gyr, curve, amin, amid, amax); + } - /** - * Set a new value coming from an gyroscope, propagate it to all relevant FAUSTFLOAT* zones. - * - * @param gyr - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope - * @param value - the new value - * - */ - void propagateGyr(int gyr, double value) - { - for (size_t i = 0; i < fGyr[gyr].size(); i++) { - fGyr[gyr][i]->update(value); - } - } + /** + * Used to edit accelerometer curves and mapping. Get curve and related mapping for a + * given UI parameter. + * + * @param p - the UI parameter index + * @param acc - the acc value to be retrieved (-1 means "no mapping") + * @param curve - the curve value to be retrieved + * @param amin - the amin value to be retrieved + * @param amid - the amid value to be retrieved + * @param amax - the amax value to be retrieved + * + */ + void getAccConverter(int p, int& acc, int& curve, double& amin, double& amid, + double& amax) + { + getConverter(fAcc, p, acc, curve, amin, amid, amax); + } - /** - * Get the number of FAUSTFLOAT* zones controlled with the accelerometer. - * - * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer - * @return the number of zones - * - */ - int getAccCount(int acc) - { - return (acc >= 0 && acc < 3) ? int(fAcc[acc].size()) : 0; - } + /** + * Used to edit gyroscope curves and mapping. Get curve and related mapping for a + * given UI parameter. + * + * @param p - the UI parameter index + * @param gyr - the gyr value to be retrieved (-1 means "no mapping") + * @param curve - the curve value to be retrieved + * @param amin - the amin value to be retrieved + * @param amid - the amid value to be retrieved + * @param amax - the amax value to be retrieved + * + */ + void getGyrConverter(int p, int& gyr, int& curve, double& amin, double& amid, + double& amax) + { + getConverter(fGyr, p, gyr, curve, amin, amid, amax); + } - /** - * Get the number of FAUSTFLOAT* zones controlled with the gyroscope. - * - * @param gyr - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope - * @param the number of zones - * - */ - int getGyrCount(int gyr) - { - return (gyr >= 0 && gyr < 3) ? int(fGyr[gyr].size()) : 0; + /** + * Set a new value coming from an gyroscope, propagate it to all relevant FAUSTFLOAT* + * zones. + * + * @param gyr - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope + * @param value - the new value + * + */ + void propagateGyr(int gyr, double value) + { + for (size_t i = 0; i < fGyr[gyr].size(); i++) { + fGyr[gyr][i]->update(value); } + } - // getScreenColor() : -1 means no screen color control (no screencolor metadata found) - // otherwise return 0x00RRGGBB a ready to use color - int getScreenColor() - { - if (fHasScreenControl) { - int r = (fRedReader) ? fRedReader->getValue() : 0; - int g = (fGreenReader) ? fGreenReader->getValue() : 0; - int b = (fBlueReader) ? fBlueReader->getValue() : 0; - return (r<<16) | (g<<8) | b; - } else { - return -1; - } - } + /** + * Get the number of FAUSTFLOAT* zones controlled with the accelerometer. + * + * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer + * @return the number of zones + * + */ + int getAccCount(int acc) { return (acc >= 0 && acc < 3) ? int(fAcc[acc].size()) : 0; } + /** + * Get the number of FAUSTFLOAT* zones controlled with the gyroscope. + * + * @param gyr - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope + * @param the number of zones + * + */ + int getGyrCount(int gyr) { return (gyr >= 0 && gyr < 3) ? int(fGyr[gyr].size()) : 0; } + + // getScreenColor() : -1 means no screen color control (no screencolor metadata found) + // otherwise return 0x00RRGGBB a ready to use color + int getScreenColor() + { + if (fHasScreenControl) { + int r = (fRedReader) ? fRedReader->getValue() : 0; + int g = (fGreenReader) ? fGreenReader->getValue() : 0; + int b = (fBlueReader) ? fBlueReader->getValue() : 0; + return (r << 16) | (g << 8) | b; + } else { + return -1; + } + } }; #endif @@ -1849,23 +1955,23 @@ class APIUI : public PathBuilder, public Meta, public UI // FAUST Generated Code //---------------------------------------------------------------------------- - #ifndef FAUSTFLOAT #define FAUSTFLOAT float -#endif +#endif + +#include #include #include #include -#include -#ifndef FAUSTCLASS +#ifndef FAUSTCLASS #define FAUSTCLASS volumedsp #endif -#ifdef __APPLE__ +#ifdef __APPLE__ #define exp10f __exp10f -#define exp10 __exp10 +#define exp10 __exp10 #endif #if defined(_WIN32) @@ -1874,113 +1980,113 @@ class APIUI : public PathBuilder, public Meta, public UI #define RESTRICT __restrict__ #endif - -class volumedsp : public dsp { - - private: - - FAUSTFLOAT fHslider0; - FAUSTFLOAT fCheckbox0; - int fSampleRate; - float fConst0; - float fConst1; - float fRec0[2]; - - public: - - void metadata(Meta* m) { - m->declare("author", "Matt Horton, adapted from GRAME"); - m->declare("basics.lib/name", "Faust Basic Element Library"); - m->declare("basics.lib/version", "0.8"); - m->declare("compile_options", "-a faust2header.cpp -lang cpp -i -inpl -cn volumedsp -es 1 -mcd 16 -single -ftz 0"); - m->declare("description", "Volume Control Faust Plugin for JackTrip, based on Faust examples"); - m->declare("filename", "volumedsp.dsp"); - m->declare("license", "MIT Style STK-4.2"); - m->declare("maths.lib/author", "GRAME"); - m->declare("maths.lib/copyright", "GRAME"); - m->declare("maths.lib/license", "LGPL with exception"); - m->declare("maths.lib/name", "Faust Math Library"); - m->declare("maths.lib/version", "2.5"); - m->declare("name", "volume"); - m->declare("platform.lib/name", "Generic Platform Library"); - m->declare("platform.lib/version", "0.2"); - m->declare("signals.lib/name", "Faust Signal Routing Library"); - m->declare("signals.lib/version", "0.3"); - m->declare("version", "1.0"); - } - - virtual int getNumInputs() { - return 1; - } - virtual int getNumOutputs() { - return 1; - } - - static void classInit(int /*sample_rate*/) { - } - - virtual void instanceConstants(int sample_rate) { - fSampleRate = sample_rate; - fConst0 = 44.0999985f / std::min(192000.0f, std::max(1.0f, float(fSampleRate))); - fConst1 = 1.0f - fConst0; - } - - virtual void instanceResetUserInterface() { - fHslider0 = FAUSTFLOAT(0.0f); - fCheckbox0 = FAUSTFLOAT(0.0f); - } - - virtual void instanceClear() { - for (int l0 = 0; l0 < 2; l0 = l0 + 1) { - fRec0[l0] = 0.0f; - } - } - - virtual void init(int sample_rate) { - classInit(sample_rate); - instanceInit(sample_rate); - } - virtual void instanceInit(int sample_rate) { - instanceConstants(sample_rate); - instanceResetUserInterface(); - instanceClear(); - } - - virtual volumedsp* clone() { - return new volumedsp(); - } - - virtual int getSampleRate() { - return fSampleRate; - } - - virtual void buildUserInterface(UI* ui_interface) { - ui_interface->openVerticalBox("Volume Control"); - ui_interface->declare(&fHslider0, "0", ""); - ui_interface->addHorizontalSlider("Volume", &fHslider0, FAUSTFLOAT(0.0f), FAUSTFLOAT(-40.0f), FAUSTFLOAT(0.0f), FAUSTFLOAT(0.100000001f)); - ui_interface->declare(&fCheckbox0, "1", ""); - ui_interface->addCheckButton("Mute", &fCheckbox0); - ui_interface->closeBox(); - } - - virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { - FAUSTFLOAT* input0 = inputs[0]; - FAUSTFLOAT* output0 = outputs[0]; - float fSlow0 = float(fHslider0); - int iSlow1 = fSlow0 == -40.0f; - int iSlow2 = int(float(fCheckbox0)); - float fSlow3 = fConst0 * std::pow(10.0f, 0.0500000007f * fSlow0); - for (int i0 = 0; i0 < count; i0 = i0 + 1) { - float fTemp0 = float(input0[i0]); - fRec0[0] = fSlow3 + fConst1 * fRec0[1]; - float fThen0 = fTemp0 * fRec0[0]; - float fThen1 = ((iSlow2) ? 0.0f : fThen0); - output0[i0] = FAUSTFLOAT(((iSlow1) ? 0.0f : fThen1)); - fRec0[1] = fRec0[0]; - } - } - +class volumedsp : public dsp +{ + private: + FAUSTFLOAT fHslider0; + FAUSTFLOAT fCheckbox0; + int fSampleRate; + float fConst0; + float fConst1; + float fRec0[2]; + + public: + void metadata(Meta* m) + { + m->declare("author", "Matt Horton, adapted from GRAME"); + m->declare("basics.lib/name", "Faust Basic Element Library"); + m->declare("basics.lib/version", "0.8"); + m->declare("compile_options", + "-a faust2header.cpp -lang cpp -i -inpl -cn volumedsp -es 1 -mcd 16 " + "-single -ftz 0"); + m->declare("description", + "Volume Control Faust Plugin for JackTrip, based on Faust examples"); + m->declare("filename", "volumedsp.dsp"); + m->declare("license", "MIT Style STK-4.2"); + m->declare("maths.lib/author", "GRAME"); + m->declare("maths.lib/copyright", "GRAME"); + m->declare("maths.lib/license", "LGPL with exception"); + m->declare("maths.lib/name", "Faust Math Library"); + m->declare("maths.lib/version", "2.5"); + m->declare("name", "volume"); + m->declare("platform.lib/name", "Generic Platform Library"); + m->declare("platform.lib/version", "0.2"); + m->declare("signals.lib/name", "Faust Signal Routing Library"); + m->declare("signals.lib/version", "0.3"); + m->declare("version", "1.0"); + } + + virtual int getNumInputs() { return 1; } + virtual int getNumOutputs() { return 1; } + + static void classInit(int /*sample_rate*/) {} + + virtual void instanceConstants(int sample_rate) + { + fSampleRate = sample_rate; + fConst0 = 44.0999985f + / std::min(192000.0f, std::max(1.0f, float(fSampleRate))); + fConst1 = 1.0f - fConst0; + } + + virtual void instanceResetUserInterface() + { + fHslider0 = FAUSTFLOAT(0.0f); + fCheckbox0 = FAUSTFLOAT(0.0f); + } + + virtual void instanceClear() + { + for (int l0 = 0; l0 < 2; l0 = l0 + 1) { + fRec0[l0] = 0.0f; + } + } + + virtual void init(int sample_rate) + { + classInit(sample_rate); + instanceInit(sample_rate); + } + virtual void instanceInit(int sample_rate) + { + instanceConstants(sample_rate); + instanceResetUserInterface(); + instanceClear(); + } + + virtual volumedsp* clone() { return new volumedsp(); } + + virtual int getSampleRate() { return fSampleRate; } + + virtual void buildUserInterface(UI* ui_interface) + { + ui_interface->openVerticalBox("Volume Control"); + ui_interface->declare(&fHslider0, "0", ""); + ui_interface->addHorizontalSlider("Volume", &fHslider0, FAUSTFLOAT(0.0f), + FAUSTFLOAT(-40.0f), FAUSTFLOAT(0.0f), + FAUSTFLOAT(0.100000001f)); + ui_interface->declare(&fCheckbox0, "1", ""); + ui_interface->addCheckButton("Mute", &fCheckbox0); + ui_interface->closeBox(); + } + + virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) + { + FAUSTFLOAT* input0 = inputs[0]; + FAUSTFLOAT* output0 = outputs[0]; + float fSlow0 = float(fHslider0); + int iSlow1 = fSlow0 == -40.0f; + int iSlow2 = int(float(fCheckbox0)); + float fSlow3 = fConst0 * std::pow(10.0f, 0.0500000007f * fSlow0); + for (int i0 = 0; i0 < count; i0 = i0 + 1) { + float fTemp0 = float(input0[i0]); + fRec0[0] = fSlow3 + fConst1 * fRec0[1]; + float fThen0 = fTemp0 * fRec0[0]; + float fThen1 = ((iSlow2) ? 0.0f : fThen0); + output0[i0] = FAUSTFLOAT(((iSlow1) ? 0.0f : fThen1)); + fRec0[1] = fRec0[0]; + } + } }; - #endif diff --git a/src/zitarevdsp.h b/src/zitarevdsp.h index 0ee6905..b7e839a 100644 --- a/src/zitarevdsp.h +++ b/src/zitarevdsp.h @@ -1130,8 +1130,8 @@ class FAUST_API AccUpDownConverter : public UpdatableValueConverter Interpolator fF2A; public: - AccUpDownConverter(double amin, double amid, double amax, double fmin, double /*fmid*/, - double fmax) + AccUpDownConverter(double amin, double amid, double amax, double fmin, + double /*fmid*/, double fmax) : fA2F(amin, amid, amax, fmin, fmax, fmin) , fF2A(fmin, fmax, amin, amax) // Special, pseudo inverse of a non monotonic function @@ -1167,8 +1167,8 @@ class FAUST_API AccDownUpConverter : public UpdatableValueConverter Interpolator fF2A; public: - AccDownUpConverter(double amin, double amid, double amax, double fmin, double /*fmid*/, - double fmax) + AccDownUpConverter(double amin, double amid, double amax, double fmin, + double /*fmid*/, double fmax) : fA2F(amin, amid, amax, fmax, fmin, fmax) , fF2A(fmin, fmax, amin, amax) // Special, pseudo inverse of a non monotonic function @@ -1207,8 +1207,9 @@ class FAUST_API ZoneControl virtual void update(double /*v*/) const {} - virtual void setMappingValues(int /*curve*/, double /*amin*/, double /*amid*/, double /*amax*/, - double /*min*/, double /*init*/, double /*max*/) + virtual void setMappingValues(int /*curve*/, double /*amin*/, double /*amid*/, + double /*amax*/, double /*min*/, double /*init*/, + double /*max*/) { } virtual void getMappingValues(double& /*amin*/, double& /*amid*/, double& /*amax*/) {} @@ -1701,7 +1702,7 @@ class APIUI std::string path = std::string(path_aux); auto it = find_if(fItems.begin(), fItems.end(), [=](const Item& it) { return (it.fLabel == path) || (it.fShortname == path) || (it.fPath == path); - }); + }); return (it != fItems.end()) ? int(it - fItems.begin()) : -1; } @@ -2773,8 +2774,8 @@ class zitarevdsp : public dsp float fTemp25 = fSlow5 * fRec2[0]; float fTemp26 = 1.0f - fRec1[0]; output0[i0] = FAUSTFLOAT( - fRec0[0] - * (0.5f * fRec1[0] + fRec0[0] + * (0.5f * fRec1[0] * (fTemp25 + fRec2[2] + fTemp23 + fTemp24 + fSlow3 * ((fTemp25 + fTemp24 + fRec2[2]) - fTemp23)) + fTemp0 * fTemp26)); @@ -2789,8 +2790,8 @@ class zitarevdsp : public dsp fRec44[0] = fTemp30 - (fTemp31 + fSlow5 * fRec44[2]); float fTemp32 = fSlow5 * fRec44[0]; output1[i0] = FAUSTFLOAT( - fRec0[0] - * (0.5f * fRec1[0] + fRec0[0] + * (0.5f * fRec1[0] * (fTemp32 + fRec44[2] + fTemp30 + fTemp31 + fSlow3 * ((fTemp32 + fTemp31 + fRec44[2]) - fTemp30)) + fTemp1 * fTemp26)); diff --git a/src/zitarevmonodsp.h b/src/zitarevmonodsp.h index 4f0475b..4df8807 100644 --- a/src/zitarevmonodsp.h +++ b/src/zitarevmonodsp.h @@ -1130,8 +1130,8 @@ class FAUST_API AccUpDownConverter : public UpdatableValueConverter Interpolator fF2A; public: - AccUpDownConverter(double amin, double amid, double amax, double fmin, double /*fmid*/, - double fmax) + AccUpDownConverter(double amin, double amid, double amax, double fmin, + double /*fmid*/, double fmax) : fA2F(amin, amid, amax, fmin, fmax, fmin) , fF2A(fmin, fmax, amin, amax) // Special, pseudo inverse of a non monotonic function @@ -1167,8 +1167,8 @@ class FAUST_API AccDownUpConverter : public UpdatableValueConverter Interpolator fF2A; public: - AccDownUpConverter(double amin, double amid, double amax, double fmin, double /*fmid*/, - double fmax) + AccDownUpConverter(double amin, double amid, double amax, double fmin, + double /*fmid*/, double fmax) : fA2F(amin, amid, amax, fmax, fmin, fmax) , fF2A(fmin, fmax, amin, amax) // Special, pseudo inverse of a non monotonic function @@ -1207,8 +1207,9 @@ class FAUST_API ZoneControl virtual void update(double /*v*/) const {} - virtual void setMappingValues(int /*curve*/, double /*amin*/, double /*amid*/, double /*amax*/, - double /*min*/, double /*init*/, double /*max*/) + virtual void setMappingValues(int /*curve*/, double /*amin*/, double /*amid*/, + double /*amax*/, double /*min*/, double /*init*/, + double /*max*/) { } virtual void getMappingValues(double& /*amin*/, double& /*amid*/, double& /*amax*/) {} @@ -1701,7 +1702,7 @@ class APIUI std::string path = std::string(path_aux); auto it = find_if(fItems.begin(), fItems.end(), [=](const Item& it) { return (it.fLabel == path) || (it.fShortname == path) || (it.fPath == path); - }); + }); return (it != fItems.end()) ? int(it - fItems.begin()) : -1; } @@ -2793,8 +2794,8 @@ class zitarevmonodsp : public dsp fRec44[0] = fTemp27 - (fTemp28 + fSlow5 * fRec44[2]); float fTemp29 = fSlow5 * fRec44[0]; output0[i0] = FAUSTFLOAT( - fRec0[0] - * (0.5f * fRec1[0] + fRec0[0] + * (0.5f * fRec1[0] * (fTemp22 + fRec2[2] + fTemp20 + fTemp21 + fSlow3 * ((fTemp22 + fTemp21 + fRec2[2]) - fTemp20)) + fTemp23 + fTemp23