diff --git a/.travis.yml b/.travis.yml index 8973eeadb740..21af5fb1d6a4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,6 +34,7 @@ addons: - librubberband-dev - libshout3-dev - libsndfile1-dev + - libsoundtouch-dev - libsqlite3-dev - libtag1-dev - libupower-glib-dev @@ -45,6 +46,7 @@ addons: - qt5-default - qtdeclarative5-dev - qtscript5-dev + - libqt5x11extras5-dev - scons - vamp-plugin-sdk - qtkeychain-dev @@ -53,7 +55,7 @@ before_install: # Virtual X, needed for analyzer waveform tests - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then export DISPLAY=:99.0 ; fi - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sh -e /etc/init.d/xvfb start ; fi - - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install scons portaudio libsndfile libogg libvorbis portmidi taglib libshout protobuf flac ffmpeg qt chromaprint rubberband libmodplug libid3tag libmad mp4v2 faad2 wavpack opusfile lilv lame; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install scons portaudio libsndfile libogg libvorbis portmidi taglib libshout protobuf flac ffmpeg qt chromaprint rubberband libmodplug libid3tag libmad mp4v2 faad2 wavpack opusfile lilv lame sound-touch; fi install: #### diff --git a/CHANGELOG b/CHANGELOG index 4710f8121ea7..cf4d1609fd3f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,23 +1,34 @@ -==== 2.2.0 (draft) 2018-09-12 ==== +==== 2.2.0 2018-12-17 ==== +General * Update from Qt4 to Qt5. -* Remove GUI scaling option from preferences; use Qt5's automatic - scaling instead. +* Use Qt5's automatic high DPI scaling (and remove the old + scaling option from the preferences). +* Vectorize remaining raster graphics for better HiDPI support. + +Effects * Add mix mode switch (Dry/Wet vs Dry+Wet) for effect units. -* Add support for LV2 effects plugins. (currently no way to show plugin GUIs) +* Add support for LV2 effects plugins (currently no way to show plugin GUIs). * Add preference option for selecting which effects are shown in the - list of available effects in the main window. (all LV2 effects are - hidden by default and must be explicitly enabled by users) -* Add preference option for adjusting play position marker of + list of available effects in the main window (all LV2 effects are + hidden by default and must be explicitly enabled by users). + +Skins +* Add 8 sampler and small sampler options to LateNight. +* Add key / BPM expansion indicators to Deere decks. +* Add skin settings menu to LateNight. + +Controllers +* Add controller mapping for Numark Mixtrack Platinum. +* Update controller mapping for Numark N4. +* Add spinback and break for Vestax VCI-400 mapping. + +Miscellaneous +* Add preference option to adjust the play position marker of scrolling waveforms. * Add preference option to adjust opacity of beatgrid markers on scrolling waveforms. -* Add 8 sampler and small sampler options to LateNight. -* Add key / BPM expansion indicators to Deere decks. -* Vectorize Deere, LateNight and Tango skin assets for better HiDPI support. -* Behringer CMD-MM1 controller preset improvements. * Support IRC/AIM/ICQ broadcast metadata. -* Add skin settings menu to LateNight. ==== 2.1.5 2018-10-28 ==== diff --git a/Mixxx-Manual.pdf b/Mixxx-Manual.pdf index d42a9391ace0..c82442963a40 100644 Binary files a/Mixxx-Manual.pdf and b/Mixxx-Manual.pdf differ diff --git a/appveyor.yml b/appveyor.yml index 62a56d3d7a10..f5663bb1263d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -50,7 +50,7 @@ for: install: - sudo apt-get update - - sudo apt-get -y install gdb libavformat-dev libchromaprint-dev libfaad-dev libfftw3-dev libflac-dev libid3tag0-dev libmad0-dev libmodplug-dev libmp3lame-dev libmp4v2-dev libopusfile-dev libportmidi-dev libprotobuf-dev libqt5opengl5-dev libqt5sql5-sqlite libqt5svg5-dev librubberband-dev libshout3-dev libsndfile1-dev libsqlite3-dev libtag1-dev libupower-glib-dev libusb-1.0-0-dev libwavpack-dev portaudio19-dev protobuf-compiler qt5-default qtdeclarative5-dev qtscript5-dev scons vamp-plugin-sdk qtkeychain-dev liblilv-dev + - sudo apt-get -y install gdb libavformat-dev libchromaprint-dev libfaad-dev libfftw3-dev libflac-dev libid3tag0-dev libmad0-dev libmodplug-dev libmp3lame-dev libmp4v2-dev libopusfile-dev libportmidi-dev libprotobuf-dev libqt5opengl5-dev libqt5sql5-sqlite libqt5svg5-dev librubberband-dev libshout3-dev libsndfile1-dev libsqlite3-dev libtag1-dev libupower-glib-dev libusb-1.0-0-dev libwavpack-dev portaudio19-dev protobuf-compiler qt5-default qtdeclarative5-dev qtscript5-dev libqt5x11extras5-dev scons vamp-plugin-sdk qtkeychain-dev liblilv-dev libsoundtouch-dev build_script: - scons -j4 test=1 mad=1 faad=1 ffmpeg=1 opus=1 modplug=1 wv=1 hss1394=0 virtualize=0 debug_assertions_fatal=1 verbose=0 localecompare=1 diff --git a/build/appveyor/build_mixxx.bat b/build/appveyor/build_mixxx.bat index e9f08e4b82ba..69e8371bf932 100644 --- a/build/appveyor/build_mixxx.bat +++ b/build/appveyor/build_mixxx.bat @@ -78,7 +78,7 @@ SET BIN_DIR=%WINLIB_DIR%\bin SET LIB_DIR=%WINLIB_DIR%\lib SET INCLUDE_DIR=%WINLIB_DIR%\include REM TODO(rryan): Remove hard-coding of Qt version. -set QT_VERSION=5.11.2 +set QT_VERSION=5.12.0 SET QTDIR=%WINLIB_DIR%\Qt-%QT_VERSION% if NOT EXIST "%BIN_DIR%\scons.py" ( diff --git a/build/debian/control b/build/debian/control index b8bf8610afa6..93fdf28958e4 100644 --- a/build/debian/control +++ b/build/debian/control @@ -23,6 +23,7 @@ Build-Depends: debhelper (>= 9), libqt5svg5-dev, # Only needed for running tests that use SQLite. libqt5sql5-sqlite, + libqt5x11extras5-dev, scons, libjack-dev, portaudio19-dev, @@ -122,4 +123,4 @@ Depends: ${shlibs:Depends}, libqt5xml5, libqt5sql5, libqt5sql5-sqlite -Description: The Mixxx test suite. \ No newline at end of file +Description: The Mixxx test suite. diff --git a/build/depends.py b/build/depends.py index 20b96b26c06c..295bd68b673f 100644 --- a/build/depends.py +++ b/build/depends.py @@ -280,6 +280,9 @@ def configure(self, build, conf): if not conf.CheckForPKG('Qt5Core', '5.0'): raise Exception('Qt >= 5.0 not found') + if not conf.CheckLib('Qt5X11Extras'): + raise Exception('Could not find Qt5X11Extras or its development headers') + qt_modules.extend(['QtDBus']) # This automatically converts QtXXX to Qt5XXX where appropriate. build.env.EnableQt5Modules(qt_modules, debug=False) @@ -375,6 +378,7 @@ def configure(self, build, conf): build.env.Append(LIBS = 'userenv') # qt5core build.env.Append(LIBS = 'uxtheme') # ? build.env.Append(LIBS = 'version') # ? + build.env.Append(LIBS = 'wtsapi32') # ? build.env.Append(LIBS = 'qtfreetype') build.env.Append(LIBS = 'qtharfbuzz') diff --git a/build/features.py b/build/features.py index b60b5ba06a46..68469f0ffe38 100644 --- a/build/features.py +++ b/build/features.py @@ -355,14 +355,18 @@ def configure(self, build, conf): # If there is no system vamp-hostsdk is installed or if the version # of the installed vamp-hostsdk is less than the bundled version, # then we'll directly link the bundled vamp-hostsdk - if not conf.CheckLib('vamp-hostsdk') or not conf.CheckForPKG('vamp-plugin-sdk', '2.7.1'): + # Note: We're adding vamp-hostsdk to LIBS in sources(), so + # don't add it now in order to prevent duplication. + if not conf.CheckLib('vamp-hostsdk', autoadd=False) or not conf.CheckForPKG('vamp-plugin-sdk', '2.7.1'): self.INTERNAL_LINK = True build.env.Append(CPPPATH=['#' + self.INTERNAL_VAMP_PATH]) # Needed on Linux at least. Maybe needed elsewhere? if build.platform_is_linux: # Optionally link libdl Required for some distros. - conf.CheckLib(['dl', 'libdl']) + # Note: We can't add dl to LIBS here because it needs to be added after vamp-hostsdk. + # See: https://bugs.launchpad.net/mixxx/+bug/1804411 + conf.CheckLib(['dl', 'libdl'], autoadd=False) # FFTW3 support have_fftw3_h = conf.CheckHeader('fftw3.h') @@ -383,7 +387,13 @@ def sources(self, build): env.SConscript(env.File('SConscript', vamp_dir)) build.env.Append(LIBPATH=self.INTERNAL_VAMP_PATH) - build.env.Append(LIBS=['vamp-hostsdk']) + + # Add this here unconditionally because we're not adding it in configure(). + build.env.Append(LIBS=['vamp-hostsdk']) + + # Ubuntu requires dl to be specified after vamp-hostsdk. + if build.platform_is_linux: + build.env.Append(LIBS=['dl']) return ['src/analyzer/vamp/vampanalyzer.cpp', 'src/analyzer/vamp/vamppluginadapter.cpp', diff --git a/build/osx/golden_environment b/build/osx/golden_environment index d23d7c357711..095115120192 100644 --- a/build/osx/golden_environment +++ b/build/osx/golden_environment @@ -1 +1 @@ -2.3-j00001-6fe69c4-osx10.11-x86_64-release +2.3-j00002-e5dbf6e0-osx10.11-x86_64-release diff --git a/build/windows/golden_environment b/build/windows/golden_environment index 57aa525c9122..6dfe2d574022 100644 --- a/build/windows/golden_environment +++ b/build/windows/golden_environment @@ -1 +1 @@ -2.3-j00009-PLATFORM-CONFIGURATION-static-f588d481-minimal \ No newline at end of file +2.3-j00013-PLATFORM-CONFIGURATION-static-36f44bd2-minimal diff --git a/build/wix/Localization/mixxx_ca-ES.wxl b/build/wix/Localization/mixxx_ca-ES.wxl index cd090e2fa440..94195cb30fe0 100644 --- a/build/wix/Localization/mixxx_ca-ES.wxl +++ b/build/wix/Localization/mixxx_ca-ES.wxl @@ -26,7 +26,7 @@ Ja teniu instal·lada aquesta versió del Mixxx o una més recent. Heu d'instal·lar la versió de 64 bits d'aquest producte en un Windows de 64 bits. Heu d'instal·lar la versió de 32 bits d'aquest producte en un Windows de 32 bits. - Esteu a punt d'instal·lar la versió de 32 bits en un sistema operatiu de 64 bits. Recomanem utilitzar la versió de 64 bits per a un millor rendiment. Podeu baixar l'instal·lador de la versió de 64 bits des de http://mixxx.org/download/ + Esteu a punt d'instal·lar la versió de 32 bits en un sistema operatiu de 64 bits. Recomanem utilitzar la versió de 64 bits per a un millor rendiment. Podeu baixar l'instal·lador de la versió de 64 bits des de http://mixxx.org/download/ Esteu instal·lant el Mixxx en un sistema operatiu obsolet. Algunes funcionalitats poden no funcionar correctament. Recomanem actualitzar el sistema operatiu. Esteu a punt d'instal·lar la versió de 32 bits tot i que teniu instal·lada una versió de 64 bits. Això pot provocar un comportament no desitjat. Desinstal·leu primer la versió existent del Mixxx o baixeu l'instal·lador de 64 bits per actualitzar la versió (a no ser que sapigueu exactament què esteu fent). Esteu a punt d'instal·lar la versió de 64 bits tot i que teniu instal·lada una versió de 32 bits. Això pot provocar un comportament no desitjat. Desinstal·leu primer la versió existent del Mixxx o baixeu l'instal·lador de 32 bits per a actualitzar la versió (a no ser que sapigueu exactament què esteu fent). diff --git a/build/wix/Localization/mixxx_cs-CZ.wxl b/build/wix/Localization/mixxx_cs-CZ.wxl index 1afddfaa677a..2b1e3f4e4fdd 100644 --- a/build/wix/Localization/mixxx_cs-CZ.wxl +++ b/build/wix/Localization/mixxx_cs-CZ.wxl @@ -26,7 +26,7 @@ Již je nainstalována stejná nebo novější verze tohoto výrobku. Do 64bitových Windows musíte nainstalovat 64bitovou verzi tohoto výrobku. Do 32bitových Windows musíte nainstalovat 32bitovou verzi tohoto výrobku. - Chystáte se nainstalovat 32bitovou verzi do 64bitového operačního systému. Doporučujeme použít 64bitovou verzi kvůli lepšímu výkonu. Instalační balíček pro 64bitový systém můžete stáhnout z http://mixxx.org/download/ + Chystáte se nainstalovat 32bitovou verzi do 64bitového operačního systému. Doporučujeme použít 64bitovou verzi kvůli lepšímu výkonu. Instalační balíček pro 64bitový systém můžete stáhnout z http://mixxx.org/download/ Instalujete Mixxx do zastaralého operačního systému. Některé funkce nemusí pracovat dobře, nebo nebudou pracovat vůbec. Doporučujeme vám povýšení operačního sytému. Chystáte se nainstalovat 32bitovou verzi, ale již je nainstalována 64bitová verze. To může vést k neobvyklému chování. Odinstalujte, prosím, nejprve stávající verzi Mixxxu, nebo pro povýšení verze stáhněte instalační balíček pro 64bitový systém (pokud přesně nevíte, co děláte). Chystáte se nainstalovat 64bitovou verzi, ale již je nainstalována 32bitová verze. To může vést k neobvyklému chování. Odinstalujte, prosím, nejprve stávající verzi Mixxxu, nebo pro povýšení verze stáhněte instalační balíček pro 32bitový systém (pokud přesně nevíte, co děláte). diff --git a/build/wix/Localization/mixxx_de-DE.wxl b/build/wix/Localization/mixxx_de-DE.wxl index b337398de6e7..15623815de71 100644 --- a/build/wix/Localization/mixxx_de-DE.wxl +++ b/build/wix/Localization/mixxx_de-DE.wxl @@ -80,7 +80,7 @@ Setup-Fortschritt Wird bearbeitet: Initialisiere... - &Cancel + &Abbrechen Setup ändern &Reparieren &Deinstallieren diff --git a/build/wix/Localization/mixxx_es-ES.wxl b/build/wix/Localization/mixxx_es-ES.wxl index b3bd1c0e607d..2b598f6eee2f 100644 --- a/build/wix/Localization/mixxx_es-ES.wxl +++ b/build/wix/Localization/mixxx_es-ES.wxl @@ -22,11 +22,11 @@ - Este producto requiere Windows 7 o una versión superior. + Este producto requiere Windows 7 o superior. La misma versión o una más reciente de este producto está ya instalada. Necesita instalar la versión de 64 bits de este producto en una versión de Windows de 64 bits. Necesita instalar la versión de 32 bits de este producto en una versión de Windows de 32 bits. - Está a punto de instalar la versión de 32 bits en un sistema operativo de 64 bits. Recomendamos usar la versión de 64 bits para un mejor rendimiento. Puede descargar el instalador de la versión de 64 bits desde http://mixxx.org/download/ + Está a punto de instalar la versión de 32 bits en un sistema operativo de 64 bits. Recomendamos utilizar la versión de 64 bits para un mejor rendimiento. Puede descargar el paquete de instalación de 64 bits desde http://mixxx.org/download/ Está instalando Mixxx en un sistema operativo obsoleto. Algunas funciones pueden no funcionar correctamente. Recomendamos actualizar su sistema operativo. Está a punto de instalar la versión de 32 bits pero la versión de 64 bits está instalada. Esto puede llevar a un comportamiento indeseado del programa. Por favor, desinstale primero la versión existente, o descargue el instalador de 64 bits (a no ser que sepa exactamente lo que está haciendo). Está a punto de instalar la versión de 64 bits pero la versión de 32 bits está instalada. Esto puede llevar a un comportamiento indeseado del programa. Por favor, desinstale primero la versión existente, o descargue el instalador de 32 bits (a no ser que sepa exactamente lo que está haciendo). diff --git a/build/wix/Localization/mixxx_et-EE.wxl b/build/wix/Localization/mixxx_et-EE.wxl index 3bac56dd565a..ff4f81a5421c 100644 --- a/build/wix/Localization/mixxx_et-EE.wxl +++ b/build/wix/Localization/mixxx_et-EE.wxl @@ -26,7 +26,7 @@ Sama või uuem versioon sellest tootest on juba paigaldatud. Sul tuleb paigaldada 64-bitine versioon sellest tootest 64-bitisele Windowsile. Sul tuleb paigaldada 32-bitine versioon sellest tootest 32-bitisele Windowsile. - Sa soovid paigaldada 32-bitist versiooni 64-bitisele operatsioonisüsteemile. Soovitame kasutada 64-bitist versiooni parema jõudluse jaoks. Saate 64-bitise paigalduspaketi alla laadida aadressilt http://mixxx.org/download/ + Sa soovid paigaldada 32-bitist versiooni 64-bitisele operatsioonisüsteemile. Soovitame kasutada 64-bitist versiooni parema jõudluse jaoks. Saate 64-bitise paigalduspaketi alla laadida aadressilt http://mixxx.org/download/ Te paigaldate Mixxxi vananenud operatsioonisüsteemile. Mõned funktsioonid ei pruugi normaalselt või üldse töödata. Soovitame teil uuendada oma operatsioonisüsteem. Sa proovid paigaldada 32-bitist versiooni, kuid 64-bitine on juba paigaldatud. See võib viia soovimatu käitumiseni. Palun eemaldage olemasolev Mixxx kõigepealt või laadige 64-bitine paigalduspakett uuendamiseks alla (kui sa just ei tea mida sa täpselt teed) Sa proovid paigaldada 64-bitist versiooni aga 32-bitine on juba paigaldatud. See võib viia soovimatu käitumiseni. Palun eemaldage olemasolev Mixxx kõigepealt või laadige 32-bitine paigalduspakett uuendamiseks alla (kui sa just ei tea mida sa täpselt teed) diff --git a/build/wix/Localization/mixxx_fr-FR.wxl b/build/wix/Localization/mixxx_fr-FR.wxl index a9f5c70c815d..afc6a9e73a17 100644 --- a/build/wix/Localization/mixxx_fr-FR.wxl +++ b/build/wix/Localization/mixxx_fr-FR.wxl @@ -26,7 +26,7 @@ Une version plus récente ou identique de ce produit est déjà installée. Vous devez installer la version 64-bits de ce produit sur un Windows 64-bits. Vous devez installer la version 32-bits de ce produit sur un Windows 32-bits. - Vous installez une version 32 bits sur un système 64 bits. Nous vous recommandons d'utiliser une version 64 bits pour de meilleures performances. Vous pouvez télécharger l'installeur 64 bits ici : http://mixxx.org/download/ + Vous installez une version 32 bits sur un système 64 bits. Nous vous recommandons d'utiliser une version 64 bits pour de meilleures performances. Vous pouvez télécharger l'installeur 64 bits ici : http://mixxx.org/download/ Vous installez Mixxx sur un système obsolète. Certaines fonctions pourraient ne pas fonctionner. Nous vous recommandons de mettre à jour votre système d'exploitation. Vous installez une version 32 bits de Mixxx, mais il existe déjà une version 64 bits installée. Ceci peut conduire à un comportement imprévisible. SVP, désinstallez d'abord ou téléchargez l'installeur correspondant pour mettre à jour, à moins de savoir exactement ce que vous faites. Vous installez une version 64 bits de Mixxx, mais il existe déjà une version 32 bits installée. Ceci peut conduire à un comportement imprévisible. SVP, désinstallez d'abord ou téléchargez l'installeur correspondant pour mettre à jour, à moins de savoir exactement ce que vous faites. diff --git a/build/wix/Localization/mixxx_it-IT.wxl b/build/wix/Localization/mixxx_it-IT.wxl index a9196a5f3ae0..a834ba405279 100644 --- a/build/wix/Localization/mixxx_it-IT.wxl +++ b/build/wix/Localization/mixxx_it-IT.wxl @@ -26,7 +26,7 @@ La stessa o una versione più recente di questo prodotto è già installata. Devi installare la versione a 64-bit di questo prodotto su Windows a 64-bit. Devi installare la versione a 32-bit di questo prodotto su Windows a 32-bit. - Stai per installare la versione a 32-bit su un sistema operativo a 64-bit. Raccomandiamo di usare la versione a 64-bit per ottenere prestazioni migliori. Puoi scaricare il pacchetto di installazione a 64-bit da http://mixxx.org/download/ + Stai per installare la versione a 32-bit su un sistema operativo a 64-bit. Raccomandiamo di usare la versione a 64-bit per ottenere prestazioni migliori. Puoi scaricare il pacchetto di installazione a 64-bit da http://mixxx.org/download/ Stai per installare Mixxx su un sistema operativo vecchio. Alcune funzioni potrebbero non funzionare bene o completamente. Raccomandiamo di aggiornare il tuo sistema operativo. Stai per installare la versione a 32-bit ma è già installata una versione a 64-bit. Ciò può portare a comportamenti indesiderati. Disinstallare prima l'esistente Mixxx per favore, oppure scaricare il pacchetto di installazione a 64-bit per eseguire l'aggiornamento (a meno che tu non conosca esattamente quello che stai facendo). Stai per installare la versione a 64-bit ma è già installata una versione a 32-bit. Ciò può portare a comportamenti indesiderati. Disinstallare prima l'esistente Mixxx per favore, oppure scaricare il pacchetto di installazione a 32-bit per eseguire l'aggiornamento (a meno che tu non conosca esattamente quello che stai facendo). diff --git a/build/wix/Localization/mixxx_nl-NL.wxl b/build/wix/Localization/mixxx_nl-NL.wxl index 828cf46e8c15..080fe7f38ce2 100644 --- a/build/wix/Localization/mixxx_nl-NL.wxl +++ b/build/wix/Localization/mixxx_nl-NL.wxl @@ -26,7 +26,7 @@ Dezelfde of een nieuwere versie van dit product is reeds geïnstalleerd. Je moet de 64-bits versie van dit product installeren op een 64-bits versie van Windows. Je moet de 32-bits versie van dit product installeren op een 32-bits versie van Windows. - Je staat op het punt om de 32-bits versie te installeren op een 64-bits besturingssysteem. We raden aan om de 64-bits versie te gebruiken voor betere prestaties. Je kunt het 64-bits installatiepakket downloaden van http://mixxx.org/download/ + Je staat op het punt om de 32-bits versie te installeren op een 64-bits besturingssysteem. We raden aan om de 64-bits versie te gebruiken voor betere prestaties. Je kunt het 64-bits installatiepakket downloaden van http://mixxx.org/download/ Je wilt Mixxx installeren op een verouderd besturingssysteem. Sommige functies werken mogelijk niet goed of helemaal niet. We raden je aan om je besturingssysteem te upgraden. Je wilt de 32-bits versie installeren maar een 64-bits is reeds geïnstalleerd. Dit kan leiden tot ongewenste effecten. Gelieve eerst de bestaande Mixxx te verwijderen, of het 64-bits installatiepakket te downloaden en te upgraden (Tenzij je exact weet waar je aan begint) Je wilt de 64-bits versie installeren maar een 32-bits is reeds geïnstalleerd. Dit kan leiden tot ongewenste effecten. Gelieve eerst de bestaande Mixxx te verwijderen, of het 32-bits installatiepakket te downloaden en te upgraden (Tenzij je exact weet waar je aan begint) diff --git a/build/wix/Localization/mixxx_pl-PL.wxl b/build/wix/Localization/mixxx_pl-PL.wxl index 99c6b76af139..f133619d2152 100644 --- a/build/wix/Localization/mixxx_pl-PL.wxl +++ b/build/wix/Localization/mixxx_pl-PL.wxl @@ -22,11 +22,11 @@ - Ten produkt wymaga Windowsa XP lub wyżsego + Ten produkt wymaga Windowsa 7 lub wyżsego Ta lub nowsza wersja tego produktu jest juź zainstalowana. Musisz zainstalować 64-bitową wersję na 64-bitowym Windowsie. Musisz zainstalować 32-bitową wersję na 32-bitowym Windowsie. - Masz zamiar zainstalować wersję 32-bitową w 64-bitowym systemie operacyjnym. Zalecane jest użycie 64-bitowej wersji dla lepszej wydajności. Pakiet instalacji 64-bitowej można pobrać z http://mixxx.org/download/ + Masz zamiar zainstalować wersję 32-bitową w 64-bitowym systemie operacyjnym. Zalecane jest użycie 64-bitowej wersji dla lepszej wydajności. Pakiet instalacji 64-bitowej można pobrać z http://mixxx.org/download/ Instalujesz Mixxx'a na przestarzałym systemie operacyjnym. Niektóre funkcje mogą nie działac prawidłowo lub wcale. Rekomendujemy zaktualizować swój system operacyjny. Masz zamiar zainstalować 32-bitową wersje, ale już jest zainstalowana wersja 64-bitowa. Może to prowadzić do niepożądanego działania. Najpierw należy odinstalować istniejącego Mixxx'a, lub Pobrać pakiet instalacji 64-bitowej do uaktualnienia (chyba, że wiesz, co robisz.) Masz zamiar zainstalować 64-bitową wersję, ale już jest zainstalowana wersja 32-bitowa. Może to prowadzić do niepożądanego działania. Najpierw należy odinstalować istniejącego Mixxx'a, lub Pobrać pakiet instalacji 32-bitowe do uaktualnienia (chyba, że wiesz, co robisz.) diff --git a/build/wix/Localization/mixxx_pt-BR.wxl b/build/wix/Localization/mixxx_pt-BR.wxl index fb0e58f55aa0..eed143c84f7d 100644 --- a/build/wix/Localization/mixxx_pt-BR.wxl +++ b/build/wix/Localization/mixxx_pt-BR.wxl @@ -26,7 +26,7 @@ A mesma ou melhor versão deste produto já está instalada. Você precisa instalar a versão 64-bit desse produto no Windows 64-bit. Você precisa instalar a versão 32-bit desse produto no Windows 32-bit. - Você está prestes a instalar a versão 32-bit em um sistema operacional 64-bit. Nós recomendamos usar uma versão 64-bit para melhor performance. Você pode baixar o pacote de instalação 64-bit de http://mixxx.org/download/ + Você está prestes a instalar a versão 32-bit em um sistema operacional 64-bit. Nós recomendamos usar uma versão 64-bit para melhor performance. Você pode baixar o pacote de instalação 64-bit de http://mixxx.org/download/ Você está instalando o Mixxx em um sistema operacional desatualizado. Algumas funções podem não funcionar corretamente ou nem funcionar. Nós recomendamos atualizar o seu sistema operacional. Você está prestes a instalar a versão 32-bit mas uma versão 64-bit já está instalada. Isso pode levar a comportamento indesejado. Por favor desinstale a versão existente do Mixxx primeiro, ou baixe o pacote de instalação 64-bit para atualizar (a menos que você saiba exatamente o que você está fazendo.) Você está prestes a instalar a versão 64-bit mas uma versão 32-bit já está instalada. Isso pode levar a comportamento indesejado. Por favor desinstale a versão existente do Mixxx primeiro, ou baixe o pacote de instalação 32-bit para atualizar (a menos que você saiba exatamente o que você está fazendo.) @@ -59,32 +59,32 @@ Previous version Setup Help /install | /repair | /uninstall | /layout [directory] - installs, repairs, uninstalls or creates a complete local copy of the bundle in directory. Install is the default. /passive | /quiet - displays minimal user interface with no prompts or displays no user interface and no prompts. By default user interface and all prompts are displayed. /norestart - suppress any attempts to restart. By default user interface will prompt before restart. /log log.txt - logs to a specific file. By default a log file is created in %TEMP%. - &Close - Welcome + &Fechar + Bem-vindo Setup will install Mixxx on your computer. It will first install required third party libraries, then Mixxx itself. Click Install to continue or Close to exit. - Version [WixBundleVersion] - &Options - &Install - &Close + Versão [WixBundleVersion] + &Opções + &Instalar + &Fechar Setup Options Install location: &Browse &OK - &Cancel + &Cancelar Files In Use The following applications are using files that need to be updated: Close the &applications and attempt to restart them. &Do not close applications. A reboot will be required. &OK - &Cancel + &Cancelar Setup Progress Processing: Initializing... - &Cancel + &Cancelar Modify Setup &Repair &Uninstall - &Close + &Fechar Setup Successful Mixxx installation has been successful Mixxx repair has been successful @@ -92,7 +92,7 @@ &Launch You must restart your computer before you can use the software. &Restart - &Close + &Fechar Setup Failed Mixxx installation failed Mixxx repair failed @@ -100,5 +100,5 @@ One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the <a href="#">log file</a>. You must restart your computer to complete the rollback of the software. &Restart - &Close + &Fechar diff --git a/build/wix/Localization/mixxx_pt-PT.wxl b/build/wix/Localization/mixxx_pt-PT.wxl index 5c0eea61b406..bae1f5b17aca 100644 --- a/build/wix/Localization/mixxx_pt-PT.wxl +++ b/build/wix/Localization/mixxx_pt-PT.wxl @@ -22,11 +22,11 @@ - Este produto requer o Windows 7 ou superior. + Este produto necessita do Windows 7 ou superior. Já está instalada esta versão ou uma mais recente deste programa. Tem de instalar a versão 64-bit deste produto no Windows de 64-bit. Tem de instalar a versão 32-bit deste produto no Windows de 32-bit. - Está prestes a instalar a versão 32-bit num sistema operativo de 64-bit. É recomendável usar a versão 64-bit para obter um melhor desempenho. Pode transferir o pacote de instalação de 64-bit a partir de http://mixxx.org/download/ + Está prestes a instalar a versão 32-bit num sistema operativo de 64-bit. Recomendamos a utilização da versão de 64-bit para um melhor desempenho. Pode descarregar o pacote de instalação de 64-bit em http://mixxx.org/download/ Está a instalar o Mixxx num sistema operativo desatualizado. Algumas funcionalidade poderão não funcionar corretamente. É recomendável atualizar o seu sistema operativo. Está prestes a instalar a versão de 32-bit mas a de 64-bit já está instalada. Isto pode resultar num comportamento indesejado. Por favor, desinstale a versão do Mixxx existente primeiro, ou transfira a versão de 64-bit para atualizar (a não ser que realmente saiba o que está a fazer.) Está prestes a instalar a versão de 64-bit mas a de 32-bit já está instalada. Isto pode resultar num comportamento indesejado. Por favor, desinstale a versão do Mixxx existente primeiro, ou transfira a versão de 32-bit para atualizar (a não ser que realmente saiba o que está a fazer.) diff --git a/build/wix/Localization/mixxx_ro-RO.wxl b/build/wix/Localization/mixxx_ro-RO.wxl index 274e7b189619..12c783ab05ce 100644 --- a/build/wix/Localization/mixxx_ro-RO.wxl +++ b/build/wix/Localization/mixxx_ro-RO.wxl @@ -26,7 +26,7 @@ Aceiaşi sau o versiune mai nouă a acestui produs este deja instalată. Trebuie să instalaţi versiunea produsului pe 64-biţi pentru Windows. Trebuie să instalaţi versiunea pe 32-biţi a acestui produs pentru Windows. - You are about to install the 32-bit version on a 64-bit operating system. We recommend using the 64-bit version for better performance. You can download the 64-bit installation package from http://mixxx.org/download/ + You are about to install the 32-bit version on a 64-bit operating system. We recommend using the 64-bit version for better performance. You can download the 64-bit installation package from http://mixxx.org/download/ Instalaţi Mixxx pe un sistem de operare expirat. Unele funcţii este posibil să nu funcţioneze corect sau deloc. Vă recomandăm să actualizaţi sistemul de operare. You are about to install the 32-bit version but a 64-bit one is already installed. This can lead to undesired behavior. Please un-install the existing Mixxx first, or download the 64-bit installation package to upgrade (unless you know exactly what you are doing.) You are about to install the 64-bit version but a 32-bit one is already installed. This can lead to undesired behavior. Please un-install the existing Mixxx first, or download the 32-bit installation package to upgrade (unless you know exactly what you are doing.) diff --git a/build/wix/Localization/mixxx_ru-RU.wxl b/build/wix/Localization/mixxx_ru-RU.wxl index 12f7757e9a6e..e77796831aae 100644 --- a/build/wix/Localization/mixxx_ru-RU.wxl +++ b/build/wix/Localization/mixxx_ru-RU.wxl @@ -26,7 +26,7 @@ Данная или выше версия продукта уже установлена. Вам необходимо установить 64-битную версию продукта на 64-битную версию Windows. Вам необходимо установить 32-битную версию продукта на 32-битную версию Windows. - Вы пытаетесь установить 32-битную версию на 64-битную версию операционной системы. Мы рекомендуем использовать 64-битную версию для увеличения производительности. Вы можете скачать 64-битную версию программы на http://mixxx.org/download/. + Вы пытаетесь установить 32-битную версию на 64-битную версию операционной системы. Мы рекомендуем использовать 64-битную версию для увеличения производительности.Вы можете скачать 64-битную версию программы на http://mixxx.org/download/. Вы установили Mixxx на операционную систему, которая более не поддерживается. Некоторые функции могут не работать или работать некорректно. Рекомендуем Вам обновить операционную систему. Вы пытаетесь установить 32-битную версию, но у вас уже установлена 64-битная версия. Это может привести к нежелательным последствиям. Пожалуйста, удалите сначала установленную версию, или скачайте 64-битную версию установщика для обновления текущей версии ПО (если вы уверены в том, что делаете.) Вы пытаетесь установить 64-битную версию, но у вас уже установлена 32-битная версия. Это может привести к нежелательным последствиям. Пожалуйста, удалите сначала установленную версию, или скачайте 32-битную версию установщика для обновления текущей версии ПО (если вы уверены в том, что делаете.) @@ -53,7 +53,7 @@ Файлы, позволяющие Mixxx отображать интерфейс на альтернативных языках, нежели US английский. - [WixBundleName] Setup + [WixBundleName] Установка [WixBundleName] Вы уверены, что хотите отменить? Предыдущая версия @@ -61,44 +61,44 @@ /install | /repair | /uninstall | /layout [directory] - устанавливает, восстанавливает, удаляет или создает полную локальную копию пакета в каталог. Установка (/install) включена по умолчанию. /passive | /quiet - показывает минималистичный пользовательский интерфейс без запросов параметров или не показывает пользовательский интерфейс вообще и без параметров. По умолчанию интерфейс и параметры включены. /norestart - подавляет попытки перезапуска. По умолчанию будет выводиться окно информирования перед перезагрузкой. /log log.txt - лог в отдельный файл. По умолчанию лог пишется по пути %TEMP%. &Закрыть Добро пожаловать - Setup will install Mixxx on your computer. It will first install required third party libraries, then Mixxx itself. Click Install to continue or Close to exit. - Version [WixBundleVersion] - &Options - &Install + Программа установки установит Mixxx на ваш компьютер. Сначала он установит необходимые сторонние библиотеки, а затем сам Mixxx. Нажмите кнопку Установить для продолжения или закрыть для выхода. + Версия [WixBundleVersion] + &Параметры + &Установить &Закрыть - Setup Options - Install location: - &Browse - &OK - &Cancel - Files In Use - The following applications are using files that need to be updated: - Close the &applications and attempt to restart them. - &Do not close applications. A reboot will be required. - &OK - &Cancel - Setup Progress - Processing: - Initializing... - &Cancel - Modify Setup - &Repair - &Uninstall + Параметры установки + Место установки: + &Просмотреть + &ОК + &Отмена + Используемые файлы + Следующие приложения используют файлы, которые необходимо обновить: + Закройте &приложения и попытайтесь перезапустить их. + &Не закрывайте приложение. Потребуется перезагрузка. + &ОК + &Отмена + Процесс установки + Обработка: + Инициализация... + &Отмена + Изменить установку + &Восстановление + &Удалить &Закрыть - Setup Successful - Mixxx installation has been successful - Mixxx repair has been successful - Mixxx uninstall has been successful - &Launch - You must restart your computer before you can use the software. - &Restart + Успешная установка + Установка Mixxx прошло успешно + Восстановление Mixxx прошло успешно + Удаление Mixxx прошло успешно + &Запуск + Перед использованием программного обеспечения необходимо перезагрузить компьютер. + &Перезапуск &Закрыть - Setup Failed - Mixxx installation failed - Mixxx repair failed - Mixxx uninstall failed - One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the <a href="#">log file</a>. - You must restart your computer to complete the rollback of the software. - &Restart + Ошибка установки + Установки программы Mixxx не удалось + Восстановление программы Mixxx не удалось + Удалить программу Mixxx не удалось + Одна или несколько проблем вызвали сбой установки. Устраните неполадки и повторите попытку установки. Для получения дополнительной информации см. <a href="#"> файл лога</a>. + Необходимо перезагрузить компьютер для завершения возврата программного обеспечения. + &Перезапуск &Закрыть diff --git a/build/wix/Localization/mixxx_sv-SE.wxl b/build/wix/Localization/mixxx_sv-SE.wxl index 7cb6c264252c..abbe2ebaf20f 100644 --- a/build/wix/Localization/mixxx_sv-SE.wxl +++ b/build/wix/Localization/mixxx_sv-SE.wxl @@ -26,7 +26,7 @@ Samma eller en nyare version av denna produkt är redan installerad. Du behöver installera 64-bitars-versionen utav denna produkt på 64-bitars Windows. Du behöver installera 32-bitars-versionen utav denna produkt på 32-bitars Windows. - You are about to install the 32-bit version on a 64-bit operating system. We recommend using the 64-bit version for better performance. You can download the 64-bit installation package from http://mixxx.org/download/ + You are about to install the 32-bit version on a 64-bit operating system. We recommend using the 64-bit version for better performance. You can download the 64-bit installation package from http://mixxx.org/download/ You are installing Mixxx on an outdated operating system. Some functions may not work well or at all. We recommend upgrading your operating system. You are about to install the 32-bit version but a 64-bit one is already installed. This can lead to undesired behavior. Please un-install the existing Mixxx first, or download the 64-bit installation package to upgrade (unless you know exactly what you are doing.) You are about to install the 64-bit version but a 32-bit one is already installed. This can lead to undesired behavior. Please un-install the existing Mixxx first, or download the 32-bit installation package to upgrade (unless you know exactly what you are doing.) diff --git a/build/wix/Localization/mixxx_tr-TR.wxl b/build/wix/Localization/mixxx_tr-TR.wxl index e75649a7accc..8302700e0800 100644 --- a/build/wix/Localization/mixxx_tr-TR.wxl +++ b/build/wix/Localization/mixxx_tr-TR.wxl @@ -26,7 +26,7 @@ Bu ürünün aynı veya daha yeni bir sürümü zaten yüklü. 64-bit Windows üzerine bu ürünün 64-bit sürümünü yüklemeniz gerekmektedir. 32-bit Windows üzerine bu ürünün 32-bit sürümünü yüklemeniz gerekmektedir. - 64-bit bir işletim sistemine 32-bit sürümü yüklemek üzeresiniz. Daha iyi bir performans için 64-bit sürümü kullanmanızı öneririz. 64-bit Yükleme paketini http://mixxx.org/download/ adresinden edinebilirsiniz. + 64-bit bir işletim sistemine 32-bit sürümü yüklemek üzeresiniz. Daha iyi bir performans için 64-bit sürümü kullanmanızı öneririz. 64-bit Yükleme paketini http://mixxx.org/download/ adresinden edinebilirsiniz. Mixxx'i eski bir işletim sistemine yüklemek üzeresiniz. Bazı özellikler istendiği gibi veya hiç çalışmayabilir. İşletim sisteminizi yükseltmenizi öneririz. 32-bit sürümü yüklemek üzeresiniz ancak bir 64-bit sürüm zaten yüklü. Devam etmek istenmeyen sonuçlar doğurabilir. Lütfen önce mevcut Mixxx'i kaldırın, veya güncellemek için 64-bit yükleme paketini indirin (ne yaptığınızı tam olarak bilmiyorsanız). 64-bit sürümü yüklemek üzeresiniz ancak bir 32-bit versiyon zaten yüklü. Devam etmek istenmeyen sonuçlar doğurabilir. Lütfen önce Mixxx'i kaldırın, veya güncellemek için 32-bit yükleme paketini indirin (ne yaptığınızı tam olarak bilmiyorsanız). diff --git a/build/wix/Localization/mixxx_zh-CN.wxl b/build/wix/Localization/mixxx_zh-CN.wxl index c4a8928e0534..11440ac39ba7 100644 --- a/build/wix/Localization/mixxx_zh-CN.wxl +++ b/build/wix/Localization/mixxx_zh-CN.wxl @@ -26,7 +26,7 @@ 已安装此产品相同或更高版本。 您需要在64位Windows上安装本产品的64位版本。 您需要在32位Windows上安装本产品的32位版本。 - 您将要在64位操作系统上安装32位版本的Mixxx。 我们建议使用64位版本以获取更好的性能。 您可以从http://mixxx.org/download/ 下载64位的安装包。 + 您将要在64位操作系统上安装32位版本的Mixxx。我们建议使用64位版本以获取更好的性能。您可以从http://mixxx.org/download/ 下载64位的安装包。 您正在一个过时的操作系统上安装Mixxx。部分甚至全部功能可能无法正常工作,我们建议您升级操作系统。 您将要安装Mixxx的32位版本,但64位版本已经安装,这可能会导致超乎您意料的结果。请先卸载现有的Mixxx,或下载64位的安装包进行升级 (除非您知道自己在做什么。) 您将要安装Mixxx的64位版本,但32位版本已经安装,这可能会导致超乎您意料的结果。请先卸载现有的Mixxx,或下载64位的安装包进行升级 (除非您知道自己在做什么。) diff --git a/build/wix/Localization/mixxx_zh-TW.wxl b/build/wix/Localization/mixxx_zh-TW.wxl index 5c8f6d06f6f6..78c91ed2b591 100644 --- a/build/wix/Localization/mixxx_zh-TW.wxl +++ b/build/wix/Localization/mixxx_zh-TW.wxl @@ -26,7 +26,7 @@ 已安裝相同版本或更新版本的這種產品。 您需要在 64 位 Windows 上安裝此產品的 64 位版本。 您需要在 32 位 Windows 上安裝 32 位版本的這種產品。 - 您將要在 64 位作業系統上安裝 32 位版本。 我們推薦使用 64 位版本的更好的性能。 你可以從 HTTP://mixxx.org/download/ 下載 64 位安裝包 + 您將要在 64 位作業系統上安裝 32 位版本。我們推薦使用 64 位版本的更好的性能。你可以從 http://mixxx.org/download/ 下載 64 位安裝包 你過時的作業系統上安裝 Mixxx。好或根本,某些功能可能無法工作。我們建議升級您的作業系統。 您將要安裝的 32 位版本,但已經安裝了一個 64 位。這可能導致意外的行為。首先,請卸載現有的 Mixxx 首先,請卸載現有的 Mixxx 或下載 64 位安裝套裝軟體來升級 (除非你知道你在做什麼)。 您將要安裝 64 位版本,但已經安裝了一個 32 位。這可能導致意外的行為。首先,請卸載現有的 Mixxx 首先,請卸載現有的 Mixxx 或下載 32 位安裝套裝軟體來升級 (除非你知道你在做什麼)。 diff --git a/build/wix/Localization/po/ca-ES.po b/build/wix/Localization/po/ca-ES.po index 7e954ee51126..5bd0b6b83f59 100644 --- a/build/wix/Localization/po/ca-ES.po +++ b/build/wix/Localization/po/ca-ES.po @@ -4,12 +4,12 @@ # Ferran Pujol Camins , 2016 # Josep Maria Antolin , 2016-2017 # Josep Maria Antolin , 2016 -# S.Brandt , 2016 +# S.Brandt , 2016,2018 msgid "" msgstr "" "Project-Id-Version: Mixxx DJ Windows installer\n" -"PO-Revision-Date: 2017-09-23 22:04+0000\n" -"Last-Translator: Josep Maria Antolin \n" +"PO-Revision-Date: 2018-12-16 18:33+0000\n" +"Last-Translator: S.Brandt \n" "Language-Team: Catalan (Spain) (http://www.transifex.com/mixxx-dj-software/mixxxdj-windows-installer/language/ca_ES/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -60,10 +60,10 @@ msgstr "Heu d'instal·lar la versió de 32 bits d'aquest producte en un Windows msgctxt "x86VersionWarning" msgid "" -"You are about to install the 32-bit version on a 64-bit operating system.\r\n" -"We recommend using the 64-bit version for better performance.\r\n" -"You can download the 64-bit installation package from http://mixxx.org/download/" -msgstr "Esteu a punt d'instal·lar la versió de 32 bits en un sistema operatiu de 64 bits.\nRecomanem utilitzar la versió de 64 bits per a un millor rendiment.\nPodeu baixar l'instal·lador de la versió de 64 bits des de http://mixxx.org/download/" +"You are about to install the 32-bit version on a 64-bit operating system. We" +" recommend using the 64-bit version for better performance. You can download" +" the 64-bit installation package from http://mixxx.org/download/" +msgstr "Esteu a punt d'instal·lar la versió de 32 bits en un sistema operatiu de 64 bits. Recomanem utilitzar la versió de 64 bits per a un millor rendiment. Podeu baixar l'instal·lador de la versió de 64 bits des de http://mixxx.org/download/" msgctxt "XPWarning" msgid "" diff --git a/build/wix/Localization/po/cs-CZ.po b/build/wix/Localization/po/cs-CZ.po index 0b469b8796b8..c402726307ee 100644 --- a/build/wix/Localization/po/cs-CZ.po +++ b/build/wix/Localization/po/cs-CZ.po @@ -2,13 +2,14 @@ # Translators: # Filip Klačanský , 2018 # fri, 2016-2017 +# S.Brandt , 2018 # Sebastien BLAISOT , 2016 # Sebastien BLAISOT , 2016 msgid "" msgstr "" "Project-Id-Version: Mixxx DJ Windows installer\n" -"PO-Revision-Date: 2018-02-23 04:55+0000\n" -"Last-Translator: Filip Klačanský \n" +"PO-Revision-Date: 2018-12-16 20:48+0000\n" +"Last-Translator: S.Brandt \n" "Language-Team: Czech (Czech Republic) (http://www.transifex.com/mixxx-dj-software/mixxxdj-windows-installer/language/cs_CZ/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -59,10 +60,10 @@ msgstr "Do 32bitových Windows musíte nainstalovat 32bitovou verzi tohoto výro msgctxt "x86VersionWarning" msgid "" -"You are about to install the 32-bit version on a 64-bit operating system.\r\n" -"We recommend using the 64-bit version for better performance.\r\n" -"You can download the 64-bit installation package from http://mixxx.org/download/" -msgstr "Chystáte se nainstalovat 32bitovou verzi do 64bitového operačního systému.\nDoporučujeme použít 64bitovou verzi kvůli lepšímu výkonu.\nInstalační balíček pro 64bitový systém můžete stáhnout z http://mixxx.org/download/" +"You are about to install the 32-bit version on a 64-bit operating system. We" +" recommend using the 64-bit version for better performance. You can download" +" the 64-bit installation package from http://mixxx.org/download/" +msgstr "Chystáte se nainstalovat 32bitovou verzi do 64bitového operačního systému. Doporučujeme použít 64bitovou verzi kvůli lepšímu výkonu. Instalační balíček pro 64bitový systém můžete stáhnout z http://mixxx.org/download/" msgctxt "XPWarning" msgid "" diff --git a/build/wix/Localization/po/de-DE.po b/build/wix/Localization/po/de-DE.po index 1917e38f10a4..64314109557c 100644 --- a/build/wix/Localization/po/de-DE.po +++ b/build/wix/Localization/po/de-DE.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Mixxx DJ Windows installer\n" -"PO-Revision-Date: 2018-03-22 21:11+0000\n" +"PO-Revision-Date: 2018-12-16 18:31+0000\n" "Last-Translator: S.Brandt \n" "Language-Team: German (Germany) (http://www.transifex.com/mixxx-dj-software/mixxxdj-windows-installer/language/de_DE/)\n" "MIME-Version: 1.0\n" @@ -60,9 +60,9 @@ msgstr "Sie müssen die 32-Bit-Version dieses Produkts auf 32-Bit-Windows instal msgctxt "x86VersionWarning" msgid "" -"You are about to install the 32-bit version on a 64-bit operating system.\r\n" -"We recommend using the 64-bit version for better performance.\r\n" -"You can download the 64-bit installation package from http://mixxx.org/download/" +"You are about to install the 32-bit version on a 64-bit operating system. We" +" recommend using the 64-bit version for better performance. You can download" +" the 64-bit installation package from http://mixxx.org/download/" msgstr "Sie installieren gerade die 32-Bit-Version auf einem 64-Bit-Betriebssystem. Wir empfehlen stattdessen die 64-Bit-Version für eine bessere Performance zu installieren. Sie können das 64-Bit-Installationspaket hier herunterladen: http://mixxx.org/download/" msgctxt "XPWarning" @@ -286,7 +286,7 @@ msgstr "Initialisiere..." msgctxt "ProgressCancelButton" msgid "&Cancel" -msgstr "&Cancel" +msgstr "&Abbrechen" msgctxt "ModifyHeader" msgid "Modify Setup" diff --git a/build/wix/Localization/po/es-ES.po b/build/wix/Localization/po/es-ES.po index eb97188b571e..03661bfefb93 100644 --- a/build/wix/Localization/po/es-ES.po +++ b/build/wix/Localization/po/es-ES.po @@ -2,16 +2,18 @@ # Translators: # Jorge Marcos (Jorgeelalto) , 2016 # Jorge Marcos (Jorgeelalto) , 2016 +# Jose Manuel López , 2018 # Josep Maria Antolin , 2016-2017 # Josep Maria Antolin , 2016 # miguel angel , 2017 +# S.Brandt , 2018 # Sebastien BLAISOT , 2016 # Sebastien BLAISOT , 2016 msgid "" msgstr "" "Project-Id-Version: Mixxx DJ Windows installer\n" -"PO-Revision-Date: 2017-10-24 17:56+0000\n" -"Last-Translator: miguel angel \n" +"PO-Revision-Date: 2018-12-16 20:47+0000\n" +"Last-Translator: S.Brandt \n" "Language-Team: Spanish (Spain) (http://www.transifex.com/mixxx-dj-software/mixxxdj-windows-installer/language/es_ES/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -44,7 +46,7 @@ msgstr "Instala Mixxx" #. DO NOT BREAK LINES BECAUSE LINE BREAKS WILL SHOW UP AS-IS IN THE INTERFACE msgctxt "OS2Old" msgid "This product requires Windows 7 or above." -msgstr "Este producto requiere Windows 7 o una versión superior." +msgstr "Este producto requiere Windows 7 o superior." msgctxt "NewerInstalled" msgid "The same or a newer version of this product is already installed." @@ -62,10 +64,10 @@ msgstr "Necesita instalar la versión de 32 bits de este producto en una versió msgctxt "x86VersionWarning" msgid "" -"You are about to install the 32-bit version on a 64-bit operating system.\r\n" -"We recommend using the 64-bit version for better performance.\r\n" -"You can download the 64-bit installation package from http://mixxx.org/download/" -msgstr "Está a punto de instalar la versión de 32 bits en un sistema operativo de 64 bits.\nRecomendamos usar la versión de 64 bits para un mejor rendimiento.\nPuede descargar el instalador de la versión de 64 bits desde http://mixxx.org/download/" +"You are about to install the 32-bit version on a 64-bit operating system. We" +" recommend using the 64-bit version for better performance. You can download" +" the 64-bit installation package from http://mixxx.org/download/" +msgstr "Está a punto de instalar la versión de 32 bits en un sistema operativo de 64 bits. Recomendamos utilizar la versión de 64 bits para un mejor rendimiento. Puede descargar el paquete de instalación de 64 bits desde http://mixxx.org/download/" msgctxt "XPWarning" msgid "" diff --git a/build/wix/Localization/po/et-EE.po b/build/wix/Localization/po/et-EE.po index 0e36e781d2a1..7fc15730778f 100644 --- a/build/wix/Localization/po/et-EE.po +++ b/build/wix/Localization/po/et-EE.po @@ -1,14 +1,14 @@ # # Translators: # Laur Pärn , 2016 -# S.Brandt , 2016 +# S.Brandt , 2016,2018 # Sebastien BLAISOT , 2016 # Sebastien BLAISOT , 2016 msgid "" msgstr "" "Project-Id-Version: Mixxx DJ Windows installer\n" -"PO-Revision-Date: 2017-09-22 19:10+0000\n" -"Last-Translator: Sebastien BLAISOT \n" +"PO-Revision-Date: 2018-12-16 20:46+0000\n" +"Last-Translator: S.Brandt \n" "Language-Team: Estonian (Estonia) (http://www.transifex.com/mixxx-dj-software/mixxxdj-windows-installer/language/et_EE/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -59,10 +59,10 @@ msgstr "Sul tuleb paigaldada 32-bitine versioon sellest tootest 32-bitisele Wind msgctxt "x86VersionWarning" msgid "" -"You are about to install the 32-bit version on a 64-bit operating system.\r\n" -"We recommend using the 64-bit version for better performance.\r\n" -"You can download the 64-bit installation package from http://mixxx.org/download/" -msgstr "Sa soovid paigaldada 32-bitist versiooni 64-bitisele operatsioonisüsteemile.\nSoovitame kasutada 64-bitist versiooni parema jõudluse jaoks.\nSaate 64-bitise paigalduspaketi alla laadida aadressilt http://mixxx.org/download/" +"You are about to install the 32-bit version on a 64-bit operating system. We" +" recommend using the 64-bit version for better performance. You can download" +" the 64-bit installation package from http://mixxx.org/download/" +msgstr "Sa soovid paigaldada 32-bitist versiooni 64-bitisele operatsioonisüsteemile. Soovitame kasutada 64-bitist versiooni parema jõudluse jaoks. Saate 64-bitise paigalduspaketi alla laadida aadressilt http://mixxx.org/download/" msgctxt "XPWarning" msgid "" diff --git a/build/wix/Localization/po/fr-FR.po b/build/wix/Localization/po/fr-FR.po index f5d194f7fa02..6c9df837ea76 100644 --- a/build/wix/Localization/po/fr-FR.po +++ b/build/wix/Localization/po/fr-FR.po @@ -1,12 +1,13 @@ # # Translators: +# S.Brandt , 2018 # Sebastien BLAISOT , 2016-2017 # Sebastien BLAISOT , 2016 msgid "" msgstr "" "Project-Id-Version: Mixxx DJ Windows installer\n" -"PO-Revision-Date: 2017-09-23 22:04+0000\n" -"Last-Translator: Sebastien BLAISOT \n" +"PO-Revision-Date: 2018-12-16 18:35+0000\n" +"Last-Translator: S.Brandt \n" "Language-Team: French (France) (http://www.transifex.com/mixxx-dj-software/mixxxdj-windows-installer/language/fr_FR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -57,10 +58,10 @@ msgstr "Vous devez installer la version 32-bits de ce produit sur un Windows 32- msgctxt "x86VersionWarning" msgid "" -"You are about to install the 32-bit version on a 64-bit operating system.\r\n" -"We recommend using the 64-bit version for better performance.\r\n" -"You can download the 64-bit installation package from http://mixxx.org/download/" -msgstr "Vous installez une version 32 bits sur un système 64 bits.\r\nNous vous recommandons d'utiliser une version 64 bits pour de meilleures performances.\r\nVous pouvez télécharger l'installeur 64 bits ici : http://mixxx.org/download/" +"You are about to install the 32-bit version on a 64-bit operating system. We" +" recommend using the 64-bit version for better performance. You can download" +" the 64-bit installation package from http://mixxx.org/download/" +msgstr "Vous installez une version 32 bits sur un système 64 bits. Nous vous recommandons d'utiliser une version 64 bits pour de meilleures performances. Vous pouvez télécharger l'installeur 64 bits ici : http://mixxx.org/download/" msgctxt "XPWarning" msgid "" diff --git a/build/wix/Localization/po/it-IT.po b/build/wix/Localization/po/it-IT.po index 606953deeaa1..50ceab754f1d 100644 --- a/build/wix/Localization/po/it-IT.po +++ b/build/wix/Localization/po/it-IT.po @@ -3,14 +3,15 @@ # Damtux, 2016 # Edoardo Codeglia , 2016 # Roberto Ekesi , 2017 +# S.Brandt , 2018 # Sebastien BLAISOT , 2016 # Sebastien BLAISOT , 2016 # Damtux, 2016 msgid "" msgstr "" "Project-Id-Version: Mixxx DJ Windows installer\n" -"PO-Revision-Date: 2017-10-03 08:16+0000\n" -"Last-Translator: Roberto Ekesi \n" +"PO-Revision-Date: 2018-12-16 20:44+0000\n" +"Last-Translator: S.Brandt \n" "Language-Team: Italian (Italy) (http://www.transifex.com/mixxx-dj-software/mixxxdj-windows-installer/language/it_IT/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -61,10 +62,10 @@ msgstr "Devi installare la versione a 32-bit di questo prodotto su Windows a 32- msgctxt "x86VersionWarning" msgid "" -"You are about to install the 32-bit version on a 64-bit operating system.\r\n" -"We recommend using the 64-bit version for better performance.\r\n" -"You can download the 64-bit installation package from http://mixxx.org/download/" -msgstr "Stai per installare la versione a 32-bit su un sistema operativo a 64-bit.\nRaccomandiamo di usare la versione a 64-bit per ottenere prestazioni migliori.\nPuoi scaricare il pacchetto di installazione a 64-bit da http://mixxx.org/download/" +"You are about to install the 32-bit version on a 64-bit operating system. We" +" recommend using the 64-bit version for better performance. You can download" +" the 64-bit installation package from http://mixxx.org/download/" +msgstr "Stai per installare la versione a 32-bit su un sistema operativo a 64-bit. Raccomandiamo di usare la versione a 64-bit per ottenere prestazioni migliori. Puoi scaricare il pacchetto di installazione a 64-bit da http://mixxx.org/download/" msgctxt "XPWarning" msgid "" diff --git a/build/wix/Localization/po/mixxx.pot b/build/wix/Localization/po/mixxx.pot index e4f24d1662a6..046bc65561cd 100644 --- a/build/wix/Localization/po/mixxx.pot +++ b/build/wix/Localization/po/mixxx.pot @@ -5,7 +5,7 @@ msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -#. Programm informations +#. Programm informations msgctxt "ApplicationName" msgid "Mixxx" msgstr "" @@ -26,8 +26,8 @@ msgctxt "Comments" msgid "Installs Mixxx" msgstr "" -#. Error messages -#. DO NOT BREAK LINES BECAUSE LINE BREAKS WILL SHOW UP AS-IS IN THE INTERFACE +#. Error messages +#. DO NOT BREAK LINES BECAUSE LINE BREAKS WILL SHOW UP AS-IS IN THE INTERFACE msgctxt "OS2Old" msgid "This product requires Windows 7 or above." msgstr "" @@ -45,10 +45,7 @@ msgid "You need to install the 32-bit version of this product on 32-bit Windows. msgstr "" msgctxt "x86VersionWarning" -msgid "" -"You are about to install the 32-bit version on a 64-bit operating system.\r\n" -"We recommend using the 64-bit version for better performance.\r\n" -"You can download the 64-bit installation package from http://mixxx.org/download/" +msgid "You are about to install the 32-bit version on a 64-bit operating system. We recommend using the 64-bit version for better performance. You can download the 64-bit installation package from http://mixxx.org/download/" msgstr "" msgctxt "XPWarning" @@ -71,17 +68,17 @@ msgctxt "VCredistNotFound" msgid "Installer was not able to find Microsoft Visual C++ 2015 Redistributable on this system. This is likely an installer bug that should be reported to Mixxx developers." msgstr "" -#. Custom Warning Dialog +#. Custom Warning Dialog msgctxt "WarningDlgTitle" msgid "{\\WixUI_Font_Title}Warning" msgstr "" -#. Custom exit dialog +#. Custom exit dialog msgctxt "StartOnExit" msgid "Launch Mixxx when setup exits." msgstr "" -#. Features translations +#. Features translations msgctxt "FeatureCompleteDescription" msgid "The complete package." msgstr "" @@ -126,7 +123,7 @@ msgctxt "FeatureTranslationsDescription" msgid "Resource files that allow Mixxx to display in alternate languages, other than US english" msgstr "" -#. Bootstrapper +#. Bootstrapper msgctxt "Caption" msgid "[WixBundleName] Setup" msgstr "" diff --git a/build/wix/Localization/po/nl-NL.po b/build/wix/Localization/po/nl-NL.po index 373b668754c6..f16c59e3cdb4 100644 --- a/build/wix/Localization/po/nl-NL.po +++ b/build/wix/Localization/po/nl-NL.po @@ -3,13 +3,14 @@ # Henk Gordebeke , 2017 # Raf Van De Meirssche , 2016 # Raf Van De Meirssche , 2016 +# S.Brandt , 2018 # Sebastien BLAISOT , 2016-2017 # Sebastien BLAISOT , 2016 msgid "" msgstr "" "Project-Id-Version: Mixxx DJ Windows installer\n" -"PO-Revision-Date: 2017-09-23 22:04+0000\n" -"Last-Translator: Henk Gordebeke \n" +"PO-Revision-Date: 2018-12-16 20:43+0000\n" +"Last-Translator: S.Brandt \n" "Language-Team: Dutch (Netherlands) (http://www.transifex.com/mixxx-dj-software/mixxxdj-windows-installer/language/nl_NL/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -60,10 +61,10 @@ msgstr "Je moet de 32-bits versie van dit product installeren op een 32-bits ver msgctxt "x86VersionWarning" msgid "" -"You are about to install the 32-bit version on a 64-bit operating system.\r\n" -"We recommend using the 64-bit version for better performance.\r\n" -"You can download the 64-bit installation package from http://mixxx.org/download/" -msgstr "Je staat op het punt om de 32-bits versie te installeren op een 64-bits besturingssysteem.\nWe raden aan om de 64-bits versie te gebruiken voor betere prestaties.\nJe kunt het 64-bits installatiepakket downloaden van http://mixxx.org/download/" +"You are about to install the 32-bit version on a 64-bit operating system. We" +" recommend using the 64-bit version for better performance. You can download" +" the 64-bit installation package from http://mixxx.org/download/" +msgstr "Je staat op het punt om de 32-bits versie te installeren op een 64-bits besturingssysteem. We raden aan om de 64-bits versie te gebruiken voor betere prestaties. Je kunt het 64-bits installatiepakket downloaden van http://mixxx.org/download/" msgctxt "XPWarning" msgid "" diff --git a/build/wix/Localization/po/pl-PL.po b/build/wix/Localization/po/pl-PL.po index d2c0666c9dbf..ce0110278b1a 100644 --- a/build/wix/Localization/po/pl-PL.po +++ b/build/wix/Localization/po/pl-PL.po @@ -2,11 +2,12 @@ # Translators: # Jakub Fabijan (Felidae) , 2018 # Jan Ochwat , 2016 +# S.Brandt , 2018 msgid "" msgstr "" "Project-Id-Version: Mixxx DJ Windows installer\n" -"PO-Revision-Date: 2018-03-26 16:11+0000\n" -"Last-Translator: Jakub Fabijan (Felidae) \n" +"PO-Revision-Date: 2018-12-16 20:42+0000\n" +"Last-Translator: S.Brandt \n" "Language-Team: Polish (Poland) (http://www.transifex.com/mixxx-dj-software/mixxxdj-windows-installer/language/pl_PL/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -39,7 +40,7 @@ msgstr "Instaluje Mixxx" #. DO NOT BREAK LINES BECAUSE LINE BREAKS WILL SHOW UP AS-IS IN THE INTERFACE msgctxt "OS2Old" msgid "This product requires Windows 7 or above." -msgstr "Ten produkt wymaga Windowsa XP lub wyżsego" +msgstr "Ten produkt wymaga Windowsa 7 lub wyżsego" msgctxt "NewerInstalled" msgid "The same or a newer version of this product is already installed." @@ -57,10 +58,10 @@ msgstr "Musisz zainstalować 32-bitową wersję na 32-bitowym Windowsie." msgctxt "x86VersionWarning" msgid "" -"You are about to install the 32-bit version on a 64-bit operating system.\r\n" -"We recommend using the 64-bit version for better performance.\r\n" -"You can download the 64-bit installation package from http://mixxx.org/download/" -msgstr "Masz zamiar zainstalować wersję 32-bitową w 64-bitowym systemie operacyjnym.\nZalecane jest użycie 64-bitowej wersji dla lepszej wydajności.\nPakiet instalacji 64-bitowej można pobrać z http://mixxx.org/download/" +"You are about to install the 32-bit version on a 64-bit operating system. We" +" recommend using the 64-bit version for better performance. You can download" +" the 64-bit installation package from http://mixxx.org/download/" +msgstr "Masz zamiar zainstalować wersję 32-bitową w 64-bitowym systemie operacyjnym. Zalecane jest użycie 64-bitowej wersji dla lepszej wydajności. Pakiet instalacji 64-bitowej można pobrać z http://mixxx.org/download/" msgctxt "XPWarning" msgid "" diff --git a/build/wix/Localization/po/pt-BR.po b/build/wix/Localization/po/pt-BR.po index d9604f21b628..c6659d8e2a3b 100644 --- a/build/wix/Localization/po/pt-BR.po +++ b/build/wix/Localization/po/pt-BR.po @@ -2,13 +2,15 @@ # Translators: # Felipe Morato , 2017 # Fer22f , 2016 +# Rui , 2018 +# S.Brandt , 2018 # Sebastien BLAISOT , 2016 # Sebastien BLAISOT , 2016 msgid "" msgstr "" "Project-Id-Version: Mixxx DJ Windows installer\n" -"PO-Revision-Date: 2017-09-23 22:04+0000\n" -"Last-Translator: Sebastien BLAISOT \n" +"PO-Revision-Date: 2018-12-16 20:41+0000\n" +"Last-Translator: S.Brandt \n" "Language-Team: Portuguese (Brazil) (http://www.transifex.com/mixxx-dj-software/mixxxdj-windows-installer/language/pt_BR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -59,10 +61,10 @@ msgstr "Você precisa instalar a versão 32-bit desse produto no Windows 32-bit. msgctxt "x86VersionWarning" msgid "" -"You are about to install the 32-bit version on a 64-bit operating system.\r\n" -"We recommend using the 64-bit version for better performance.\r\n" -"You can download the 64-bit installation package from http://mixxx.org/download/" -msgstr "Você está prestes a instalar a versão 32-bit em um sistema operacional 64-bit.\nNós recomendamos usar uma versão 64-bit para melhor performance.\nVocê pode baixar o pacote de instalação 64-bit de http://mixxx.org/download/" +"You are about to install the 32-bit version on a 64-bit operating system. We" +" recommend using the 64-bit version for better performance. You can download" +" the 64-bit installation package from http://mixxx.org/download/" +msgstr "Você está prestes a instalar a versão 32-bit em um sistema operacional 64-bit. Nós recomendamos usar uma versão 64-bit para melhor performance. Você pode baixar o pacote de instalação 64-bit de http://mixxx.org/download/" msgctxt "XPWarning" msgid "" @@ -198,11 +200,11 @@ msgstr "" msgctxt "HelpCloseButton" msgid "&Close" -msgstr "" +msgstr "&Fechar" msgctxt "InstallHeader" msgid "Welcome" -msgstr "" +msgstr "Bem-vindo" msgctxt "InstallMessage" msgid "" @@ -213,19 +215,19 @@ msgstr "" msgctxt "InstallVersion" msgid "Version [WixBundleVersion]" -msgstr "" +msgstr "Versão [WixBundleVersion]" msgctxt "InstallOptionsButton" msgid "&Options" -msgstr "" +msgstr "&Opções" msgctxt "InstallInstallButton" msgid "&Install" -msgstr "" +msgstr "&Instalar" msgctxt "InstallCloseButton" msgid "&Close" -msgstr "" +msgstr "&Fechar" msgctxt "OptionsHeader" msgid "Setup Options" @@ -245,7 +247,7 @@ msgstr "" msgctxt "OptionsCancelButton" msgid "&Cancel" -msgstr "" +msgstr "&Cancelar" msgctxt "FilesInUseHeader" msgid "Files In Use" @@ -269,7 +271,7 @@ msgstr "" msgctxt "FilesInUseCancelButton" msgid "&Cancel" -msgstr "" +msgstr "&Cancelar" msgctxt "ProgressHeader" msgid "Setup Progress" @@ -285,7 +287,7 @@ msgstr "" msgctxt "ProgressCancelButton" msgid "&Cancel" -msgstr "" +msgstr "&Cancelar" msgctxt "ModifyHeader" msgid "Modify Setup" @@ -301,7 +303,7 @@ msgstr "" msgctxt "ModifyCloseButton" msgid "&Close" -msgstr "" +msgstr "&Fechar" msgctxt "SuccessHeader" msgid "Setup Successful" @@ -333,7 +335,7 @@ msgstr "" msgctxt "SuccessCloseButton" msgid "&Close" -msgstr "" +msgstr "&Fechar" msgctxt "FailureHeader" msgid "Setup Failed" @@ -368,4 +370,4 @@ msgstr "" msgctxt "FailureCloseButton" msgid "&Close" -msgstr "" +msgstr "&Fechar" diff --git a/build/wix/Localization/po/pt-PT.po b/build/wix/Localization/po/pt-PT.po index 581c35fa04c0..02558ef26b4c 100644 --- a/build/wix/Localization/po/pt-PT.po +++ b/build/wix/Localization/po/pt-PT.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Mixxx DJ Windows installer\n" -"PO-Revision-Date: 2018-10-04 08:37+0000\n" +"PO-Revision-Date: 2018-11-20 19:17+0000\n" "Last-Translator: Rui \n" "Language-Team: Portuguese (Portugal) (http://www.transifex.com/mixxx-dj-software/mixxxdj-windows-installer/language/pt_PT/)\n" "MIME-Version: 1.0\n" @@ -42,7 +42,7 @@ msgstr "Instala o Mixxx" #. DO NOT BREAK LINES BECAUSE LINE BREAKS WILL SHOW UP AS-IS IN THE INTERFACE msgctxt "OS2Old" msgid "This product requires Windows 7 or above." -msgstr "Este produto requer o Windows 7 ou superior." +msgstr "Este produto necessita do Windows 7 ou superior." msgctxt "NewerInstalled" msgid "The same or a newer version of this product is already installed." @@ -60,10 +60,10 @@ msgstr "Tem de instalar a versão 32-bit deste produto no Windows de 32-bit." msgctxt "x86VersionWarning" msgid "" -"You are about to install the 32-bit version on a 64-bit operating system.\r\n" -"We recommend using the 64-bit version for better performance.\r\n" -"You can download the 64-bit installation package from http://mixxx.org/download/" -msgstr "Está prestes a instalar a versão 32-bit num sistema operativo de 64-bit.\nÉ recomendável usar a versão 64-bit para obter um melhor desempenho.\nPode transferir o pacote de instalação de 64-bit a partir de http://mixxx.org/download/" +"You are about to install the 32-bit version on a 64-bit operating system. We" +" recommend using the 64-bit version for better performance. You can download" +" the 64-bit installation package from http://mixxx.org/download/" +msgstr "Está prestes a instalar a versão 32-bit num sistema operativo de 64-bit. Recomendamos a utilização da versão de 64-bit para um melhor desempenho. Pode descarregar o pacote de instalação de 64-bit em http://mixxx.org/download/" msgctxt "XPWarning" msgid "" diff --git a/build/wix/Localization/po/ro-RO.po b/build/wix/Localization/po/ro-RO.po index d3e4f1c01138..6d33a43fe6db 100644 --- a/build/wix/Localization/po/ro-RO.po +++ b/build/wix/Localization/po/ro-RO.po @@ -1,5 +1,6 @@ # # Translators: +# S.Brandt , 2018 # Sebastien BLAISOT , 2016 # Sebastien BLAISOT , 2016 # titus , 2016 @@ -7,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: Mixxx DJ Windows installer\n" -"PO-Revision-Date: 2017-09-23 22:04+0000\n" -"Last-Translator: Sebastien BLAISOT \n" +"PO-Revision-Date: 2018-12-16 20:39+0000\n" +"Last-Translator: S.Brandt \n" "Language-Team: Romanian (Romania) (http://www.transifex.com/mixxx-dj-software/mixxxdj-windows-installer/language/ro_RO/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -59,9 +60,9 @@ msgstr "Trebuie să instalaţi versiunea pe 32-biţi a acestui produs pentru Win msgctxt "x86VersionWarning" msgid "" -"You are about to install the 32-bit version on a 64-bit operating system.\r\n" -"We recommend using the 64-bit version for better performance.\r\n" -"You can download the 64-bit installation package from http://mixxx.org/download/" +"You are about to install the 32-bit version on a 64-bit operating system. We" +" recommend using the 64-bit version for better performance. You can download" +" the 64-bit installation package from http://mixxx.org/download/" msgstr "" msgctxt "XPWarning" diff --git a/build/wix/Localization/po/ru-RU.po b/build/wix/Localization/po/ru-RU.po index 015d284565fe..6e292396b916 100644 --- a/build/wix/Localization/po/ru-RU.po +++ b/build/wix/Localization/po/ru-RU.po @@ -1,5 +1,7 @@ # # Translators: +# Artem, 2018 +# S.Brandt , 2018 # Sebastien BLAISOT , 2016 # Sebastien BLAISOT , 2016 # Владимир Новиков , 2016 @@ -8,8 +10,8 @@ msgid "" msgstr "" "Project-Id-Version: Mixxx DJ Windows installer\n" -"PO-Revision-Date: 2017-09-23 22:04+0000\n" -"Last-Translator: Владимир Новиков \n" +"PO-Revision-Date: 2018-12-16 18:34+0000\n" +"Last-Translator: S.Brandt \n" "Language-Team: Russian (Russia) (http://www.transifex.com/mixxx-dj-software/mixxxdj-windows-installer/language/ru_RU/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -60,10 +62,10 @@ msgstr "Вам необходимо установить 32-битную вер msgctxt "x86VersionWarning" msgid "" -"You are about to install the 32-bit version on a 64-bit operating system.\r\n" -"We recommend using the 64-bit version for better performance.\r\n" -"You can download the 64-bit installation package from http://mixxx.org/download/" -msgstr "Вы пытаетесь установить 32-битную версию на 64-битную версию операционной системы.\nМы рекомендуем использовать 64-битную версию для увеличения производительности.\nВы можете скачать 64-битную версию программы на http://mixxx.org/download/." +"You are about to install the 32-bit version on a 64-bit operating system. We" +" recommend using the 64-bit version for better performance. You can download" +" the 64-bit installation package from http://mixxx.org/download/" +msgstr "Вы пытаетесь установить 32-битную версию на 64-битную версию операционной системы. Мы рекомендуем использовать 64-битную версию для увеличения производительности.Вы можете скачать 64-битную версию программы на http://mixxx.org/download/." msgctxt "XPWarning" msgid "" @@ -165,11 +167,11 @@ msgstr "Файлы, позволяющие Mixxx отображать интер #. Bootstrapper msgctxt "Caption" msgid "[WixBundleName] Setup" -msgstr "" +msgstr "[WixBundleName] Установка" msgctxt "Title" msgid "[WixBundleName]" -msgstr "" +msgstr "[WixBundleName]" msgctxt "ConfirmCancelMessage" msgid "Are you sure you want to cancel?" @@ -210,19 +212,19 @@ msgid "" "Setup will install Mixxx on your computer.\n" "It will first install required third party libraries, then Mixxx itself.\n" "Click Install to continue or Close to exit." -msgstr "" +msgstr "Программа установки установит Mixxx на ваш компьютер.\nСначала он установит необходимые сторонние библиотеки, а затем сам Mixxx.\nНажмите кнопку Установить для продолжения или закрыть для выхода." msgctxt "InstallVersion" msgid "Version [WixBundleVersion]" -msgstr "" +msgstr "Версия [WixBundleVersion]" msgctxt "InstallOptionsButton" msgid "&Options" -msgstr "" +msgstr "&Параметры" msgctxt "InstallInstallButton" msgid "&Install" -msgstr "" +msgstr "&Установить" msgctxt "InstallCloseButton" msgid "&Close" @@ -230,75 +232,75 @@ msgstr "&Закрыть" msgctxt "OptionsHeader" msgid "Setup Options" -msgstr "" +msgstr "Параметры установки" msgctxt "OptionsLocationLabel" msgid "Install location:" -msgstr "" +msgstr "Место установки:" msgctxt "OptionsBrowseButton" msgid "&Browse" -msgstr "" +msgstr "&Просмотреть" msgctxt "OptionsOkButton" msgid "&OK" -msgstr "" +msgstr "&ОК" msgctxt "OptionsCancelButton" msgid "&Cancel" -msgstr "" +msgstr "&Отмена" msgctxt "FilesInUseHeader" msgid "Files In Use" -msgstr "" +msgstr "Используемые файлы" msgctxt "FilesInUseLabel" msgid "The following applications are using files that need to be updated:" -msgstr "" +msgstr "Следующие приложения используют файлы, которые необходимо обновить:" msgctxt "FilesInUseCloseRadioButton" msgid "Close the &applications and attempt to restart them." -msgstr "" +msgstr "Закройте &приложения и попытайтесь перезапустить их." msgctxt "FilesInUseDontCloseRadioButton" msgid "&Do not close applications. A reboot will be required." -msgstr "" +msgstr "&Не закрывайте приложение. Потребуется перезагрузка." msgctxt "FilesInUseOkButton" msgid "&OK" -msgstr "" +msgstr "&ОК" msgctxt "FilesInUseCancelButton" msgid "&Cancel" -msgstr "" +msgstr "&Отмена" msgctxt "ProgressHeader" msgid "Setup Progress" -msgstr "" +msgstr "Процесс установки" msgctxt "ProgressLabel" msgid "Processing:" -msgstr "" +msgstr "Обработка:" msgctxt "OverallProgressPackageText" msgid "Initializing..." -msgstr "" +msgstr "Инициализация..." msgctxt "ProgressCancelButton" msgid "&Cancel" -msgstr "" +msgstr "&Отмена" msgctxt "ModifyHeader" msgid "Modify Setup" -msgstr "" +msgstr "Изменить установку" msgctxt "ModifyRepairButton" msgid "&Repair" -msgstr "" +msgstr "&Восстановление " msgctxt "ModifyUninstallButton" msgid "&Uninstall" -msgstr "" +msgstr "&Удалить" msgctxt "ModifyCloseButton" msgid "&Close" @@ -306,31 +308,31 @@ msgstr "&Закрыть" msgctxt "SuccessHeader" msgid "Setup Successful" -msgstr "" +msgstr "Успешная установка" msgctxt "SuccessInstallHeader" msgid "Mixxx installation has been successful" -msgstr "" +msgstr "Установка Mixxx прошло успешно" msgctxt "SuccessRepairHeader" msgid "Mixxx repair has been successful" -msgstr "" +msgstr "Восстановление Mixxx прошло успешно" msgctxt "SuccessUninstallHeader" msgid "Mixxx uninstall has been successful" -msgstr "" +msgstr "Удаление Mixxx прошло успешно" msgctxt "SuccessLaunchButton" msgid "&Launch" -msgstr "" +msgstr "&Запуск" msgctxt "SuccessRestartText" msgid "You must restart your computer before you can use the software." -msgstr "" +msgstr "Перед использованием программного обеспечения необходимо перезагрузить компьютер." msgctxt "SuccessRestartButton" msgid "&Restart" -msgstr "" +msgstr "&Перезапуск" msgctxt "SuccessCloseButton" msgid "&Close" @@ -338,34 +340,34 @@ msgstr "&Закрыть" msgctxt "FailureHeader" msgid "Setup Failed" -msgstr "" +msgstr "Ошибка установки" msgctxt "FailureInstallHeader" msgid "Mixxx installation failed" -msgstr "" +msgstr "Установки программы Mixxx не удалось" msgctxt "FailureRepairHeader" msgid "Mixxx repair failed" -msgstr "" +msgstr "Восстановление программы Mixxx не удалось" msgctxt "FailureUninstallHeader" msgid "Mixxx uninstall failed" -msgstr "" +msgstr "Удалить программу Mixxx не удалось" msgctxt "FailureHyperlinkLogText" msgid "" "One or more issues caused the setup to fail. Please fix the issues and then " "retry setup. For more information see the log file." -msgstr "" +msgstr "Одна или несколько проблем вызвали сбой установки. Устраните неполадки и повторите попытку установки. Для получения дополнительной информации см. файл лога." msgctxt "FailureRestartText" msgid "" "You must restart your computer to complete the rollback of the software." -msgstr "" +msgstr "Необходимо перезагрузить компьютер для завершения возврата программного обеспечения." msgctxt "FailureRestartButton" msgid "&Restart" -msgstr "" +msgstr "&Перезапуск" msgctxt "FailureCloseButton" msgid "&Close" diff --git a/build/wix/Localization/po/sv-SE.po b/build/wix/Localization/po/sv-SE.po index 283e5c708590..1e57bf3f74f7 100644 --- a/build/wix/Localization/po/sv-SE.po +++ b/build/wix/Localization/po/sv-SE.po @@ -1,11 +1,12 @@ # # Translators: # Henrik Mattsson-Mårn , 2017 +# S.Brandt , 2018 msgid "" msgstr "" "Project-Id-Version: Mixxx DJ Windows installer\n" -"PO-Revision-Date: 2017-12-22 20:22+0000\n" -"Last-Translator: Henrik Mattsson-Mårn \n" +"PO-Revision-Date: 2018-12-16 20:37+0000\n" +"Last-Translator: S.Brandt \n" "Language-Team: Swedish (Sweden) (http://www.transifex.com/mixxx-dj-software/mixxxdj-windows-installer/language/sv_SE/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -56,9 +57,9 @@ msgstr "Du behöver installera 32-bitars-versionen utav denna produkt på 32-bit msgctxt "x86VersionWarning" msgid "" -"You are about to install the 32-bit version on a 64-bit operating system.\r\n" -"We recommend using the 64-bit version for better performance.\r\n" -"You can download the 64-bit installation package from http://mixxx.org/download/" +"You are about to install the 32-bit version on a 64-bit operating system. We" +" recommend using the 64-bit version for better performance. You can download" +" the 64-bit installation package from http://mixxx.org/download/" msgstr "" msgctxt "XPWarning" diff --git a/build/wix/Localization/po/tr-TR.po b/build/wix/Localization/po/tr-TR.po index b37c0668b9de..0b8df1305f6a 100644 --- a/build/wix/Localization/po/tr-TR.po +++ b/build/wix/Localization/po/tr-TR.po @@ -2,11 +2,12 @@ # Translators: # Salih Tekin , 2017 # Salih Tekin , 2017 +# S.Brandt , 2018 msgid "" msgstr "" "Project-Id-Version: Mixxx DJ Windows installer\n" -"PO-Revision-Date: 2017-09-22 19:25+0000\n" -"Last-Translator: Sebastien BLAISOT \n" +"PO-Revision-Date: 2018-12-16 20:36+0000\n" +"Last-Translator: S.Brandt \n" "Language-Team: Turkish (Turkey) (http://www.transifex.com/mixxx-dj-software/mixxxdj-windows-installer/language/tr_TR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -57,10 +58,10 @@ msgstr "32-bit Windows üzerine bu ürünün 32-bit sürümünü yüklemeniz ger msgctxt "x86VersionWarning" msgid "" -"You are about to install the 32-bit version on a 64-bit operating system.\r\n" -"We recommend using the 64-bit version for better performance.\r\n" -"You can download the 64-bit installation package from http://mixxx.org/download/" -msgstr "64-bit bir işletim sistemine 32-bit sürümü yüklemek üzeresiniz.\nDaha iyi bir performans için 64-bit sürümü kullanmanızı öneririz.\n64-bit Yükleme paketini http://mixxx.org/download/ adresinden edinebilirsiniz." +"You are about to install the 32-bit version on a 64-bit operating system. We" +" recommend using the 64-bit version for better performance. You can download" +" the 64-bit installation package from http://mixxx.org/download/" +msgstr "64-bit bir işletim sistemine 32-bit sürümü yüklemek üzeresiniz. Daha iyi bir performans için 64-bit sürümü kullanmanızı öneririz. 64-bit Yükleme paketini http://mixxx.org/download/ adresinden edinebilirsiniz." msgctxt "XPWarning" msgid "" diff --git a/build/wix/Localization/po/zh-CN.po b/build/wix/Localization/po/zh-CN.po index 2408a7f2f8f8..8bdf07555b88 100644 --- a/build/wix/Localization/po/zh-CN.po +++ b/build/wix/Localization/po/zh-CN.po @@ -4,14 +4,15 @@ # liushuyu011 , 2017 # liushuyu011 , 2017 # Nya Chan (喵酱) , 2016 +# S.Brandt , 2018 # Sebastien BLAISOT , 2016 # Sebastien BLAISOT , 2016 # zwpwjwtz , 2017 msgid "" msgstr "" "Project-Id-Version: Mixxx DJ Windows installer\n" -"PO-Revision-Date: 2017-10-22 14:24+0000\n" -"Last-Translator: zwpwjwtz \n" +"PO-Revision-Date: 2018-12-16 20:35+0000\n" +"Last-Translator: S.Brandt \n" "Language-Team: Chinese (China) (http://www.transifex.com/mixxx-dj-software/mixxxdj-windows-installer/language/zh_CN/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -62,10 +63,10 @@ msgstr "您需要在32位Windows上安装本产品的32位版本。" msgctxt "x86VersionWarning" msgid "" -"You are about to install the 32-bit version on a 64-bit operating system.\r\n" -"We recommend using the 64-bit version for better performance.\r\n" -"You can download the 64-bit installation package from http://mixxx.org/download/" -msgstr "您将要在64位操作系统上安装32位版本的Mixxx。\n我们建议使用64位版本以获取更好的性能。\n您可以从http://mixxx.org/download/ 下载64位的安装包。" +"You are about to install the 32-bit version on a 64-bit operating system. We" +" recommend using the 64-bit version for better performance. You can download" +" the 64-bit installation package from http://mixxx.org/download/" +msgstr "您将要在64位操作系统上安装32位版本的Mixxx。我们建议使用64位版本以获取更好的性能。您可以从http://mixxx.org/download/ 下载64位的安装包。" msgctxt "XPWarning" msgid "" diff --git a/build/wix/Localization/po/zh-TW.po b/build/wix/Localization/po/zh-TW.po index 57e13032fe7d..4f7f23f53ac0 100644 --- a/build/wix/Localization/po/zh-TW.po +++ b/build/wix/Localization/po/zh-TW.po @@ -1,15 +1,16 @@ # # Translators: +# S.Brandt , 2018 # Sebastien BLAISOT , 2016 # Sebastien BLAISOT , 2016 -# 尚齊 吳 , 2018 +# 尚齊 吳, 2018 # 羅廷中 , 2017 # 鬼迪 陳 , 2016 msgid "" msgstr "" "Project-Id-Version: Mixxx DJ Windows installer\n" -"PO-Revision-Date: 2018-08-28 19:42+0000\n" -"Last-Translator: 尚齊 吳 \n" +"PO-Revision-Date: 2018-12-16 20:33+0000\n" +"Last-Translator: S.Brandt \n" "Language-Team: Chinese (Taiwan) (http://www.transifex.com/mixxx-dj-software/mixxxdj-windows-installer/language/zh_TW/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -60,10 +61,10 @@ msgstr "您需要在 32 位 Windows 上安裝 32 位版本的這種產品。" msgctxt "x86VersionWarning" msgid "" -"You are about to install the 32-bit version on a 64-bit operating system.\r\n" -"We recommend using the 64-bit version for better performance.\r\n" -"You can download the 64-bit installation package from http://mixxx.org/download/" -msgstr "您將要在 64 位作業系統上安裝 32 位版本。\r\n我們推薦使用 64 位版本的更好的性能。\r\n你可以從 HTTP://mixxx.org/download/ 下載 64 位安裝包" +"You are about to install the 32-bit version on a 64-bit operating system. We" +" recommend using the 64-bit version for better performance. You can download" +" the 64-bit installation package from http://mixxx.org/download/" +msgstr "您將要在 64 位作業系統上安裝 32 位版本。我們推薦使用 64 位版本的更好的性能。你可以從 http://mixxx.org/download/ 下載 64 位安裝包" msgctxt "XPWarning" msgid "" diff --git a/lib/soundtouch-2.1.0.tar.bz2 b/lib/soundtouch-2.1.0.tar.bz2 deleted file mode 100644 index cfca78a0be5c..000000000000 Binary files a/lib/soundtouch-2.1.0.tar.bz2 and /dev/null differ diff --git a/lib/soundtouch/BPMDetect.cpp b/lib/soundtouch/BPMDetect.cpp index 01202f0e8071..3ecda49f616a 100644 --- a/lib/soundtouch/BPMDetect.cpp +++ b/lib/soundtouch/BPMDetect.cpp @@ -186,8 +186,10 @@ BPMDetect::BPMDetect(int numChannels, int aSampleRate) : // choose decimation factor so that result is approx. 1000 Hz decimateBy = sampleRate / TARGET_SRATE; - assert(decimateBy > 0); - assert(INPUT_BLOCK_SIZE < decimateBy * DECIMATED_BLOCK_SIZE); + if ((decimateBy <= 0) || (decimateBy * DECIMATED_BLOCK_SIZE < INPUT_BLOCK_SIZE)) + { + ST_THROW_RT_ERROR("Too small samplerate"); + } // Calculate window length & starting item according to desired min & max bpms windowLen = (60 * sampleRate) / (decimateBy * MIN_BPM); diff --git a/lib/soundtouch/README.html b/lib/soundtouch/README.html index 93734321e0f3..84a534583151 100644 --- a/lib/soundtouch/README.html +++ b/lib/soundtouch/README.html @@ -1,914 +1,923 @@ - - - - SoundTouch library README - - - - - - - -
-

SoundTouch audio processing library v2.1

-

SoundTouch library Copyright © Olli Parviainen 2001-2018

-
-

1. Introduction

-

SoundTouch is an open-source audio processing library that allows -changing the sound tempo, pitch and playback rate parameters -independently from each other, i.e.:

-
    -
  • Sound tempo can be increased or decreased while maintaining the -original pitch
  • -
  • Sound pitch can be increased or decreased while maintaining the -original tempo
  • -
  • Change playback rate that affects both tempo and pitch at the -same time
  • -
  • Choose any combination of tempo/pitch/rate
  • -
-

1.1 Contact information

-

Author email: oparviai 'at' iki.fi

-

SoundTouch WWW page: http://soundtouch.surina.net

-

SoundTouch git repository: https://gitlab.com/soundtouch/soundtouch.git

-
-

2. Compiling SoundTouch

-

Before compiling, notice that you can choose the sample data format if it's -desirable to use floating point sample data instead of 16bit integers. See -section "sample data format" for more information.

-

Also notice that SoundTouch can use OpenMP instructions for parallel -computation to accelerate the runtime processing speed in multi-core systems, -however, these improvements need to be separately enabled before compiling. See -OpenMP notes in Chapter 3 below.

-

2.1. Building in Microsoft Windows

-

Project files for Microsoft Visual C++ are supplied with the source -code package. Go to Microsoft WWW page to download - -Microsoft Visual Studio Express version for free. -

-

To build the binaries with Visual C++ compiler, either run -"make-win.bat" script, or open the appropriate project files in source -code directories with Visual Studio. The final executable will appear -under the "SoundTouch\bin" directory. If using the Visual Studio IDE -instead of the make-win.bat script, directories bin and lib may need to -be created manually to the SoundTouch package root for the final -executables. The make-win.bat script creates these directories -automatically.

-

C# example: The source code package includes also a C# example - application for Windows that shows how to invoke SoundTouch.dll - dynamic-load library for processing mp3 audio. -

OpenMP NOTE: If activating the OpenMP parallel computing in -the compilation, the target program will require additional vcomp dll library to -properly run. In Visual C++ 9.0 these libraries can be found in the following -folders.

-
    -
  • x86 32bit: C:\Program Files (x86)\Microsoft Visual Studio - 9.0\VC\redist\x86\Microsoft.VC90.OPENMP\vcomp90.dll
  • -
  • x64 64bit: C:\Program Files (x86)\Microsoft Visual Studio - 9.0\VC\redist\amd64\Microsoft.VC90.OPENMP\vcomp90.dll
  • -
-

In Visual Studio 2008, a SP1 version may be required for these libraries. In -other VC++ versions the required library will be expectedly found in similar -"redist" location.

-

Notice that as minor demonstration of a "dll hell" phenomenon both the 32-bit -and 64-bit version of vcomp90.dll have the same filename but different contents, -thus choose the proper version to allow the program start.

-

2.2. Building in Gnu platforms

-

The SoundTouch library compiles in practically any platform -supporting GNU compiler (GCC) tools. SoundTouch requires GCC version 4.3 or later.

-

To build and install the binaries, run the following commands in -/soundtouch directory:

- - - - - - - - - - - - - - - - - - - -
-
./bootstrap  -
-
Creates "configure" file with -local autoconf/automake toolset.
-
-
./configure  -
-
-

Configures the SoundTouch package for the local environment. -Notice that "configure" file is not available before running the -"./bootstrap" command as above.
-

-
-
make         -
-
-

Builds the SoundTouch library & SoundStretch utility. You can - optionally add "-j" switch after "make" to speed up the compilation in - multi-core systems.

-
-
make install -
-
-

Installs the SoundTouch & BPM libraries to /usr/local/lib -and SoundStretch utility to /usr/local/bin. Please notice that -'root' privileges may be required to install the binaries to the -destination locations.

-
-

2.2.1 Required GNU tools

-

Bash shell, GNU C++ compiler, libtool, autoconf and automake tools -are required for compiling the SoundTouch library. These are usually -included with the GNU/Linux distribution, but if not, install these -packages first. For example, Ubuntu Linux can acquire and install -these with the following command:

-
sudo apt-get install automake autoconf libtool build-essential
-

2.2.2 Problems with GCC compiler compatibility

-

At the release time the SoundTouch package has been tested to -compile in GNU/Linux platform. However, If you have problems getting the -SoundTouch library compiled, try disabling optimizations that are specific for -x86 processors by running ./configure script with switch -

-
--enable-x86-optimizations=no
-
- -Alternatively, if you don't use GNU Configure system, edit file "include/STTypes.h" -directly and remove the following definition:
-
#define SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS 1
-
- -

2.2.3 Compiling Shared Library / DLL version in Cygwin

-

- The GNU compilation does not automatically create a shared-library version of - SoundTouch (.so or .dll). If such is desired, then you can create it as follows - after running the usual compilation:

-
-
g++ -shared -static -DDLL_EXPORTS -I../../include -o SoundTouch.dll \
-     SoundTouchDLL.cpp ../SoundTouch/.libs/libSoundTouch.a
-sstrip SoundTouch.dll
-
- -

2.3. Building in Android

-

Android compilation instructions are within the - source code package, see file "source/Android-lib/README-SoundTouch-Android.html" - in the source code package.

-

The Android compilation automatically builds separate .so library binaries -for ARM, X86 and MIPS processor architectures. For optimal device support, -include all these .so library binaries into the Android .apk application -package, so the target Android device can automatically choose the proper -library binary version to use.

-

The source/Android-lib folder includes also an Android -example application that processes WAV audio files using SoundTouch library in -Android devices.

- -
-

3. About implementation & Usage tips

3.1. Supported sample data formats

-

The sample data format can be chosen between 16bit signed integer -and 32bit floating point values. The default is 32bit floating point format, -which will also provide slightly better sound quality over the integer format.

-

In Windows environment, the sample data format is chosen in file -"STTypes.h" by choosing one of the following defines:

-
    -
  • #define -SOUNDTOUCH_INTEGER_SAMPLES for 16bit signed integer
  • -
  • #define SOUNDTOUCH_FLOAT_SAMPLES for 32bit floating -point
  • -
-

In GNU environment, the floating sample format is used by default, -but integer sample format can be chosen by giving the following switch -to the configure script:

-
-
./configure --enable-integer-samples
-
-

The sample data can have either single (mono) or double (stereo) -audio channel. Stereo data is interleaved so that every other data -value is for left channel and every second for right channel. Notice -that while it'd be possible in theory to process stereo sound as two -separate mono channels, this isn't recommended because processing the -channels separately would result in losing the phase coherency between -the channels, which consequently would ruin the stereo effect.

-

Sample rates between 8000-48000H are supported.

-

3.2. Processing latency

-

The processing and latency constraints of the SoundTouch library are:

-
    -
  • Input/output processing latency for the SoundTouch processor is -around 100 ms. This is when time-stretching is used. If the rate -transposing effect alone is used, the latency requirement is much -shorter, see section 'About algorithms'.
  • -
  • Processing CD-quality sound (16bit stereo sound with 44100H -sample rate) in real-time or faster is possible starting from -processors equivalent to Intel Pentium 133Mh or better, if using the -"quick" processing algorithm. If not using the "quick" mode or if -floating point sample data are being used, several times more CPU power -is typically required.
  • -
-

3.3. About algorithms

-

SoundTouch provides three seemingly independent effects: tempo, -pitch and playback rate control. These three controls are implemented -as combination of two primary effects, sample rate transposing -and time-stretching.

-

Sample rate transposing affects both the audio stream -duration and pitch. It's implemented simply by converting the original -audio sample stream to the desired duration by interpolating from -the original audio samples. In SoundTouch, linear interpolation with -anti-alias filtering is used. Theoretically a higher-order -interpolation provide better result than 1st order linear -interpolation, but in audio application linear interpolation together -with anti-alias filtering performs subjectively about as well as -higher-order filtering would.

-

Time-stretching means changing the audio stream duration -without affecting it's pitch. SoundTouch uses WSOLA-like -time-stretching routines that operate in the time domain. Compared to -sample rate transposing, time-stretching is a much heavier operation -and also requires a longer processing "window" of sound samples used by -the processing algorithm, thus increasing the algorithm input/output -latency. Typical i/o latency for the SoundTouch time-stretch algorithm -is around 100 ms.

-

Sample rate transposing and time-stretching are then used together -to produce the tempo, pitch and rate controls:

-
    -
  • 'Tempo' control is implemented purely by -time-stretching.
  • -
  • 'Rate' control is implemented purely by sample -rate transposing.
  • -
  • 'Pitch' control is implemented as a -combination of time-stretching and sample rate transposing. For -example, to increase pitch the audio stream is first time-stretched to -longer duration (without affecting pitch) and then transposed back to -original duration by sample rate transposing, which simultaneously -reduces duration and increases pitch. The result is original duration -but increased pitch.
  • -
-

3.4 Tuning the algorithm parameters

-

The time-stretch algorithm has few parameters that can be tuned to -optimize sound quality for certain application. The current default -parameters have been chosen by iterative if-then analysis (read: "trial -and error") to obtain best subjective sound quality in pop/rock music -processing, but in applications processing different kind of sound the -default parameter set may result into a sub-optimal result.

-

The time-stretch algorithm default parameter values are set by the -following #defines in file "TDStretch.h":

-
-
#define DEFAULT_SEQUENCE_MS     AUTOMATIC
#define DEFAULT_SEEKWINDOW_MS AUTOMATIC
#define DEFAULT_OVERLAP_MS 8
-
-

These parameters affect to the time-stretch algorithm as follows:

-
    -
  • DEFAULT_SEQUENCE_MS: This is the default -length of a single processing sequence in milliseconds which determines -the how the original sound is chopped in the time-stretch algorithm. -Larger values mean fewer sequences are used in processing. In principle -a larger value sounds better when slowing down the tempo, but worse -when increasing the tempo and vice versa.
    -
    -By default, this setting value is calculated automatically according to -tempo value.
    -
  • -
  • DEFAULT_SEEKWINDOW_MS: The seeking window -default length in milliseconds is for the algorithm that seeks the best -possible overlapping location. This determines from how wide a sample -"window" the algorithm can use to find an optimal mixing location when -the sound sequences are to be linked back together.
    -
    -The bigger this window setting is, the higher the possibility to find a -better mixing position becomes, but at the same time large values may -cause a "drifting" sound artifact because neighboring sequences can be -chosen at more uneven intervals. If there's a disturbing artifact that -sounds as if a constant frequency was drifting around, try reducing -this setting.
    -
    -By default, this setting value is calculated automatically according to -tempo value.
    -
  • -
  • DEFAULT_OVERLAP_MS: Overlap length in -milliseconds. When the sound sequences are mixed back together to form -again a continuous sound stream, this parameter defines how much the -ends of the consecutive sequences will overlap with each other.
    -
    -This shouldn't be that critical parameter. If you reduce the -DEFAULT_SEQUENCE_MS setting by a large amount, you might wish to try a -smaller value on this.
  • -
-

Notice that these parameters can also be set during execution time -with functions "TDStretch::setParameters()" and "SoundTouch::setSetting()".

-

The table below summaries how the parameters can be adjusted for -different applications:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Parameter nameDefault value magnitudeLarger value affects...Smaller value affects...Effect to CPU burden
-
SEQUENCE_MS
-
Default value is relatively large, chosen for -slowing down music tempoLarger value is usually better for slowing down -tempo. Growing the value decelerates the "echoing" artifact when -slowing down the tempo.Smaller value might be better for speeding up -tempo. Reducing the value accelerates the "echoing" artifact when -slowing down the tempo Increasing the parameter value reduces -computation burden
-
SEEKWINDOW_MS
-
Default value is relatively large, chosen for -slowing down music tempoLarger value eases finding a good mixing -position, but may cause a "drifting" artifactSmaller reduce possibility to find a good mixing -position, but reduce the "drifting" artifact.Increasing the parameter value increases -computation burden
-
OVERLAP_MS
-
Default value is relatively large, chosen to -suit with above parameters.If you reduce the "sequence ms" setting, you -might wish to try a smaller value.Increasing the parameter value increases -computation burden
-

3.5 Performance Optimizations

-

General optimizations:

-

The time-stretch routine has a 'quick' mode that substantially -speeds up the algorithm but may slightly compromise the sound quality. -This mode is activated by calling SoundTouch::setSetting() -function with parameter id of SETTING_USE_QUICKSEEK and value -"1", i.e.

-
-

setSetting(SETTING_USE_QUICKSEEK, 1);

-
-

CPU-specific optimizations:

-

Intel x86 specific SIMD optimizations are implemented using compiler -intrinsics, providing about a 3x processing speedup for x86 compatible -processors vs. non-SIMD implementation:

-
    -
  • Intel MMX optimized routines are used with x86 CPUs when 16bit integer - sample type is used
  • -
  • Intel SSE optimized routines are used with x86 CPUs when 32bit floating - point sample type is used
  • -
-

3.5 OpenMP parallel computation

-

SoundTouch 1.9 onwards support running the algorithms parallel in several CPU -cores. Based on benchmark the experienced multi-core processing speed-up gain -ranges between +30% (on a high-spec dual-core x86 Windows PC) to 215% (on a moderately low-spec -quad-core ARM of Raspberry Pi2).

-

See an external blog article with more detailed discussion about the - -SoundTouch OpenMP optimization.

-

The parallel computing support is implemented using OpenMP spec 3.0 -instructions. These instructions are supported by Visual C++ 2008 and later, and -GCC v4.2 and later. Compilers that do not supporting OpenMP will ignore these -optimizations and routines will still work properly. Possible warnings about -unknown #pragmas are related to OpenMP support and can be safely ignored.

-

The OpenMP improvements are disabled by default, and need to be enabled by -developer during compile-time. Reason for this is that parallel processing adds -moderate runtime overhead in managing the multi-threading, so it may not be -necessary nor desirable in all applications. For example real-time processing -that is not constrained by CPU power will not benefit of speed-up provided by -the parallel processing, in the contrary it may increase power consumption due -to the increased overhead.

-

However, applications that run on low-spec multi-core CPUs and may otherwise -have possibly constrained performance will benefit of the OpenMP improvements. -This include for example multi-core embedded devices.

-

OpenMP parallel computation can be enabled before compiling SoundTouch -library as follows:

-
    -
  • Visual Studio: Open properties for the SoundTouch - sub-project, browse to C/C++ and Language - settings. Set - there "OpenMP support" to "Yes". Alternatively add - /openmp switch to command-line - parameters
  • -
  • GNU: Run the configure script with "./configure - --enable-openmp" switch, then run make as usually
  • -
  • Android: Add "-fopenmp" switches to compiler & linker - options, see README-SoundTouch-Android.html in the source code package for - more detailed instructions.
  • -
-
-

4. SoundStretch audio processing utility -

-

SoundStretch audio processing utility
- Copyright (c) Olli Parviainen 2002-2015

-

SoundStretch is a simple command-line application that can change -tempo, pitch and playback rates of WAV sound files. This program is -intended primarily to demonstrate how the "SoundTouch" library can be -used to process sound in your own program, but it can as well be used -for processing sound files.

-

4.1. SoundStretch Usage Instructions

-

SoundStretch Usage syntax:

-
-
soundstretch infilename outfilename [switches]
-
-

Where:

- - - - - - - - - - - - - - - -
-
"infilename"
-
Name of the input sound data file (in .WAV audio -file format). Give "stdin" as filename to use standard input pipe.
-
"outfilename"
-
Name of the output sound file where the -resulting sound is saved (in .WAV audio file format). This parameter -may be omitted if you don't want to save the output (e.g. when -only calculating BPM rate with '-bpm' switch). Give "stdout" as -filename to use standard output pipe.
-
[switches]
-
Are one or more control switches.
-

Available control switches are:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-tempo=n 
-
Change the sound tempo by n percents (n = -95.0 -.. +5000.0 %)
-
-pitch=n
-
Change the sound pitch by n semitones (n = -60.0 -.. + 60.0 semitones)
-
-rate=n
-
Change the sound playback rate by n percents (n -= -95.0 .. +5000.0 %)
-
-bpm=n
-
Detect the Beats-Per-Minute (BPM) rate of the -sound and adjust the tempo to meet 'n' BPMs. When this switch is -applied, the "-tempo" switch is ignored. If "=n" is omitted, i.e. -switch "-bpm" is used alone, then the BPM rate is estimated and -displayed, but tempo not adjusted according to the BPM value.
-
-quick
-
Use quicker tempo change algorithm. Gains speed -but loses sound quality.
-
-naa
-
Don't use anti-alias filtering in sample rate -transposing. Gains speed but loses sound quality.
-
-license
-
Displays the program license text (LGPL)
-

Notes:

-
    -
  • To use standard input/output pipes for processing, give "stdin" -and "stdout" as input/output filenames correspondingly. The standard -input/output pipes will still carry the audio data in .wav audio file -format.
  • -
  • The numerical switches allow both integer (e.g. "-tempo=123") -and decimal (e.g. "-tempo=123.45") numbers.
  • -
  • The "-naa" and/or "-quick" switches can be used to reduce CPU -usage while compromising some sound quality
  • -
  • The BPM detection algorithm works by detecting repeating bass or -drum patterns at low frequencies of <250Hz. A lower-than-expected -BPM figure may be reported for music with uneven or complex bass -patterns.
  • -
-

4.2. SoundStretch usage examples

-

Example 1

-

The following command increases tempo of the sound file -"originalfile.wav" by 12.5% and stores result to file -"destinationfile.wav":

-
-
soundstretch originalfile.wav destinationfile.wav -tempo=12.5
-
-

Example 2

-

The following command decreases the sound pitch (key) of the sound -file "orig.wav" by two semitones and stores the result to file -"dest.wav":

-
-
soundstretch orig.wav dest.wav -pitch=-2
-
-

Example 3

-

The following command processes the file "orig.wav" by decreasing -the sound tempo by 25.3% and increasing the sound pitch (key) by 1.5 -semitones. Resulting .wav audio data is directed to standard output -pipe:

-
-
soundstretch orig.wav stdout -tempo=-25.3 -pitch=1.5
-
-

Example 4

-

The following command detects the BPM rate of the file "orig.wav" -and adjusts the tempo to match 100 beats per minute. Result is stored -to file "dest.wav":

-
-
soundstretch orig.wav dest.wav -bpm=100
-
-

Example 5

-

The following command reads .wav sound data from standard input pipe -and estimates the BPM rate:

-
-
soundstretch stdin -bpm
-
-

Example 6

-

The following command tunes song from original 440Hz tuning to 432Hz tuning: -this corresponds to lowering the pitch by -0.318 semitones:

-
-
soundstretch original.wav output.wav -pitch=-0.318
-
-
-

5. Change History

-

5.1. SoundTouch library Change History

-

2.1:

-
    -
  • Refactored C# interface example
  • -
  • Disable anti-alias filter when switch - SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER defined because anti-alias - filter cause slight click if the rate change crosses zero during - processing
  • -
  • Added script for building SoundTouchDll dynamic-link-library for GNU platforms
  • -
  • Rewrote Beats-per-Minute analysis algorithm for more reliable BPM detection
  • -
  • Added BPM functions to SoundTouchDll API
  • -
  • Migrated Visual Studio project files to MSVC 201x format
  • -
  • Replaced function parameter value asserts with runtime exceptions
  • -
  • Code maintenance & style cleanup
  • -
-

2.0:

-
    -
  • Added functions to get initial processing latency, duration ratio between the original input and processed output tracks, and clarified reporting of input/output batch sizes
  • -
  • Fixed issue that added brief sequence of silence to beginning of output audio
  • -
  • Adjusted algorithm parameters to reduce reverberating effect at tempo slowdown
  • -
  • Bugfix: Fixed a glitch that could cause negative array indexing in quick seek algorithm
  • -
  • Bugfix: flush() didn't properly flush final samples from the pipeline on 2nd time in case that soundtouch object instance was recycled and used for processing a second audio stream.
  • -
  • Bugfix: Pi value had incorrect 9th/10th decimals
  • -
  • Added C# example application that uses SoundTouch dll library for processing MP3 files
  • -
-

1.9.2:

-
    -
  • Fix in GNU package configuration
  • -
-

1.9.1:

-
    -
  • Improved SoundTouch::flush() function so that it returns precisely the desired amount of samples for exact output duration control
  • -
  • Redesigned quickseek algorithm for improved sound quality when using the quickseek mode. The new quickseek algorithm can find 99% as good results as the - default full-scan mode, while the quickseek algorithm is remarkable less - CPU intensive.
  • -
  • Added adaptive integer divider scaling for improved sound quality when using integer processing algorithm -
  • -
-

1.9:

-
    -
  • Added support for parallel computation support via OpenMP primitives for better performance in multicore systems. - Benchmarks show that achieved parallel processing speedup improvement - typically range from +30% (x86 dual-core) to +180% (ARM quad-core). The - OpenMP optimizations are disabled by default, see OpenMP notes above in this - readme file how to enabled these optimizations.
  • -
  • Android: Added support for Android devices featuring X86 and MIPS CPUs, - in addition to ARM CPUs.
  • -
  • Android: More versatile Android example application that processes WAV - audio files with SoundTouch library
  • -
  • Replaced Windows-like 'BOOL' types with native 'bool'
  • -
  • Changed documentation token to "dist_doc_DATA" in Makefile.am file
  • -
  • Miscellaneous small fixes and improvements
  • -
-

1.8.0:

-
    -
  • Added support for multi-channel audio processing
  • -
  • Added support for cubic and shannon interpolation for rate and pitch shift effects besides - the original linear interpolation, to reduce aliasing at high frequencies due to interpolation. - Cubic interpolation is used as default for floating point processing, and linear interpolation for integer - processing.
  • -
  • Fixed bug in anti-alias filtering that limited stop-band attenuation to -10 dB instead of <-50dB, and - increased filter length from 32 to 64 taps to further reduce aliasing due to frequency folding.
  • -
  • Performance improvements in cross-correlation algorithm
  • -
  • Other bug and compatibility fixes
  • -
-

1.7.1:

-
    -
  • Added files for Android compilation -
-

1.7.0:

-
    -
  • Sound quality improvements/li> -
  • Improved flush() to adjust output sound stream duration to match better with - ideal duration
  • -
  • Rewrote x86 cpu feature check to resolve compatibility problems
  • -
  • Configure script automatically checks if CPU supports mmx & sse compatibility for GNU platform, and - the script support now "--enable-x86-optimizations" switch to allow disabling x86-specific optimizations.
  • -
  • Revised #define conditions for 32bit/64bit compatibility
  • -
  • gnu autoconf/automake script compatibility fixes
  • -
  • Tuned beat-per-minute detection algorithm
  • -
-

1.6.0:

-
    -
  • Added automatic cutoff threshold adaptation to beat detection -routine to better adapt BPM calculation to different types of music
  • -
  • Retired 3DNow! optimization support as 3DNow! is nowadays -obsoleted and assembler code is nuisance to maintain
  • -
  • Retired "configure" file from source code package due to -autoconf/automake versio conflicts, so that it is from now on to be -generated by invoking "boostrap" script that uses locally available -toolchain version for generating the "configure" file
  • -
  • Resolved namespace/label naming conflicts with other libraries by -replacing global labels such as INTEGER_SAMPLES with more specific -SOUNDTOUCH_INTEGER_SAMPLES etc.
    -
  • -
  • Updated windows build scripts & project files for Visual -Studio 2008 support
  • -
  • Updated SoundTouch.dll API for .NET compatibility
  • -
  • Added API for querying nominal processing input & output -sample batch sizes
  • -
-

1.5.0:

-
    -
  • Added normalization to correlation calculation and improvement -automatic seek/sequence parameter calculation to improve sound quality
  • -
  • Bugfixes: -
      -
    • Fixed negative array indexing in quick seek algorithm
    • -
    • FIR autoalias filter running too far in processing buffer
    • -
    • Check against zero sample count in rate transposing
    • -
    • Fix for x86-64 support: Removed pop/push instructions from -the cpu detection algorithm.
    • -
    • Check against empty buffers in FIFOSampleBuffer
    • -
    • Other minor fixes & code cleanup
    • -
    -
  • -
  • Fixes in compilation scripts for non-Intel platforms
  • -
  • Added Dynamic-Link-Library (DLL) version of SoundTouch library -build, provided with Delphi/Pascal wrapper for calling the dll routines -
  • -
  • Added #define PREVENT_CLICK_AT_RATE_CROSSOVER that prevents a -click artifact when crossing the nominal pitch from either positive to -negative side or vice versa
  • -
-

1.4.1:

-
    -
  • Fixed a buffer overflow bug in BPM detect algorithm routines if -processing more than 2048 samples at one call
  • -
-

1.4.0:

-
    -
  • Improved sound quality by automatic calculation of time stretch -algorithm processing parameters according to tempo setting
  • -
  • Moved BPM detection routines from SoundStretch application into -SoundTouch library
  • -
  • Bugfixes: Usage of uninitialied variables, GNU build scripts, -compiler errors due to 'const' keyword mismatch.
  • -
  • Source code cleanup
  • -
-

1.3.1:

-
    -
  • Changed static class declaration to GCC 4.x compiler compatible -syntax.
  • -
  • Enabled MMX/SSE-optimized routines also for GCC compilers. -Earlier the MMX/SSE-optimized routines were written in -compiler-specific inline assembler, now these routines are migrated to -use compiler intrinsic syntax which allows compiling the same -MMX/SSE-optimized source code with both Visual C++ and GCC compilers.
  • -
  • Set floating point as the default sample format and added switch -to the GNU configure script for selecting the other sample format.
  • -
-

1.3.0:

-
    -
  • Fixed tempo routine output duration inaccuracy due to rounding -error
  • -
  • Implemented separate processing routines for integer and -floating arithmetic to allow improvements to floating point routines -(earlier used algorithms mostly optimized for integer arithmetic also -for floating point samples)
  • -
  • Fixed a bug that distorts sound if sample rate changes during -the sound stream
  • -
  • Fixed a memory leak that appeared in MMX/SSE/3DNow! optimized -routines
  • -
  • Reduced redundant code pieces in MMX/SSE/3DNow! optimized -routines vs. the standard C routines.
  • -
  • MMX routine incompatibility with new gcc compiler versions
  • -
  • Other miscellaneous bug fixes
  • -
-

1.2.1:

-
    -
  • Added automake/autoconf scripts for GNU platforms (in courtesy -of David Durham)
  • -
  • Fixed SCALE overflow bug in rate transposer routine.
  • -
  • Fixed 64bit address space bugs.
  • -
  • Created a 'soundtouch' namespace for SAMPLETYPE definitions.
  • -
-

1.2.0:

-
    -
  • Added support for 32bit floating point sample data type with -SSE/3DNow! optimizations for Win32 platform (SSE/3DNow! optimizations -currently not supported in GCC environment)
  • -
  • Replaced 'make-gcc' script for GNU environment by master -Makefile
  • -
  • Added time-stretch routine configurability to SoundTouch main -class
  • -
  • Bugfixes
  • -
-

1.1.1:

-
    -
  • Moved SoundTouch under lesser GPL license (LGPL). This allows -using SoundTouch library in programs that aren't released under GPL -license.
  • -
  • Changed MMX routine organiation so that MMX optimized routines -are now implemented in classes that are derived from the basic classes -having the standard non-mmx routines.
  • -
  • MMX routines to support gcc version 3.
  • -
  • Replaced windows makefiles by script using the .dsw files
  • -
-

1.0.1:

-
    -
  • "mmx_gcc.cpp": Added "using namespace std" and removed "return -0" from a function with void return value to fix compiler errors when -compiling the library in Solaris environment.
  • -
  • Moved file "FIFOSampleBuffer.h" to "include" directory to allow -accessing the FIFOSampleBuffer class from external files.
  • -
-

1.0:

-
    -
  • Initial release
  • -
-

5.2. SoundStretch application Change History

-

1.9:

-
    -
  • Added support for WAV file 'fact' information chunk.
  • -
- -

1.7.0:

-
    -
  • Bugfixes in Wavfile: exception string formatting, avoid getLengthMs() integer - precision overflow, support WAV files using 24/32bit sample format.
  • -
-

1.5.0:

-
    -
  • Added "-speech" switch to activate algorithm parameters more -suitable for speech processing than the default parameters tuned for -music processing.
  • -
-

1.4.0:

-
    -
  • Moved BPM detection routines from SoundStretch application into -SoundTouch library
  • -
  • Allow using standard input/output pipes as audio processing -input/output streams
  • -
-

1.3.0:

-
    -
  • Simplified accessing WAV files with floating point sample -format.
  • -
-

1.2.1:

-
    -
  • Fixed 64bit address space bugs.
  • -
-

1.2.0:

-
    -
  • Added support for 32bit floating point sample data type
  • -
  • Restructured the BPM routines into separate library
  • -
  • Fixed big-endian conversion bugs in WAV file routines (hopefully -:)
  • -
-

1.1.1:

-
    -
  • Fixed bugs in WAV file reading & added byte-order conversion -for big-endian processors.
  • -
  • Moved SoundStretch source code under 'example' directory to -highlight difference from SoundTouch stuff.
  • -
  • Replaced windows makefiles by script using the .dsw files
  • -
  • Output file name isn't required if output isn't desired (e.g. if -using the switch '-bpm' in plain format only)
  • -
-

1.1:

-
    -
  • Fixed "Release" settings in Microsoft Visual C++ project file -(.dsp)
  • -
  • Added beats-per-minute (BPM) detection routine and command-line -switch "-bpm"
  • -
-

1.01:

-
    -
  • Initial release
  • -
-
-

6. Acknowledgements

-

Kudos for these people who have contributed to development or -submitted bugfixes:

-
    -
  • Arthur A
  • -
  • Paul Adenot
  • -
  • Richard Ash
  • -
  • Stanislav Brabec
  • -
  • Christian Budde
  • -
  • Jamie Bullock
  • -
  • Chris Bryan
  • -
  • Jacek Caban
  • -
  • Brian Cameron
  • -
  • Jason Champion
  • -
  • David Clark
  • -
  • Patrick Colis
  • -
  • Miquel Colon
  • -
  • Jim Credland
  • -
  • Sandro Cumerlato
  • -
  • Justin Frankel
  • -
  • Masa H.
  • -
  • Jason Garland
  • -
  • Takashi Iwai
  • -
  • Thomas Klausner
  • -
  • Lu Zhihe
  • -
  • Luzpaz
  • -
  • Tony Mechelynck
  • -
  • Mathias Möhl
  • -
  • Yuval Naveh
  • -
  • Mats Palmgren
  • -
  • Chandni Patel
  • -
  • Paulo Pizarro
  • -
  • Andrey Ponomarenko
  • -
  • Blaise Potard
  • -
  • Michael Pruett
  • -
  • Rajeev Puran
  • -
  • RJ Ryan
  • -
  • John Sheehy
  • -
  • Tim Shuttleworth
  • -
  • Albert Sirvent
  • -
  • Tyson Smith
  • -
  • John Stumpo
  • -
  • Mario di Vece
  • -
  • Katja Vetter
  • -
  • Wu Q.
  • -
-

Moral greetings to all other contributors and users also!

-
-

7. LICENSE

-

SoundTouch audio processing library
-Copyright (c) Olli Parviainen

-

This library is free software; you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License version 2.1 -as published by the Free Software Foundation.

-

This library 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 library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

-

---

-

commercial license alternative also available, contact author for details.

-
-

README.html file updated in May-2018

- - + + + + SoundTouch library README + + + + + + + +
+

SoundTouch audio processing library v2.1.1

+

SoundTouch library Copyright © Olli Parviainen 2001-2018

+
+

1. Introduction

+

SoundTouch is an open-source audio processing library that allows +changing the sound tempo, pitch and playback rate parameters +independently from each other, i.e.:

+
    +
  • Sound tempo can be increased or decreased while maintaining the +original pitch
  • +
  • Sound pitch can be increased or decreased while maintaining the +original tempo
  • +
  • Change playback rate that affects both tempo and pitch at the +same time
  • +
  • Choose any combination of tempo/pitch/rate
  • +
+

1.1 Contact information

+

Author email: oparviai 'at' iki.fi

+

SoundTouch WWW page: http://soundtouch.surina.net

+

SoundTouch git repository: https://gitlab.com/soundtouch/soundtouch.git

+
+

2. Compiling SoundTouch

+

Before compiling, notice that you can choose the sample data format if it's +desirable to use floating point sample data instead of 16bit integers. See +section "sample data format" for more information.

+

Also notice that SoundTouch can use OpenMP instructions for parallel +computation to accelerate the runtime processing speed in multi-core systems, +however, these improvements need to be separately enabled before compiling. See +OpenMP notes in Chapter 3 below.

+

2.1. Building in Microsoft Windows

+

Project files for Microsoft Visual C++ are supplied with the source +code package. Go to Microsoft WWW page to download + +Microsoft Visual Studio Express version for free. +

+

To build the binaries with Visual C++ compiler, either run +"make-win.bat" script, or open the appropriate project files in source +code directories with Visual Studio. The final executable will appear +under the "SoundTouch\bin" directory. If using the Visual Studio IDE +instead of the make-win.bat script, directories bin and lib may need to +be created manually to the SoundTouch package root for the final +executables. The make-win.bat script creates these directories +automatically.

+

C# example: The source code package includes also a C# example + application for Windows that shows how to invoke SoundTouch.dll + dynamic-load library for processing mp3 audio. +

OpenMP NOTE: If activating the OpenMP parallel computing in +the compilation, the target program will require additional vcomp dll library to +properly run. In Visual C++ 9.0 these libraries can be found in the following +folders.

+
    +
  • x86 32bit: C:\Program Files (x86)\Microsoft Visual Studio + 9.0\VC\redist\x86\Microsoft.VC90.OPENMP\vcomp90.dll
  • +
  • x64 64bit: C:\Program Files (x86)\Microsoft Visual Studio + 9.0\VC\redist\amd64\Microsoft.VC90.OPENMP\vcomp90.dll
  • +
+

In Visual Studio 2008, a SP1 version may be required for these libraries. In +other VC++ versions the required library will be expectedly found in similar +"redist" location.

+

Notice that as minor demonstration of a "dll hell" phenomenon both the 32-bit +and 64-bit version of vcomp90.dll have the same filename but different contents, +thus choose the proper version to allow the program start.

+

2.2. Building in Gnu platforms

+

The SoundTouch library compiles in practically any platform +supporting GNU compiler (GCC) tools. SoundTouch requires GCC version 4.3 or later.

+

To build and install the binaries, run the following commands in +/soundtouch directory:

+ + + + + + + + + + + + + + + + + + + +
+
./bootstrap  -
+
Creates "configure" file with +local autoconf/automake toolset.
+
+
./configure  -
+
+

Configures the SoundTouch package for the local environment. +Notice that "configure" file is not available before running the +"./bootstrap" command as above.
+

+
+
make         -
+
+

Builds the SoundTouch library & SoundStretch utility. You can + optionally add "-j" switch after "make" to speed up the compilation in + multi-core systems.

+
+
make install -
+
+

Installs the SoundTouch & BPM libraries to /usr/local/lib +and SoundStretch utility to /usr/local/bin. Please notice that +'root' privileges may be required to install the binaries to the +destination locations.

+
+

2.2.1 Required GNU tools

+

Bash shell, GNU C++ compiler, libtool, autoconf and automake tools +are required for compiling the SoundTouch library. These are usually +included with the GNU/Linux distribution, but if not, install these +packages first. For example, Ubuntu Linux can acquire and install +these with the following command:

+
sudo apt-get install automake autoconf libtool build-essential
+

2.2.2 Problems with GCC compiler compatibility

+

At the release time the SoundTouch package has been tested to +compile in GNU/Linux platform. However, If you have problems getting the +SoundTouch library compiled, try disabling optimizations that are specific for +x86 processors by running ./configure script with switch +

+
--enable-x86-optimizations=no
+
+ +Alternatively, if you don't use GNU Configure system, edit file "include/STTypes.h" +directly and remove the following definition:
+
#define SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS 1
+
+ +

2.2.3 Compiling Shared Library / DLL version in Cygwin

+

+ The GNU compilation does not automatically create a shared-library version of + SoundTouch (.so or .dll). If such is desired, then you can create it as follows + after running the usual compilation:

+
+
g++ -shared -static -DDLL_EXPORTS -I../../include -o SoundTouch.dll \
+     SoundTouchDLL.cpp ../SoundTouch/.libs/libSoundTouch.a
+sstrip SoundTouch.dll
+
+ +

2.3. Building in Android

+

Android compilation instructions are within the + source code package, see file "source/Android-lib/README-SoundTouch-Android.html" + in the source code package.

+

The Android compilation automatically builds separate .so library binaries +for ARM, X86 and MIPS processor architectures. For optimal device support, +include all these .so library binaries into the Android .apk application +package, so the target Android device can automatically choose the proper +library binary version to use.

+

The source/Android-lib folder includes also an Android +example application that processes WAV audio files using SoundTouch library in +Android devices.

+ +
+

3. About implementation & Usage tips

3.1. Supported sample data formats

+

The sample data format can be chosen between 16bit signed integer +and 32bit floating point values. The default is 32bit floating point format, +which will also provide slightly better sound quality over the integer format.

+

In Windows environment, the sample data format is chosen in file +"STTypes.h" by choosing one of the following defines:

+
    +
  • #define +SOUNDTOUCH_INTEGER_SAMPLES for 16bit signed integer
  • +
  • #define SOUNDTOUCH_FLOAT_SAMPLES for 32bit floating +point
  • +
+

In GNU environment, the floating sample format is used by default, +but integer sample format can be chosen by giving the following switch +to the configure script:

+
+
./configure --enable-integer-samples
+
+

The sample data can have either single (mono) or double (stereo) +audio channel. Stereo data is interleaved so that every other data +value is for left channel and every second for right channel. Notice +that while it'd be possible in theory to process stereo sound as two +separate mono channels, this isn't recommended because processing the +channels separately would result in losing the phase coherency between +the channels, which consequently would ruin the stereo effect.

+

Sample rates between 8000-48000H are supported.

+

3.2. Processing latency

+

The processing and latency constraints of the SoundTouch library are:

+
    +
  • Input/output processing latency for the SoundTouch processor is +around 100 ms. This is when time-stretching is used. If the rate +transposing effect alone is used, the latency requirement is much +shorter, see section 'About algorithms'.
  • +
  • Processing CD-quality sound (16bit stereo sound with 44100H +sample rate) in real-time or faster is possible starting from +processors equivalent to Intel Pentium 133Mh or better, if using the +"quick" processing algorithm. If not using the "quick" mode or if +floating point sample data are being used, several times more CPU power +is typically required.
  • +
+

3.3. About algorithms

+

SoundTouch provides three seemingly independent effects: tempo, +pitch and playback rate control. These three controls are implemented +as combination of two primary effects, sample rate transposing +and time-stretching.

+

Sample rate transposing affects both the audio stream +duration and pitch. It's implemented simply by converting the original +audio sample stream to the desired duration by interpolating from +the original audio samples. In SoundTouch, linear interpolation with +anti-alias filtering is used. Theoretically a higher-order +interpolation provide better result than 1st order linear +interpolation, but in audio application linear interpolation together +with anti-alias filtering performs subjectively about as well as +higher-order filtering would.

+

Time-stretching means changing the audio stream duration +without affecting it's pitch. SoundTouch uses WSOLA-like +time-stretching routines that operate in the time domain. Compared to +sample rate transposing, time-stretching is a much heavier operation +and also requires a longer processing "window" of sound samples used by +the processing algorithm, thus increasing the algorithm input/output +latency. Typical i/o latency for the SoundTouch time-stretch algorithm +is around 100 ms.

+

Sample rate transposing and time-stretching are then used together +to produce the tempo, pitch and rate controls:

+
    +
  • 'Tempo' control is implemented purely by +time-stretching.
  • +
  • 'Rate' control is implemented purely by sample +rate transposing.
  • +
  • 'Pitch' control is implemented as a +combination of time-stretching and sample rate transposing. For +example, to increase pitch the audio stream is first time-stretched to +longer duration (without affecting pitch) and then transposed back to +original duration by sample rate transposing, which simultaneously +reduces duration and increases pitch. The result is original duration +but increased pitch.
  • +
+

3.4 Tuning the algorithm parameters

+

The time-stretch algorithm has few parameters that can be tuned to +optimize sound quality for certain application. The current default +parameters have been chosen by iterative if-then analysis (read: "trial +and error") to obtain best subjective sound quality in pop/rock music +processing, but in applications processing different kind of sound the +default parameter set may result into a sub-optimal result.

+

The time-stretch algorithm default parameter values are set by the +following #defines in file "TDStretch.h":

+
+
#define DEFAULT_SEQUENCE_MS     AUTOMATIC
#define DEFAULT_SEEKWINDOW_MS AUTOMATIC
#define DEFAULT_OVERLAP_MS 8
+
+

These parameters affect to the time-stretch algorithm as follows:

+
    +
  • DEFAULT_SEQUENCE_MS: This is the default +length of a single processing sequence in milliseconds which determines +the how the original sound is chopped in the time-stretch algorithm. +Larger values mean fewer sequences are used in processing. In principle +a larger value sounds better when slowing down the tempo, but worse +when increasing the tempo and vice versa.
    +
    +By default, this setting value is calculated automatically according to +tempo value.
    +
  • +
  • DEFAULT_SEEKWINDOW_MS: The seeking window +default length in milliseconds is for the algorithm that seeks the best +possible overlapping location. This determines from how wide a sample +"window" the algorithm can use to find an optimal mixing location when +the sound sequences are to be linked back together.
    +
    +The bigger this window setting is, the higher the possibility to find a +better mixing position becomes, but at the same time large values may +cause a "drifting" sound artifact because neighboring sequences can be +chosen at more uneven intervals. If there's a disturbing artifact that +sounds as if a constant frequency was drifting around, try reducing +this setting.
    +
    +By default, this setting value is calculated automatically according to +tempo value.
    +
  • +
  • DEFAULT_OVERLAP_MS: Overlap length in +milliseconds. When the sound sequences are mixed back together to form +again a continuous sound stream, this parameter defines how much the +ends of the consecutive sequences will overlap with each other.
    +
    +This shouldn't be that critical parameter. If you reduce the +DEFAULT_SEQUENCE_MS setting by a large amount, you might wish to try a +smaller value on this.
  • +
+

Notice that these parameters can also be set during execution time +with functions "TDStretch::setParameters()" and "SoundTouch::setSetting()".

+

The table below summaries how the parameters can be adjusted for +different applications:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Parameter nameDefault value magnitudeLarger value affects...Smaller value affects...Effect to CPU burden
+
SEQUENCE_MS
+
Default value is relatively large, chosen for +slowing down music tempoLarger value is usually better for slowing down +tempo. Growing the value decelerates the "echoing" artifact when +slowing down the tempo.Smaller value might be better for speeding up +tempo. Reducing the value accelerates the "echoing" artifact when +slowing down the tempo Increasing the parameter value reduces +computation burden
+
SEEKWINDOW_MS
+
Default value is relatively large, chosen for +slowing down music tempoLarger value eases finding a good mixing +position, but may cause a "drifting" artifactSmaller reduce possibility to find a good mixing +position, but reduce the "drifting" artifact.Increasing the parameter value increases +computation burden
+
OVERLAP_MS
+
Default value is relatively large, chosen to +suit with above parameters.If you reduce the "sequence ms" setting, you +might wish to try a smaller value.Increasing the parameter value increases +computation burden
+

3.5 Performance Optimizations

+

General optimizations:

+

The time-stretch routine has a 'quick' mode that substantially +speeds up the algorithm but may slightly compromise the sound quality. +This mode is activated by calling SoundTouch::setSetting() +function with parameter id of SETTING_USE_QUICKSEEK and value +"1", i.e.

+
+

setSetting(SETTING_USE_QUICKSEEK, 1);

+
+

CPU-specific optimizations:

+

Intel x86 specific SIMD optimizations are implemented using compiler +intrinsics, providing about a 3x processing speedup for x86 compatible +processors vs. non-SIMD implementation:

+
    +
  • Intel MMX optimized routines are used with x86 CPUs when 16bit integer + sample type is used
  • +
  • Intel SSE optimized routines are used with x86 CPUs when 32bit floating + point sample type is used
  • +
+

3.5 OpenMP parallel computation

+

SoundTouch 1.9 onwards support running the algorithms parallel in several CPU +cores. Based on benchmark the experienced multi-core processing speed-up gain +ranges between +30% (on a high-spec dual-core x86 Windows PC) to 215% (on a moderately low-spec +quad-core ARM of Raspberry Pi2).

+

See an external blog article with more detailed discussion about the + +SoundTouch OpenMP optimization.

+

The parallel computing support is implemented using OpenMP spec 3.0 +instructions. These instructions are supported by Visual C++ 2008 and later, and +GCC v4.2 and later. Compilers that do not supporting OpenMP will ignore these +optimizations and routines will still work properly. Possible warnings about +unknown #pragmas are related to OpenMP support and can be safely ignored.

+

The OpenMP improvements are disabled by default, and need to be enabled by +developer during compile-time. Reason for this is that parallel processing adds +moderate runtime overhead in managing the multi-threading, so it may not be +necessary nor desirable in all applications. For example real-time processing +that is not constrained by CPU power will not benefit of speed-up provided by +the parallel processing, in the contrary it may increase power consumption due +to the increased overhead.

+

However, applications that run on low-spec multi-core CPUs and may otherwise +have possibly constrained performance will benefit of the OpenMP improvements. +This include for example multi-core embedded devices.

+

OpenMP parallel computation can be enabled before compiling SoundTouch +library as follows:

+
    +
  • Visual Studio: Open properties for the SoundTouch + sub-project, browse to C/C++ and Language + settings. Set + there "OpenMP support" to "Yes". Alternatively add + /openmp switch to command-line + parameters
  • +
  • GNU: Run the configure script with "./configure + --enable-openmp" switch, then run make as usually
  • +
  • Android: Add "-fopenmp" switches to compiler & linker + options, see README-SoundTouch-Android.html in the source code package for + more detailed instructions.
  • +
+
+

4. SoundStretch audio processing utility +

+

SoundStretch audio processing utility
+ Copyright (c) Olli Parviainen 2002-2015

+

SoundStretch is a simple command-line application that can change +tempo, pitch and playback rates of WAV sound files. This program is +intended primarily to demonstrate how the "SoundTouch" library can be +used to process sound in your own program, but it can as well be used +for processing sound files.

+

4.1. SoundStretch Usage Instructions

+

SoundStretch Usage syntax:

+
+
soundstretch infilename outfilename [switches]
+
+

Where:

+ + + + + + + + + + + + + + + +
+
"infilename"
+
Name of the input sound data file (in .WAV audio +file format). Give "stdin" as filename to use standard input pipe.
+
"outfilename"
+
Name of the output sound file where the +resulting sound is saved (in .WAV audio file format). This parameter +may be omitted if you don't want to save the output (e.g. when +only calculating BPM rate with '-bpm' switch). Give "stdout" as +filename to use standard output pipe.
+
[switches]
+
Are one or more control switches.
+

Available control switches are:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
-tempo=n 
+
Change the sound tempo by n percents (n = -95.0 +.. +5000.0 %)
+
-pitch=n
+
Change the sound pitch by n semitones (n = -60.0 +.. + 60.0 semitones)
+
-rate=n
+
Change the sound playback rate by n percents (n += -95.0 .. +5000.0 %)
+
-bpm=n
+
Detect the Beats-Per-Minute (BPM) rate of the +sound and adjust the tempo to meet 'n' BPMs. When this switch is +applied, the "-tempo" switch is ignored. If "=n" is omitted, i.e. +switch "-bpm" is used alone, then the BPM rate is estimated and +displayed, but tempo not adjusted according to the BPM value.
+
-quick
+
Use quicker tempo change algorithm. Gains speed +but loses sound quality.
+
-naa
+
Don't use anti-alias filtering in sample rate +transposing. Gains speed but loses sound quality.
+
-license
+
Displays the program license text (LGPL)
+

Notes:

+
    +
  • To use standard input/output pipes for processing, give "stdin" +and "stdout" as input/output filenames correspondingly. The standard +input/output pipes will still carry the audio data in .wav audio file +format.
  • +
  • The numerical switches allow both integer (e.g. "-tempo=123") +and decimal (e.g. "-tempo=123.45") numbers.
  • +
  • The "-naa" and/or "-quick" switches can be used to reduce CPU +usage while compromising some sound quality
  • +
  • The BPM detection algorithm works by detecting repeating bass or +drum patterns at low frequencies of <250Hz. A lower-than-expected +BPM figure may be reported for music with uneven or complex bass +patterns.
  • +
+

4.2. SoundStretch usage examples

+

Example 1

+

The following command increases tempo of the sound file +"originalfile.wav" by 12.5% and stores result to file +"destinationfile.wav":

+
+
soundstretch originalfile.wav destinationfile.wav -tempo=12.5
+
+

Example 2

+

The following command decreases the sound pitch (key) of the sound +file "orig.wav" by two semitones and stores the result to file +"dest.wav":

+
+
soundstretch orig.wav dest.wav -pitch=-2
+
+

Example 3

+

The following command processes the file "orig.wav" by decreasing +the sound tempo by 25.3% and increasing the sound pitch (key) by 1.5 +semitones. Resulting .wav audio data is directed to standard output +pipe:

+
+
soundstretch orig.wav stdout -tempo=-25.3 -pitch=1.5
+
+

Example 4

+

The following command detects the BPM rate of the file "orig.wav" +and adjusts the tempo to match 100 beats per minute. Result is stored +to file "dest.wav":

+
+
soundstretch orig.wav dest.wav -bpm=100
+
+

Example 5

+

The following command reads .wav sound data from standard input pipe +and estimates the BPM rate:

+
+
soundstretch stdin -bpm
+
+

Example 6

+

The following command tunes song from original 440Hz tuning to 432Hz tuning: +this corresponds to lowering the pitch by -0.318 semitones:

+
+
soundstretch original.wav output.wav -pitch=-0.318
+
+
+

5. Change History

+

5.1. SoundTouch library Change History

+

2.1.1:

+
    +
  • Bugfixes: Fixed potential buffer overwrite bugs in WavFile routines. Replaced asserts with runtime exceptions.
  • +
  • Android: Migrated the SoundTouch Android example to new Android Studio
  • +
  • Automake: unset ACLOCAL in bootstrap script in case earlier build script has set it
  • + +
+

2.1:

+
    +
  • Refactored C# interface example
  • +
  • Disable anti-alias filter when switch + SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER defined because anti-alias + filter cause slight click if the rate change crosses zero during + processing
  • +
  • Added script for building SoundTouchDll dynamic-link-library for GNU platforms
  • +
  • Rewrote Beats-per-Minute analysis algorithm for more reliable BPM detection
  • +
  • Added BPM functions to SoundTouchDll API
  • +
  • Migrated Visual Studio project files to MSVC 201x format
  • +
  • Replaced function parameter value asserts with runtime exceptions
  • +
  • Code maintenance & style cleanup
  • +
+

2.0:

+
    +
  • Added functions to get initial processing latency, duration ratio between the original input and processed output tracks, and clarified reporting of input/output batch sizes
  • +
  • Fixed issue that added brief sequence of silence to beginning of output audio
  • +
  • Adjusted algorithm parameters to reduce reverberating effect at tempo slowdown
  • +
  • Bugfix: Fixed a glitch that could cause negative array indexing in quick seek algorithm
  • +
  • Bugfix: flush() didn't properly flush final samples from the pipeline on 2nd time in case that soundtouch object instance was recycled and used for processing a second audio stream.
  • +
  • Bugfix: Pi value had incorrect 9th/10th decimals
  • +
  • Added C# example application that uses SoundTouch dll library for processing MP3 files
  • +
+

1.9.2:

+
    +
  • Fix in GNU package configuration
  • +
+

1.9.1:

+
    +
  • Improved SoundTouch::flush() function so that it returns precisely the desired amount of samples for exact output duration control
  • +
  • Redesigned quickseek algorithm for improved sound quality when using the quickseek mode. The new quickseek algorithm can find 99% as good results as the + default full-scan mode, while the quickseek algorithm is remarkable less + CPU intensive.
  • +
  • Added adaptive integer divider scaling for improved sound quality when using integer processing algorithm +
  • +
+

1.9:

+
    +
  • Added support for parallel computation support via OpenMP primitives for better performance in multicore systems. + Benchmarks show that achieved parallel processing speedup improvement + typically range from +30% (x86 dual-core) to +180% (ARM quad-core). The + OpenMP optimizations are disabled by default, see OpenMP notes above in this + readme file how to enabled these optimizations.
  • +
  • Android: Added support for Android devices featuring X86 and MIPS CPUs, + in addition to ARM CPUs.
  • +
  • Android: More versatile Android example application that processes WAV + audio files with SoundTouch library
  • +
  • Replaced Windows-like 'BOOL' types with native 'bool'
  • +
  • Changed documentation token to "dist_doc_DATA" in Makefile.am file
  • +
  • Miscellaneous small fixes and improvements
  • +
+

1.8.0:

+
    +
  • Added support for multi-channel audio processing
  • +
  • Added support for cubic and shannon interpolation for rate and pitch shift effects besides + the original linear interpolation, to reduce aliasing at high frequencies due to interpolation. + Cubic interpolation is used as default for floating point processing, and linear interpolation for integer + processing.
  • +
  • Fixed bug in anti-alias filtering that limited stop-band attenuation to -10 dB instead of <-50dB, and + increased filter length from 32 to 64 taps to further reduce aliasing due to frequency folding.
  • +
  • Performance improvements in cross-correlation algorithm
  • +
  • Other bug and compatibility fixes
  • +
+

1.7.1:

+
    +
  • Added files for Android compilation +
+

1.7.0:

+
    +
  • Sound quality improvements/li> +
  • Improved flush() to adjust output sound stream duration to match better with + ideal duration
  • +
  • Rewrote x86 cpu feature check to resolve compatibility problems
  • +
  • Configure script automatically checks if CPU supports mmx & sse compatibility for GNU platform, and + the script support now "--enable-x86-optimizations" switch to allow disabling x86-specific optimizations.
  • +
  • Revised #define conditions for 32bit/64bit compatibility
  • +
  • gnu autoconf/automake script compatibility fixes
  • +
  • Tuned beat-per-minute detection algorithm
  • +
+

1.6.0:

+
    +
  • Added automatic cutoff threshold adaptation to beat detection +routine to better adapt BPM calculation to different types of music
  • +
  • Retired 3DNow! optimization support as 3DNow! is nowadays +obsoleted and assembler code is nuisance to maintain
  • +
  • Retired "configure" file from source code package due to +autoconf/automake versio conflicts, so that it is from now on to be +generated by invoking "boostrap" script that uses locally available +toolchain version for generating the "configure" file
  • +
  • Resolved namespace/label naming conflicts with other libraries by +replacing global labels such as INTEGER_SAMPLES with more specific +SOUNDTOUCH_INTEGER_SAMPLES etc.
    +
  • +
  • Updated windows build scripts & project files for Visual +Studio 2008 support
  • +
  • Updated SoundTouch.dll API for .NET compatibility
  • +
  • Added API for querying nominal processing input & output +sample batch sizes
  • +
+

1.5.0:

+
    +
  • Added normalization to correlation calculation and improvement +automatic seek/sequence parameter calculation to improve sound quality
  • +
  • Bugfixes: +
      +
    • Fixed negative array indexing in quick seek algorithm
    • +
    • FIR autoalias filter running too far in processing buffer
    • +
    • Check against zero sample count in rate transposing
    • +
    • Fix for x86-64 support: Removed pop/push instructions from +the cpu detection algorithm.
    • +
    • Check against empty buffers in FIFOSampleBuffer
    • +
    • Other minor fixes & code cleanup
    • +
    +
  • +
  • Fixes in compilation scripts for non-Intel platforms
  • +
  • Added Dynamic-Link-Library (DLL) version of SoundTouch library +build, provided with Delphi/Pascal wrapper for calling the dll routines +
  • +
  • Added #define PREVENT_CLICK_AT_RATE_CROSSOVER that prevents a +click artifact when crossing the nominal pitch from either positive to +negative side or vice versa
  • +
+

1.4.1:

+
    +
  • Fixed a buffer overflow bug in BPM detect algorithm routines if +processing more than 2048 samples at one call
  • +
+

1.4.0:

+
    +
  • Improved sound quality by automatic calculation of time stretch +algorithm processing parameters according to tempo setting
  • +
  • Moved BPM detection routines from SoundStretch application into +SoundTouch library
  • +
  • Bugfixes: Usage of uninitialied variables, GNU build scripts, +compiler errors due to 'const' keyword mismatch.
  • +
  • Source code cleanup
  • +
+

1.3.1:

+
    +
  • Changed static class declaration to GCC 4.x compiler compatible +syntax.
  • +
  • Enabled MMX/SSE-optimized routines also for GCC compilers. +Earlier the MMX/SSE-optimized routines were written in +compiler-specific inline assembler, now these routines are migrated to +use compiler intrinsic syntax which allows compiling the same +MMX/SSE-optimized source code with both Visual C++ and GCC compilers.
  • +
  • Set floating point as the default sample format and added switch +to the GNU configure script for selecting the other sample format.
  • +
+

1.3.0:

+
    +
  • Fixed tempo routine output duration inaccuracy due to rounding +error
  • +
  • Implemented separate processing routines for integer and +floating arithmetic to allow improvements to floating point routines +(earlier used algorithms mostly optimized for integer arithmetic also +for floating point samples)
  • +
  • Fixed a bug that distorts sound if sample rate changes during +the sound stream
  • +
  • Fixed a memory leak that appeared in MMX/SSE/3DNow! optimized +routines
  • +
  • Reduced redundant code pieces in MMX/SSE/3DNow! optimized +routines vs. the standard C routines.
  • +
  • MMX routine incompatibility with new gcc compiler versions
  • +
  • Other miscellaneous bug fixes
  • +
+

1.2.1:

+
    +
  • Added automake/autoconf scripts for GNU platforms (in courtesy +of David Durham)
  • +
  • Fixed SCALE overflow bug in rate transposer routine.
  • +
  • Fixed 64bit address space bugs.
  • +
  • Created a 'soundtouch' namespace for SAMPLETYPE definitions.
  • +
+

1.2.0:

+
    +
  • Added support for 32bit floating point sample data type with +SSE/3DNow! optimizations for Win32 platform (SSE/3DNow! optimizations +currently not supported in GCC environment)
  • +
  • Replaced 'make-gcc' script for GNU environment by master +Makefile
  • +
  • Added time-stretch routine configurability to SoundTouch main +class
  • +
  • Bugfixes
  • +
+

1.1.1:

+
    +
  • Moved SoundTouch under lesser GPL license (LGPL). This allows +using SoundTouch library in programs that aren't released under GPL +license.
  • +
  • Changed MMX routine organiation so that MMX optimized routines +are now implemented in classes that are derived from the basic classes +having the standard non-mmx routines.
  • +
  • MMX routines to support gcc version 3.
  • +
  • Replaced windows makefiles by script using the .dsw files
  • +
+

1.0.1:

+
    +
  • "mmx_gcc.cpp": Added "using namespace std" and removed "return +0" from a function with void return value to fix compiler errors when +compiling the library in Solaris environment.
  • +
  • Moved file "FIFOSampleBuffer.h" to "include" directory to allow +accessing the FIFOSampleBuffer class from external files.
  • +
+

1.0:

+
    +
  • Initial release
  • +
+

5.2. SoundStretch application Change History

+

1.9:

+
    +
  • Added support for WAV file 'fact' information chunk.
  • +
+ +

1.7.0:

+
    +
  • Bugfixes in Wavfile: exception string formatting, avoid getLengthMs() integer + precision overflow, support WAV files using 24/32bit sample format.
  • +
+

1.5.0:

+
    +
  • Added "-speech" switch to activate algorithm parameters more +suitable for speech processing than the default parameters tuned for +music processing.
  • +
+

1.4.0:

+
    +
  • Moved BPM detection routines from SoundStretch application into +SoundTouch library
  • +
  • Allow using standard input/output pipes as audio processing +input/output streams
  • +
+

1.3.0:

+
    +
  • Simplified accessing WAV files with floating point sample +format.
  • +
+

1.2.1:

+
    +
  • Fixed 64bit address space bugs.
  • +
+

1.2.0:

+
    +
  • Added support for 32bit floating point sample data type
  • +
  • Restructured the BPM routines into separate library
  • +
  • Fixed big-endian conversion bugs in WAV file routines (hopefully +:)
  • +
+

1.1.1:

+
    +
  • Fixed bugs in WAV file reading & added byte-order conversion +for big-endian processors.
  • +
  • Moved SoundStretch source code under 'example' directory to +highlight difference from SoundTouch stuff.
  • +
  • Replaced windows makefiles by script using the .dsw files
  • +
  • Output file name isn't required if output isn't desired (e.g. if +using the switch '-bpm' in plain format only)
  • +
+

1.1:

+
    +
  • Fixed "Release" settings in Microsoft Visual C++ project file +(.dsp)
  • +
  • Added beats-per-minute (BPM) detection routine and command-line +switch "-bpm"
  • +
+

1.01:

+
    +
  • Initial release
  • +
+
+

6. Acknowledgements

+

Kudos for these people who have contributed to development or +submitted bugfixes:

+
    +
  • Arthur A
  • +
  • Paul Adenot
  • +
  • Richard Ash
  • +
  • Stanislav Brabec
  • +
  • Christian Budde
  • +
  • Jamie Bullock
  • +
  • Chris Bryan
  • +
  • Jacek Caban
  • +
  • Brian Cameron
  • +
  • Jason Champion
  • +
  • David Clark
  • +
  • Patrick Colis
  • +
  • Miquel Colon
  • +
  • Jim Credland
  • +
  • Sandro Cumerlato
  • +
  • Gerry Fan
  • +
  • Justin Frankel
  • +
  • Masa H.
  • +
  • Jason Garland
  • +
  • Takashi Iwai
  • +
  • Thomas Klausner
  • +
  • Lu Zhihe
  • +
  • Luzpaz
  • +
  • Tony Mechelynck
  • +
  • Mathias Möhl
  • +
  • Yuval Naveh
  • +
  • Mats Palmgren
  • +
  • Chandni Patel
  • +
  • Paulo Pizarro
  • +
  • Andrey Ponomarenko
  • +
  • Blaise Potard
  • +
  • Michael Pruett
  • +
  • Rajeev Puran
  • +
  • RJ Ryan
  • +
  • John Sheehy
  • +
  • Tim Shuttleworth
  • +
  • Albert Sirvent
  • +
  • Tyson Smith
  • +
  • John Stumpo
  • +
  • Mario di Vece
  • +
  • Katja Vetter
  • +
  • Wu Q.
  • +
+

Moral greetings to all other contributors and users also!

+
+

7. LICENSE

+

SoundTouch audio processing library
+Copyright (c) Olli Parviainen

+

This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License version 2.1 +as published by the Free Software Foundation.

+

This library 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 library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

+

---

+

commercial license alternative also available, contact author for details.

+
+

README.html file updated in November-2018

+ + diff --git a/lib/soundtouch/SoundTouch.h b/lib/soundtouch/SoundTouch.h index f2addc1b0ae7..6f8f3061120c 100644 --- a/lib/soundtouch/SoundTouch.h +++ b/lib/soundtouch/SoundTouch.h @@ -72,10 +72,10 @@ namespace soundtouch { /// Soundtouch library version string -#define SOUNDTOUCH_VERSION "2.1" +#define SOUNDTOUCH_VERSION "2.1.1" /// SoundTouch library version id -#define SOUNDTOUCH_VERSION_ID (20100) +#define SOUNDTOUCH_VERSION_ID (20101) // // Available setting IDs for the 'setSetting' & 'get_setting' functions: diff --git a/lib/soundtouch/readme.md b/lib/soundtouch/readme.md index d6f8ef0b9e40..258543785654 100644 --- a/lib/soundtouch/readme.md +++ b/lib/soundtouch/readme.md @@ -9,6 +9,8 @@ same time Visit [SoundTouch website](https://www.surina.net/soundtouch) and see the [README file](README.html) for more information and audio examples. +### The latest stable release is 2.1.1, tagged in git as 2.1.1 + ## Example Use SoundStretch example app for modifying wav audio files, for example as follows: diff --git a/res/controllers/Allen and Heath Xone K2.midi.xml b/res/controllers/Allen and Heath Xone K2.midi.xml index 32e65f75a769..38784aae366a 100644 --- a/res/controllers/Allen and Heath Xone K2.midi.xml +++ b/res/controllers/Allen and Heath Xone K2.midi.xml @@ -20,7 +20,6 @@ If you are using K2s, they must have Latching Layers turned off, which is the de - diff --git a/res/controllers/Behringer CMD MM1.midi.xml b/res/controllers/Behringer CMD MM1.midi.xml index f2ef597384c5..be607902ac26 100644 --- a/res/controllers/Behringer CMD MM1.midi.xml +++ b/res/controllers/Behringer CMD MM1.midi.xml @@ -14,8 +14,6 @@ - - diff --git a/res/controllers/Denon-MC6000MK2.midi.xml b/res/controllers/Denon-MC6000MK2.midi.xml index 729520167014..51edac712f4c 100644 --- a/res/controllers/Denon-MC6000MK2.midi.xml +++ b/res/controllers/Denon-MC6000MK2.midi.xml @@ -8,7 +8,6 @@ - diff --git a/res/controllers/Hercules DJ Control Instinct.midi.xml b/res/controllers/Hercules DJ Control Instinct.midi.xml index 79f584b91be1..43e33c90cfb3 100644 --- a/res/controllers/Hercules DJ Control Instinct.midi.xml +++ b/res/controllers/Hercules DJ Control Instinct.midi.xml @@ -789,16 +789,6 @@ - - 0x80 - 0x41 - [Master] - headVolume - - - - - 0x90 0x1f @@ -1039,16 +1029,6 @@ - - 0x90 - 0x41 - [Master] - headVolume - - - - - diff --git a/res/controllers/Hercules P32 DJ.midi.xml b/res/controllers/Hercules P32 DJ.midi.xml index 203ac3aff2c6..436382baf89f 100644 --- a/res/controllers/Hercules P32 DJ.midi.xml +++ b/res/controllers/Hercules P32 DJ.midi.xml @@ -9,7 +9,6 @@ - diff --git a/res/controllers/Novation-Launchpad MK2-scripts.js b/res/controllers/Novation-Launchpad MK2-scripts.js index e3ef782c4a93..9549d60f5180 100644 --- a/res/controllers/Novation-Launchpad MK2-scripts.js +++ b/res/controllers/Novation-Launchpad MK2-scripts.js @@ -1,5 +1,4 @@ var NovationLaunchpadMK2 = (function () { -'use strict'; /* global engine, midi, script */ var engine_1 = engine; diff --git a/res/controllers/Novation-Launchpad-scripts.js b/res/controllers/Novation-Launchpad-scripts.js index 6c2be40bb02e..9d9042b9c6d1 100644 --- a/res/controllers/Novation-Launchpad-scripts.js +++ b/res/controllers/Novation-Launchpad-scripts.js @@ -1,5 +1,4 @@ var NovationLaunchpad = (function () { -'use strict'; /* global engine, midi, script */ var engine_1 = engine; diff --git a/res/controllers/Numark Mixtrack Platinum.midi.xml b/res/controllers/Numark Mixtrack Platinum.midi.xml new file mode 100644 index 000000000000..98be94b5ba4d --- /dev/null +++ b/res/controllers/Numark Mixtrack Platinum.midi.xml @@ -0,0 +1,2296 @@ + + + + Numark Mixtrack Platinum + Matthew Nicholson + Numark Mixtrack Platinum mapping with support for LCD screens and 4 deck playback. + https://www.mixxx.org/forums/viewtopic.php?f=7&t=8863 + https://www.mixxx.org/wiki/doku.php/numark_mixtrack_platinum + + + + + + + + + [Channel1] + MixtrackPlatinum.decks[1].pitch.inputLSB + pitch fader lsb + 0xB0 + 0x77 + + + + + + [Channel2] + MixtrackPlatinum.decks[2].pitch.inputLSB + pitch fader lsb + 0xB1 + 0x77 + + + + + + [Channel3] + MixtrackPlatinum.decks[3].pitch.inputLSB + pitch fader lsb + 0xB2 + 0x77 + + + + + + [Channel4] + MixtrackPlatinum.decks[4].pitch.inputLSB + pitch fader lsb + 0xB3 + 0x77 + + + + + + [Channel1] + MixtrackPlatinum.elapsedToggle + shift-wheel press to toggle time elapsed/remaining + 0x90 + 0x46 + + + + + + [Channel2] + MixtrackPlatinum.elapsedToggle + shift-wheel press to toggle time elapsed/remaining + 0x91 + 0x46 + + + + + + [Channel3] + MixtrackPlatinum.elapsedToggle + shift-wheel press to toggle time elapsed/remaining + 0x92 + 0x46 + + + + + + [Channel4] + MixtrackPlatinum.elapsedToggle + shift-wheel press to toggle time elapsed/remaining + 0x93 + 0x46 + + + + + + [Channel1] + MixtrackPlatinum.decks[1].manloop.loop_out.input + 0x94 + 0x39 + + + + + + [Channel2] + MixtrackPlatinum.decks[2].manloop.loop_out.input + 0x95 + 0x39 + + + + + + [Channel1] + MixtrackPlatinum.decks[1].manloop.loop_in.input + 0x94 + 0x38 + + + + + + [Channel3] + MixtrackPlatinum.decks[3].manloop.loop_out.input + 0x96 + 0x39 + + + + + + [Channel2] + MixtrackPlatinum.decks[2].manloop.loop_in.input + 0x95 + 0x38 + + + + + + [Channel4] + MixtrackPlatinum.decks[4].manloop.loop_out.input + 0x97 + 0x39 + + + + + + [Channel3] + MixtrackPlatinum.decks[3].manloop.loop_in.input + 0x96 + 0x38 + + + + + + [Channel4] + MixtrackPlatinum.decks[4].manloop.loop_in.input + 0x97 + 0x38 + + + + + + [Channel1] + MixtrackPlatinum.decks[1].manloop.loop_double.input + 0x94 + 0x35 + + + + + + [Channel2] + MixtrackPlatinum.decks[2].manloop.loop_double.input + 0x95 + 0x35 + + + + + + [Channel1] + MixtrackPlatinum.decks[1].manloop.loop_halve.input + 0x94 + 0x34 + + + + + + [Channel3] + MixtrackPlatinum.decks[3].manloop.loop_double.input + 0x96 + 0x35 + + + + + + [Channel2] + MixtrackPlatinum.decks[2].manloop.loop_halve.input + 0x95 + 0x34 + + + + + + [Channel4] + MixtrackPlatinum.decks[4].manloop.loop_double.input + 0x97 + 0x35 + + + + + + [Channel3] + MixtrackPlatinum.decks[3].manloop.loop_halve.input + 0x96 + 0x34 + + + + + + [Channel1] + MixtrackPlatinum.decks[1].manloop.loop_toggle.input + 0x94 + 0x32 + + + + + + [Channel4] + MixtrackPlatinum.decks[4].manloop.loop_halve.input + 0x97 + 0x34 + + + + + + [Channel2] + MixtrackPlatinum.decks[2].manloop.loop_toggle.input + 0x95 + 0x32 + + + + + + [Channel3] + MixtrackPlatinum.decks[3].manloop.loop_toggle.input + 0x96 + 0x32 + + + + + + [Channel4] + MixtrackPlatinum.decks[4].manloop.loop_toggle.input + 0x97 + 0x32 + + + + + + [Shift] + MixtrackPlatinum.shiftToggle + The shift key. + 0x9F + 0x32 + + + + + + [Channel1] + MixtrackPlatinum.decks[1].hotcues[4].input + 0x94 + 0x23 + + + + + + [Channel2] + MixtrackPlatinum.decks[2].hotcues[4].input + 0x95 + 0x23 + + + + + + [Channel1] + MixtrackPlatinum.decks[1].hotcues[3].input + 0x94 + 0x22 + + + + + + [Channel3] + MixtrackPlatinum.decks[3].hotcues[4].input + 0x96 + 0x23 + + + + + + [Channel2] + MixtrackPlatinum.decks[2].hotcues[3].input + 0x95 + 0x22 + + + + + + [Channel1] + MixtrackPlatinum.decks[1].hotcues[2].input + 0x94 + 0x21 + + + + + + [Sampler4] + MixtrackPlatinum.sampler[4].input + 0x9F + 0x2B + + + + + + [Channel4] + MixtrackPlatinum.decks[4].hotcues[4].input + 0x97 + 0x23 + + + + + + [Channel3] + MixtrackPlatinum.decks[3].hotcues[3].input + 0x96 + 0x22 + + + + + + [Channel2] + MixtrackPlatinum.decks[2].hotcues[2].input + 0x95 + 0x21 + + + + + + [Channel1] + MixtrackPlatinum.decks[1].hotcues[1].input + 0x94 + 0x20 + + + + + + [Sampler3] + MixtrackPlatinum.sampler[3].input + 0x9F + 0x2A + + + + + + [Channel4] + MixtrackPlatinum.decks[4].hotcues[3].input + 0x97 + 0x22 + + + + + + [Channel3] + MixtrackPlatinum.decks[3].hotcues[2].input + 0x96 + 0x21 + + + + + + [Channel2] + MixtrackPlatinum.decks[2].hotcues[1].input + 0x95 + 0x20 + + + + + + [Channel1] + MixtrackPlatinum.decks[1].autoloop.roll4.input + 0x94 + 0x1F + + + + + + [Channel1] + MixtrackPlatinum.decks[1].pfl_button.input + 0x90 + 0x1B + + + + + + [Sampler2] + MixtrackPlatinum.sampler[2].input + 0x9F + 0x29 + + + + + + [Channel4] + MixtrackPlatinum.decks[4].hotcues[2].input + 0x97 + 0x21 + + + + + + [Channel3] + MixtrackPlatinum.decks[3].hotcues[1].input + 0x96 + 0x20 + + + + + + [Channel2] + MixtrackPlatinum.decks[2].autoloop.roll4.input + 0x95 + 0x1F + + + + + + [Channel1] + MixtrackPlatinum.decks[1].autoloop.roll3.input + 0x94 + 0x1E + + + + + + [Channel2] + MixtrackPlatinum.decks[2].pfl_button.input + 0x91 + 0x1B + + + + + + [Sampler1] + MixtrackPlatinum.sampler[1].input + 0x9F + 0x28 + + + + + + [Channel4] + MixtrackPlatinum.decks[4].hotcues[1].input + 0x97 + 0x20 + + + + + + [Channel3] + MixtrackPlatinum.decks[3].autoloop.roll4.input + 0x96 + 0x1F + + + + + + [Channel2] + MixtrackPlatinum.decks[2].autoloop.roll3.input + 0x95 + 0x1E + + + + + + [Channel1] + MixtrackPlatinum.decks[1].autoloop.roll2.input + 0x94 + 0x1D + + + + + + [Channel3] + MixtrackPlatinum.decks[3].pfl_button.input + 0x92 + 0x1B + + + + + + [Channel1] + MixtrackPlatinum.deckSwitch + Fires when a deck is disabled. + 0x80 + 0x08 + + + + + + [Channel4] + MixtrackPlatinum.decks[4].autoloop.roll4.input + 0x97 + 0x1F + + + + + + [Channel3] + MixtrackPlatinum.decks[3].autoloop.roll3.input + 0x96 + 0x1E + + + + + + [Channel2] + MixtrackPlatinum.decks[2].autoloop.roll2.input + 0x95 + 0x1D + + + + + + [Channel1] + MixtrackPlatinum.decks[1].autoloop.roll1.input + 0x94 + 0x1C + + + + + + [Channel4] + MixtrackPlatinum.decks[4].pfl_button.input + 0x93 + 0x1B + + + + + + [Channel2] + MixtrackPlatinum.deckSwitch + Fires when a deck is disabled. + 0x81 + 0x08 + + + + + + [Channel4] + MixtrackPlatinum.decks[4].autoloop.roll3.input + 0x97 + 0x1E + + + + + + [Channel3] + MixtrackPlatinum.decks[3].autoloop.roll2.input + 0x96 + 0x1D + + + + + + [Channel2] + MixtrackPlatinum.decks[2].autoloop.roll1.input + 0x95 + 0x1C + + + + + + [Channel1] + MixtrackPlatinum.decks[1].hotcues[4].input + 0x94 + 0x1B + + + + + + [Channel3] + MixtrackPlatinum.deckSwitch + Fires when a deck is disabled. + 0x82 + 0x08 + + + + + + [Channel4] + MixtrackPlatinum.decks[4].autoloop.roll2.input + 0x97 + 0x1D + + + + + + [Channel3] + MixtrackPlatinum.decks[3].autoloop.roll1.input + 0x96 + 0x1C + + + + + + [Channel2] + MixtrackPlatinum.decks[2].hotcues[4].input + 0x95 + 0x1B + + + + + + [Channel1] + MixtrackPlatinum.decks[1].hotcues[3].input + 0x94 + 0x1A + + + + + + [Sampler4] + MixtrackPlatinum.sampler[4].input + 0x9F + 0x24 + + + + + + [Channel4] + MixtrackPlatinum.deckSwitch + Fires when a deck is disabled. + 0x83 + 0x08 + + + + + + [Channel4] + MixtrackPlatinum.decks[4].autoloop.roll1.input + 0x97 + 0x1C + + + + + + [Channel3] + MixtrackPlatinum.decks[3].hotcues[4].input + 0x96 + 0x1B + + + + + + [Channel2] + MixtrackPlatinum.decks[2].hotcues[3].input + 0x95 + 0x1A + + + + + + [Channel1] + MixtrackPlatinum.decks[1].hotcues[2].input + 0x94 + 0x19 + + + + + + [Channel1] + MixtrackPlatinum.decks[1].hotcues[1].input + 0x94 + 0x18 + + + + + + [Sampler3] + MixtrackPlatinum.sampler[3].input + 0x9F + 0x23 + + + + + + [Channel4] + MixtrackPlatinum.decks[4].hotcues[4].input + 0x97 + 0x1B + + + + + + [Channel3] + MixtrackPlatinum.decks[3].hotcues[3].input + 0x96 + 0x1A + + + + + + [Channel2] + MixtrackPlatinum.decks[2].hotcues[2].input + 0x95 + 0x19 + + + + + + [Channel3] + MixtrackPlatinum.decks[3].hotcues[2].input + 0x96 + 0x19 + + + + + + [Channel2] + MixtrackPlatinum.decks[2].hotcues[1].input + 0x95 + 0x18 + + + + + + [Channel1] + MixtrackPlatinum.decks[1].autoloop.auto4.input + 0x94 + 0x17 + + + + + + [Sampler2] + MixtrackPlatinum.sampler[2].input + 0x9F + 0x22 + + + + + + [Channel4] + MixtrackPlatinum.decks[4].hotcues[3].input + 0x97 + 0x1A + + + + + + [Channel4] + MixtrackPlatinum.decks[4].hotcues[2].input + 0x97 + 0x19 + + + + + + [Channel3] + MixtrackPlatinum.decks[3].hotcues[1].input + 0x96 + 0x18 + + + + + + [Channel2] + MixtrackPlatinum.decks[2].autoloop.auto4.input + 0x95 + 0x17 + + + + + + [Channel1] + MixtrackPlatinum.decks[1].autoloop.auto3.input + 0x94 + 0x16 + + + + + + [Sampler1] + MixtrackPlatinum.sampler[1].input + 0x9F + 0x21 + + + + + + [Channel4] + MixtrackPlatinum.decks[4].hotcues[1].input + 0x97 + 0x18 + + + + + + [Channel3] + MixtrackPlatinum.decks[3].autoloop.auto4.input + 0x96 + 0x17 + + + + + + [Channel2] + MixtrackPlatinum.decks[2].autoloop.auto3.input + 0x95 + 0x16 + + + + + + [Channel1] + MixtrackPlatinum.decks[1].autoloop.auto2.input + 0x94 + 0x15 + + + + + + [Channel4] + MixtrackPlatinum.decks[4].autoloop.auto4.input + 0x97 + 0x17 + + + + + + [Channel3] + MixtrackPlatinum.decks[3].autoloop.auto3.input + 0x96 + 0x16 + + + + + + [Channel2] + MixtrackPlatinum.decks[2].autoloop.auto2.input + 0x95 + 0x15 + + + + + + [Channel1] + MixtrackPlatinum.decks[1].autoloop.auto1.input + 0x94 + 0x14 + + + + + + [Channel1] + MixtrackPlatinum.decks[1].load.input + 0x90 + 0x10 + + + + + + [Channel4] + MixtrackPlatinum.decks[4].autoloop.auto3.input + 0x97 + 0x16 + + + + + + [Channel3] + MixtrackPlatinum.decks[3].autoloop.auto2.input + 0x96 + 0x15 + + + + + + [Channel2] + MixtrackPlatinum.decks[2].autoloop.auto1.input + 0x95 + 0x14 + + + + + + [Channel2] + MixtrackPlatinum.decks[2].load.input + 0x91 + 0x10 + + + + + + [Channel4] + MixtrackPlatinum.decks[4].autoloop.auto2.input + 0x97 + 0x15 + + + + + + [Channel3] + MixtrackPlatinum.decks[3].autoloop.auto1.input + 0x96 + 0x14 + + + + + + [Channel3] + MixtrackPlatinum.decks[3].load.input + 0x92 + 0x10 + + + + + + [Channel4] + MixtrackPlatinum.decks[4].autoloop.auto1.input + 0x97 + 0x14 + + + + + + [Channel1] + playposition + 0xB0 + 0x2D + + + + + + [Channel4] + MixtrackPlatinum.decks[4].load.input + 0x93 + 0x10 + + + + + + [Channel2] + playposition + 0xB1 + 0x2D + + + + + + [Channel1] + MixtrackPlatinum.decks[1].pitch_bend_down.input + 0x90 + 0x0C + + + + + + [Channel3] + playposition + 0xB2 + 0x2D + + + + + + [Channel2] + MixtrackPlatinum.decks[2].pitch_bend_down.input + 0x91 + 0x0C + + + + + + [Channel1] + MixtrackPlatinum.decks[1].pitch_bend_up.input + 0x90 + 0x0B + + + + + + [Channel4] + playposition + 0xB3 + 0x2D + + + + + + [Channel3] + MixtrackPlatinum.decks[3].pitch_bend_down.input + 0x92 + 0x0C + + + + + + [Channel2] + MixtrackPlatinum.decks[2].pitch_bend_up.input + 0x91 + 0x0B + + + + + + [Channel4] + MixtrackPlatinum.decks[4].pitch_bend_down.input + 0x93 + 0x0C + + + + + + [Channel3] + MixtrackPlatinum.decks[3].pitch_bend_up.input + 0x92 + 0x0B + + + + + + [Channel4] + MixtrackPlatinum.decks[4].pitch_bend_up.input + 0x93 + 0x0B + + + + + + [Channel1] + MixtrackPlatinum.decks[1].key_down.input + 0x90 + 0x2C + + + + + + [Channel2] + MixtrackPlatinum.decks[2].key_down.input + 0x91 + 0x2C + + + + + + [Channel3] + MixtrackPlatinum.decks[3].key_down.input + 0x92 + 0x2C + + + + + + [Channel4] + MixtrackPlatinum.decks[4].key_down.input + 0x93 + 0x2C + + + + + + [Channel1] + MixtrackPlatinum.decks[1].key_up.input + 0x90 + 0x2B + + + + + + [Channel2] + MixtrackPlatinum.decks[2].key_up.input + 0x91 + 0x2B + + + + + + [Channel3] + MixtrackPlatinum.decks[3].key_up.input + 0x92 + 0x2B + + + + + + [Channel4] + MixtrackPlatinum.decks[4].key_up.input + 0x93 + 0x2B + + + + + + [Channel1] + MixtrackPlatinum.deckSwitch + Fires when a deck is activated. + 0x90 + 0x08 + + + + + + [Channel1] + MixtrackPlatinum.wheelToggle + wheel button to toggle vinyl mode + 0x90 + 0x07 + + + + + + [Channel2] + MixtrackPlatinum.deckSwitch + Fires when a deck is activated. + 0x91 + 0x08 + + + + + + [Channel2] + MixtrackPlatinum.wheelToggle + wheel button to toggle vinyl mode + 0x91 + 0x07 + + + + + + [Channel3] + MixtrackPlatinum.deckSwitch + Fires when a deck is activated. + 0x92 + 0x08 + + + + + + [Channel1] + MixtrackPlatinum.wheelTouch + 0x90 + 0x06 + + + + + + [Channel3] + MixtrackPlatinum.wheelToggle + wheel button to toggle vinyl mode + 0x92 + 0x07 + + + + + + [Channel4] + MixtrackPlatinum.deckSwitch + Fires when a deck is activated. + 0x93 + 0x08 + + + + + + [Channel2] + MixtrackPlatinum.wheelTouch + 0x91 + 0x06 + + + + + + [Channel1] + MixtrackPlatinum.decks[1].cue_button.input + 0x90 + 0x05 + + + + + + [EffectRack1_EffectUnit1_Effect3] + MixtrackPlatinum.effects[1].enableButtons[3].input + shift fx3 + 0x98 + 0x0D + + + + + + [Channel4] + MixtrackPlatinum.wheelToggle + wheel button to toggle vinyl mode + 0x93 + 0x07 + + + + + + [Channel3] + MixtrackPlatinum.wheelTouch + 0x92 + 0x06 + + + + + + [Channel2] + MixtrackPlatinum.decks[2].cue_button.input + 0x91 + 0x05 + + + + + + [Channel1] + MixtrackPlatinum.decks[1].play_button.input + 0x90 + 0x04 + + + + + + [EffectRack1_EffectUnit1_Effect2] + MixtrackPlatinum.effects[1].enableButtons[2].input + shift fx2 + 0x98 + 0x0C + + + + + + [EffectRack1_EffectUnit2_Effect3] + MixtrackPlatinum.effects[2].enableButtons[3].input + shift fx3 + 0x99 + 0x0D + + + + + + [Channel4] + MixtrackPlatinum.wheelTouch + 0x93 + 0x06 + + + + + + [Channel3] + MixtrackPlatinum.decks[3].cue_button.input + 0x92 + 0x05 + + + + + + [Channel2] + MixtrackPlatinum.decks[2].play_button.input + 0x91 + 0x04 + + + + + + [EffectRack1_EffectUnit1_Effect1] + MixtrackPlatinum.effects[1].enableButtons[1].input + shift fx1 + 0x98 + 0x0B + + + + + + [EffectRack1_EffectUnit2_Effect2] + MixtrackPlatinum.effects[2].enableButtons[2].input + shift fx2 + 0x99 + 0x0C + + + + + + [Channel1] + MixtrackPlatinum.decks[1].sync_button.input + 0x90 + 0x02 + + + + + + [Channel1] + MixtrackPlatinum.decks[1].sync_button.input + 0x90 + 0x03 + + + + + + [Channel4] + MixtrackPlatinum.decks[4].cue_button.input + 0x93 + 0x05 + + + + + + [Channel3] + MixtrackPlatinum.decks[3].play_button.input + 0x92 + 0x04 + + + + + + [EffectRack1_EffectUnit2_Effect1] + MixtrackPlatinum.effects[2].enableButtons[1].input + shift fx1 + 0x99 + 0x0B + + + + + + [Channel2] + MixtrackPlatinum.decks[2].sync_button.input + 0x91 + 0x02 + + + + + + [Channel2] + MixtrackPlatinum.decks[2].sync_button.input + 0x91 + 0x03 + + + + + + [Channel1] + MixtrackPlatinum.decks[1].cue_button.input + 0x90 + 0x01 + + + + + + [Channel4] + MixtrackPlatinum.decks[4].play_button.input + 0x93 + 0x04 + + + + + + [Channel3] + MixtrackPlatinum.decks[3].sync_button.input + 0x92 + 0x02 + + + + + + [Channel3] + MixtrackPlatinum.decks[3].sync_button.input + 0x92 + 0x03 + + + + + + [Channel2] + MixtrackPlatinum.decks[2].cue_button.input + 0x91 + 0x01 + + + + + + [Channel1] + MixtrackPlatinum.decks[1].play_button.input + 0x90 + 0x00 + + + + + + [Channel4] + MixtrackPlatinum.decks[4].sync_button.input + 0x93 + 0x02 + + + + + + [Channel4] + MixtrackPlatinum.decks[4].sync_button.input + 0x93 + 0x03 + + + + + + [Channel3] + MixtrackPlatinum.decks[3].cue_button.input + 0x92 + 0x01 + + + + + + [Channel2] + MixtrackPlatinum.decks[2].play_button.input + 0x91 + 0x00 + + + + + + [Channel4] + MixtrackPlatinum.decks[4].cue_button.input + 0x93 + 0x01 + + + + + + [Channel3] + MixtrackPlatinum.decks[3].play_button.input + 0x92 + 0x00 + + + + + + [Channel4] + MixtrackPlatinum.decks[4].play_button.input + 0x93 + 0x00 + + + + + + [Channel1] + volume + 0xB0 + 0x1C + + + + + + [Channel1] + MixtrackPlatinum.effects[1].bpmTap.input + 0x98 + 0x04 + + + + + + [Channel2] + volume + 0xB1 + 0x1C + + + + + + [Channel2] + MixtrackPlatinum.effects[2].bpmTap.input + 0x99 + 0x04 + + + + + + [Channel3] + volume + 0xB2 + 0x1C + + + + + + [QuickEffectRack1_[Channel1]] + MixtrackPlatinum.decks[1].filter.input + 0xB0 + 0x1A + + + + + + [EffectRack1_EffectUnit1_Effect3] + MixtrackPlatinum.effects[1].enableButtons[3].input + 0x98 + 0x02 + + + + + + [Channel4] + volume + 0xB3 + 0x1C + + + + + + [QuickEffectRack1_[Channel2]] + MixtrackPlatinum.decks[2].filter.input + 0xB1 + 0x1A + + + + + + [EqualizerRack1_[Channel1]_Effect1] + MixtrackPlatinum.decks[1].low_eq.input + 0xB0 + 0x19 + + + + + + [EffectRack1_EffectUnit1_Effect2] + MixtrackPlatinum.effects[1].enableButtons[2].input + 0x98 + 0x01 + + + + + + [EffectRack1_EffectUnit2_Effect3] + MixtrackPlatinum.effects[2].enableButtons[3].input + 0x99 + 0x02 + + + + + + [QuickEffectRack1_[Channel3]] + MixtrackPlatinum.decks[3].filter.input + 0xB2 + 0x1A + + + + + + [EqualizerRack1_[Channel2]_Effect1] + MixtrackPlatinum.decks[2].low_eq.input + 0xB1 + 0x19 + + + + + + [EqualizerRack1_[Channel1]_Effect1] + MixtrackPlatinum.decks[1].mid_eq.input + 0xB0 + 0x18 + + + + + + [EffectRack1_EffectUnit1_Effect1] + MixtrackPlatinum.effects[1].enableButtons[1].input + 0x98 + 0x00 + + + + + + [EffectRack1_EffectUnit2_Effect2] + MixtrackPlatinum.effects[2].enableButtons[2].input + 0x99 + 0x01 + + + + + + [QuickEffectRack1_[Channel4]] + MixtrackPlatinum.decks[4].filter.input + 0xB3 + 0x1A + + + + + + [EqualizerRack1_[Channel3]_Effect1] + MixtrackPlatinum.decks[3].low_eq.input + 0xB2 + 0x19 + + + + + + [EqualizerRack1_[Channel2]_Effect1] + MixtrackPlatinum.decks[2].mid_eq.input + 0xB1 + 0x18 + + + + + + [EqualizerRack1_[Channel1]_Effect1] + MixtrackPlatinum.decks[1].high_eq.input + 0xB0 + 0x17 + + + + + + [EffectRack1_EffectUnit2_Effect1] + MixtrackPlatinum.effects[2].enableButtons[1].input + 0x99 + 0x00 + + + + + + [EqualizerRack1_[Channel4]_Effect1] + MixtrackPlatinum.decks[4].low_eq.input + 0xB3 + 0x19 + + + + + + [EqualizerRack1_[Channel3]_Effect1] + MixtrackPlatinum.decks[3].mid_eq.input + 0xB2 + 0x18 + + + + + + [EqualizerRack1_[Channel2]_Effect1] + MixtrackPlatinum.decks[2].high_eq.input + 0xB1 + 0x17 + + + + + + [Channel1] + MixtrackPlatinum.decks[1].gain.input + 0xB0 + 0x16 + + + + + + [EqualizerRack1_[Channel4]_Effect1] + MixtrackPlatinum.decks[4].mid_eq.input + 0xB3 + 0x18 + + + + + + [EqualizerRack1_[Channel3]_Effect1] + MixtrackPlatinum.decks[3].high_eq.input + 0xB2 + 0x17 + + + + + + [Channel2] + MixtrackPlatinum.decks[2].gain.input + 0xB1 + 0x16 + + + + + + [EqualizerRack1_[Channel4]_Effect1] + MixtrackPlatinum.decks[4].high_eq.input + 0xB3 + 0x17 + + + + + + [Channel3] + MixtrackPlatinum.decks[3].gain.input + 0xB2 + 0x16 + + + + + + [Channel4] + MixtrackPlatinum.decks[4].gain.input + 0xB3 + 0x16 + + + + + + [Channel1] + MixtrackPlatinum.decks[1].pitch.inputMSB + pitch fader msb + 0xB0 + 0x09 + + + + + + [Channel2] + MixtrackPlatinum.decks[2].pitch.inputMSB + pitch fader msb + 0xB1 + 0x09 + + + + + + [Channel3] + MixtrackPlatinum.decks[3].pitch.inputMSB + pitch fader msb + 0xB2 + 0x09 + + + + + + [Channel1] + MixtrackPlatinum.wheelTurn + 0xB0 + 0x06 + + + + + + [Channel4] + MixtrackPlatinum.decks[4].pitch.inputMSB + pitch fader msb + 0xB3 + 0x09 + + + + + + [Channel2] + MixtrackPlatinum.wheelTurn + 0xB1 + 0x06 + + + + + + [Channel3] + MixtrackPlatinum.wheelTurn + 0xB2 + 0x06 + + + + + + [Channel4] + MixtrackPlatinum.wheelTurn + 0xB3 + 0x06 + + + + + + [Master] + headMix + 0xBF + 0x0D + + + + + + [Master] + MixtrackPlatinum.head_gain.input + 0xBF + 0x0C + + + + + + [Master] + volume + 0xBF + 0x0A + + + + + + [Master] + crossfader + 0xBF + 0x08 + + + + + + [EffectRack1_EffectUnit1_Effect1] + MixtrackPlatinum.effects[1].touch_strip.input + 0xB8 + 0x00 + + + + + + [EffectRack1_EffectUnit2_Effect1] + MixtrackPlatinum.effects[2].touch_strip.input + 0xB9 + 0x00 + + + + + + [Library] + MixtrackPlatinum.browse.knob.input + 0xBF + 0x00 + + + + + + [Library] + MixtrackPlatinum.browse.button.input + 0x9F + 0x1F + + + + + + [EffectRack1_EffectUnit1] + MixtrackPlatinum.effects[1].dryWetKnob.input + 0xB8 + 0x03 + + + + + + [EffectRack1_EffectUnit2] + MixtrackPlatinum.effects[2].dryWetKnob.input + 0xB9 + 0x03 + + + + + + [Channel1] + MixtrackPlatinum.decks[1].pad_mode.input + 0x94 + 0x0E + + + + + + [Channel1] + MixtrackPlatinum.decks[1].pad_mode.input + 0x94 + 0x06 + + + + + + [Channel1] + MixtrackPlatinum.decks[1].pad_mode.input + 0x94 + 0x0B + + + + + + [Channel2] + MixtrackPlatinum.decks[2].pad_mode.input + 0x95 + 0x0E + + + + + + [Channel2] + MixtrackPlatinum.decks[2].pad_mode.input + 0x95 + 0x06 + + + + + + [Channel2] + MixtrackPlatinum.decks[2].pad_mode.input + 0x95 + 0x0B + + + + + + [Channel3] + MixtrackPlatinum.decks[3].pad_mode.input + 0x96 + 0x0E + + + + + + [Channel3] + MixtrackPlatinum.decks[3].pad_mode.input + 0x96 + 0x06 + + + + + + [Channel3] + MixtrackPlatinum.decks[3].pad_mode.input + 0x96 + 0x0B + + + + + + [Channel4] + MixtrackPlatinum.decks[4].pad_mode.input + 0x97 + 0x0E + + + + + + [Channel4] + MixtrackPlatinum.decks[4].pad_mode.input + 0x97 + 0x06 + + + + + + [Channel4] + MixtrackPlatinum.decks[4].pad_mode.input + 0x97 + 0x0B + + + + + + + + [Channel2] + slip_enabled + 0x81 + 0x0F + 0.5 + + + [Channel2] + slip_enabled + 0x91 + 0x0F + 0.5 + + + [Channel4] + keylock + 0x83 + 0x0D + 0.5 + + + [Channel4] + keylock + 0x93 + 0x0D + 0.5 + + + [Channel1] + slip_enabled + 0x80 + 0x0F + 0.5 + + + [Channel1] + slip_enabled + 0x90 + 0x0F + 0.5 + + + [Channel3] + keylock + 0x82 + 0x0D + 0.5 + + + [Channel3] + keylock + 0x92 + 0x0D + 0.5 + + + [Channel4] + slip_enabled + 0x83 + 0x0F + 0.5 + + + [Channel4] + slip_enabled + 0x93 + 0x0F + 0.5 + + + [Channel2] + keylock + 0x81 + 0x0D + 0.5 + + + [Channel2] + keylock + 0x91 + 0x0D + 0.5 + + + [Channel3] + slip_enabled + 0x82 + 0x0F + 0.5 + + + [Channel3] + slip_enabled + 0x92 + 0x0F + 0.5 + + + [Channel1] + keylock + 0x80 + 0x0D + 0.5 + + + [Channel1] + keylock + 0x90 + 0x0D + 0.5 + + + + diff --git a/res/controllers/Numark N4.midi.xml b/res/controllers/Numark N4.midi.xml index d030912476a5..ba77ca7e3b76 100644 --- a/res/controllers/Numark N4.midi.xml +++ b/res/controllers/Numark N4.midi.xml @@ -7,8 +7,6 @@ - - diff --git a/res/controllers/Numark-Mixtrack-Platinum-scripts.js b/res/controllers/Numark-Mixtrack-Platinum-scripts.js new file mode 100644 index 000000000000..7b523bdb5e67 --- /dev/null +++ b/res/controllers/Numark-Mixtrack-Platinum-scripts.js @@ -0,0 +1,1453 @@ +//////////////////////////////////////////////////////////////////////// +// JSHint configuration // +//////////////////////////////////////////////////////////////////////// +/* global engine */ +/* global script */ +/* global print */ +/* global midi */ +//////////////////////////////////////////////////////////////////////// + + +/****************** + * CONFIG OPTIONS * + ******************/ + +// should wheel be enabled on startup? +var EnableWheel = true; + +// should we use the manual loop buttons as hotcue buttons 5-8? +var UseManualLoopAsCue = false; + +// should we use the auto loop buttons as hotcue buttons 5-8? +var UseAutoLoopAsCue = false; + +// should we use the hotcue buttons for samplers 5-8? +var UseCueAsSampler = false; + +// should shift+load eject or load and play? +var ShiftLoadEjects = false; + +// should we show effect parameters when an effect is focused? +var ShowFocusedEffectParameters = false; + + +var MixtrackPlatinum = {}; + +MixtrackPlatinum.init = function(id, debug) { + MixtrackPlatinum.id = id; + MixtrackPlatinum.debug = debug; + + // effects + MixtrackPlatinum.effects = new components.ComponentContainer(); + MixtrackPlatinum.effects[1] = new MixtrackPlatinum.EffectUnit([1, 3]); + MixtrackPlatinum.effects[2] = new MixtrackPlatinum.EffectUnit([2, 4]); + + // decks + MixtrackPlatinum.decks = new components.ComponentContainer(); + MixtrackPlatinum.decks[1] = new MixtrackPlatinum.Deck(1, 0x00, MixtrackPlatinum.effects[1]); + MixtrackPlatinum.decks[2] = new MixtrackPlatinum.Deck(2, 0x01, MixtrackPlatinum.effects[2]); + MixtrackPlatinum.decks[3] = new MixtrackPlatinum.Deck(3, 0x02, MixtrackPlatinum.effects[1]); + MixtrackPlatinum.decks[4] = new MixtrackPlatinum.Deck(4, 0x03, MixtrackPlatinum.effects[2]); + + // set up two banks of samplers, 4 samplers each + MixtrackPlatinum.sampler_all = new components.ComponentContainer(); + MixtrackPlatinum.sampler_all[1] = new MixtrackPlatinum.Sampler(1); + MixtrackPlatinum.sampler_all[2] = new MixtrackPlatinum.Sampler(5); + + MixtrackPlatinum.sampler = MixtrackPlatinum.sampler_all[1]; + MixtrackPlatinum.sampler_all[2].forEachComponent(function(component) { + component.disconnect(); + }); + + + // headphone gain + MixtrackPlatinum.head_gain = new MixtrackPlatinum.HeadGain(MixtrackPlatinum.sampler_all); + + // exit demo mode + var byteArray = [0xF0, 0x00, 0x01, 0x3F, 0x7F, 0x3A, 0x60, 0x00, 0x04, 0x04, 0x01, 0x00, 0x00, 0xF7]; + midi.sendSysexMsg(byteArray, byteArray.length); + + // initialize some leds + MixtrackPlatinum.effects.forEachComponent(function (component) { + component.trigger(); + }); + MixtrackPlatinum.decks.forEachComponent(function (component) { + component.trigger(); + }); + + MixtrackPlatinum.browse = new MixtrackPlatinum.BrowseKnob(); + + // helper functions + var led = function(group, key, midi_channel, midino) { + if (engine.getValue(group, key)) { + midi.sendShortMsg(0x90 | midi_channel, midino, 0x7F); + } + else { + midi.sendShortMsg(0x80 | midi_channel, midino, 0x00); + } + }; + + // init a bunch of channel specific leds + for (var i = 0; i < 4; ++i) { + var group = "[Channel"+(i+1)+"]"; + + // keylock indicator + led(group, 'keylock', i, 0x0D); + + // turn off bpm arrows + midi.sendShortMsg(0x80 | i, 0x0A, 0x00); // down arrow off + midi.sendShortMsg(0x80 | i, 0x09, 0x00); // up arrow off + + // slip indicator + led(group, 'slip_enabled', i, 0x0F); + + // initialize wheel mode (and leds) + MixtrackPlatinum.wheel[i] = EnableWheel; + midi.sendShortMsg(0x90 | i, 0x07, EnableWheel ? 0x7F : 0x01); + } + + // zero vu meters + midi.sendShortMsg(0xBF, 0x44, 0); + midi.sendShortMsg(0xBF, 0x45, 0); + + // setup elapsed/remaining tracking + engine.makeConnection("[Controls]", "ShowDurationRemaining", MixtrackPlatinum.timeElapsedCallback); + + // setup vumeter tracking + engine.makeConnection("[Channel1]", "VuMeter", MixtrackPlatinum.vuCallback); + engine.makeConnection("[Channel2]", "VuMeter", MixtrackPlatinum.vuCallback); + engine.makeConnection("[Channel3]", "VuMeter", MixtrackPlatinum.vuCallback); + engine.makeConnection("[Channel4]", "VuMeter", MixtrackPlatinum.vuCallback); + engine.makeConnection("[Master]", "VuMeterL", MixtrackPlatinum.vuCallback); + engine.makeConnection("[Master]", "VuMeterR", MixtrackPlatinum.vuCallback); +}; + +MixtrackPlatinum.shutdown = function() { + // note: not all of this appears to be strictly necessary, things work fine + // with out this, but Serato has been observed sending these led reset + // messages during shutdown. The last sysex message may be necessary to + // re-enable demo mode. + + // turn off a bunch of channel specific leds + for (var i = 0; i < 4; ++i) { + // pfl/cue button leds + midi.sendShortMsg(0x90 | i, 0x1B, 0x01); + + // loop leds + midi.sendShortMsg(0x80 | i + 5, 0x32, 0x00); + midi.sendShortMsg(0x80 | i + 5, 0x33, 0x00); + midi.sendShortMsg(0x80 | i + 5, 0x34, 0x00); + midi.sendShortMsg(0x80 | i + 5, 0x35, 0x00); + midi.sendShortMsg(0x80 | i + 5, 0x38, 0x00); + midi.sendShortMsg(0x80 | i + 5, 0x39, 0x00); + + // play leds + midi.sendShortMsg(0x90 | i, 0x00, 0x01); + midi.sendShortMsg(0x90 | i, 0x04, 0x01); + + // sync leds + midi.sendShortMsg(0x90 | i, 0x00, 0x02); + midi.sendShortMsg(0x90 | i, 0x04, 0x03); + + // cue leds + midi.sendShortMsg(0x90 | i, 0x00, 0x01); + midi.sendShortMsg(0x90 | i, 0x04, 0x05); + + // hotcue leds + midi.sendShortMsg(0x80 | i + 5, 0x18, 0x00); + midi.sendShortMsg(0x80 | i + 5, 0x19, 0x00); + midi.sendShortMsg(0x80 | i + 5, 0x1A, 0x00); + midi.sendShortMsg(0x80 | i + 5, 0x1B, 0x00); + midi.sendShortMsg(0x80 | i + 5, 0x20, 0x00); + midi.sendShortMsg(0x80 | i + 5, 0x21, 0x00); + midi.sendShortMsg(0x80 | i + 5, 0x22, 0x00); + midi.sendShortMsg(0x80 | i + 5, 0x23, 0x00); + + // auto-loop leds + midi.sendShortMsg(0x80 | i + 5, 0x14, 0x00); + midi.sendShortMsg(0x80 | i + 5, 0x15, 0x00); + midi.sendShortMsg(0x80 | i + 5, 0x16, 0x00); + midi.sendShortMsg(0x80 | i + 5, 0x17, 0x00); + midi.sendShortMsg(0x80 | i + 5, 0x1C, 0x00); + midi.sendShortMsg(0x80 | i + 5, 0x1D, 0x00); + midi.sendShortMsg(0x80 | i + 5, 0x1E, 0x00); + midi.sendShortMsg(0x80 | i + 5, 0x1F, 0x00); + + // update spinner and position indicator + midi.sendShortMsg(0xB0 | i, 0x3F, 0); + midi.sendShortMsg(0xB0 | i, 0x06, 0); + + // keylock indicator + midi.sendShortMsg(0x80 | i, 0x0D, 0x00); + + // turn off bpm arrows + midi.sendShortMsg(0x80 | i, 0x0A, 0x00); // down arrow off + midi.sendShortMsg(0x80 | i, 0x09, 0x00); // up arrow off + + // turn off slip indicator + midi.sendShortMsg(0x80 | i, 0x0F, 0x00); + + // turn off wheel button leds + midi.sendShortMsg(0x80 | i, 0x07, 0x00); + } + + // dim FX leds + midi.sendShortMsg(0x98, 0x00, 0x01); + midi.sendShortMsg(0x98, 0x01, 0x01); + midi.sendShortMsg(0x98, 0x02, 0x01); + midi.sendShortMsg(0x99, 0x00, 0x01); + midi.sendShortMsg(0x99, 0x01, 0x01); + midi.sendShortMsg(0x99, 0x02, 0x01); + + // turn off sampler leds + midi.sendShortMsg(0x8F, 0x21, 0x00); + midi.sendShortMsg(0x8F, 0x22, 0x00); + midi.sendShortMsg(0x8F, 0x23, 0x00); + midi.sendShortMsg(0x8F, 0x24, 0x00); + + // zero vu meters + midi.sendShortMsg(0xBF, 0x44, 0); + midi.sendShortMsg(0xBF, 0x45, 0); + + // send final shutdown message + var byteArray = [0xF0, 0x00, 0x20, 0x7F, 0x02, 0xF7]; + midi.sendSysexMsg(byteArray, byteArray.length); +}; + +MixtrackPlatinum.EffectUnit = function (unitNumbers) { + var eu = this; + this.unitNumbers = unitNumbers; + + this.setCurrentUnit = function (newNumber) { + this.currentUnitNumber = newNumber; + this.group = '[EffectRack1_EffectUnit' + newNumber + ']'; + this.reconnectComponents(function (component) { + // update [EffectRack1_EffectUnitX] groups + var unitMatch = component.group.match(script.effectUnitRegEx); + if (unitMatch !== null) { + component.group = eu.group; + } else { + // update [EffectRack1_EffectUnitX_EffectY] groups + var effectMatch = component.group.match(script.individualEffectRegEx); + if (effectMatch !== null) { + component.group = '[EffectRack1_EffectUnit' + + eu.currentUnitNumber + + '_Effect' + effectMatch[2] + ']'; + } + } + }); + }; + + this.setCurrentUnit(unitNumbers[0]); + + this.dryWetKnob = new components.Encoder({ + group: this.group, + inKey: 'mix', + input: function (channel, control, value, status, group) { + if (value === 1) { + this.inSetParameter(this.inGetParameter() + 0.05); + } else if (value === 127) { + this.inSetParameter(this.inGetParameter() - 0.05); + } + }, + }); + + this.EffectUnitTouchStrip = function() { + components.Pot.call(this); + this.firstValueRecived = true; + this.connect(); + }; + this.EffectUnitTouchStrip.prototype = new components.Pot({ + relative: true, // this disables soft takeover + input: function (channel, control, value, status, group) { + // never do soft takeover when the touchstrip is used + engine.softTakeover(this.group, this.inKey, false); + components.Pot.prototype.input.call(this, channel, control, value, status, group); + }, + connect: function() { + this.focus_connection = engine.makeConnection(eu.group, "focused_effect", this.onFocusChange); + this.focus_connection.trigger(); + }, + disconnect: function() { + this.focus_connection.disconnect(); + }, + onFocusChange: function(value, group, control) { + if (value === 0) { + this.group = eu.group; + this.inKey = 'super1'; + } + else { + this.group = '[EffectRack1_EffectUnit' + eu.currentUnitNumber + '_Effect' + value + ']'; + this.inKey = 'meta'; + } + }, + }); + + this.BpmTapButton = function () { + this.group = '[Channel' + eu.currentUnitNumber + ']'; + this.midi = [0x97 + eu.currentUnitNumber, 0x04]; + components.Button.call(this); + }; + this.BpmTapButton.prototype = new components.Button({ + type: components.Button.prototype.types.push, + key: 'bpm_tap', + off: 0x01, + connect: function () { + this.group = '[Channel' + eu.currentUnitNumber + ']'; + components.Button.prototype.connect.call(this); + }, + input: function (channel, control, value, status, group) { + components.Button.prototype.input.call(this, channel, control, value, status, group); + if (this.isPress(channel, control, value, status)) { + eu.forEachComponent(function (component) { + if (component.tap !== undefined && typeof component.tap === 'function') { + component.tap(); + } + }); + } + else { + eu.forEachComponent(function (component) { + if (component.untap !== undefined) { + component.untap(); + } + }); + } + }, + }); + + this.EffectEnableButton = function (number) { + this.number = number; + this.group = '[EffectRack1_EffectUnit' + eu.currentUnitNumber + + '_Effect' + this.number + ']'; + this.midi = [0x97 + eu.currentUnitNumber, this.number - 1]; + this.flash_timer = null; + + components.Button.call(this); + }; + this.EffectEnableButton.prototype = new components.Button({ + type: components.Button.prototype.types.powerWindow, + outKey: 'enabled', + inKey: 'enabled', + off: 0x01, + tap: function() { + this.inKey = 'enabled'; + this.type = components.Button.prototype.types.toggle; + this.inToggle = this.toggle_focused_effect; + }, + untap: function() { + this.type = components.Button.prototype.types.powerWindow; + this.inToggle = components.Button.prototype.inToggle; + }, + shift: function() { + this.inKey = 'next_effect'; + this.type = components.Button.prototype.types.push; + }, + unshift: function() { + this.inKey = 'enabled'; + this.type = components.Button.prototype.types.powerWindow; + }, + output: function(value, group, control) { + var focused_effect = engine.getValue(eu.group, "focused_effect"); + if (focused_effect !== this.number) { + engine.stopTimer(this.flash_timer); + this.flash_timer = null; + components.Button.prototype.output.call(this, value, group, control); + } + else { + this.startFlash(); + } + }, + toggle_focused_effect: function() { + if (engine.getValue(eu.group, "focused_effect") === this.number) { + engine.setValue(eu.group, "focused_effect", 0); + } + else { + engine.setValue(eu.group, "focused_effect", this.number); + } + }, + connect: function() { + components.Button.prototype.connect.call(this); + this.fx_connection = engine.makeConnection(eu.group, "focused_effect", this.onFocusChange); + }, + disconnect: function() { + components.Button.prototype.disconnect.call(this); + this.fx_connection.disconnect(); + }, + onFocusChange: function(value, group, control) { + if (value === this.number) { + this.startFlash(); + } + else { + this.stopFlash(); + } + }, + startFlash: function() { + // already flashing + if (this.flash_timer) { + engine.stopTimer(this.flash_timer); + } + + this.flash_state = false; + this.send(this.on); + + var time = 500; + if (this.inGetValue() > 0) { + time = 150; + } + + var button = this; + this.flash_timer = engine.beginTimer(time, function() { + if (button.flash_state) { + button.send(button.on); + button.flash_state = false; + } + else { + button.send(button.off); + button.flash_state = true; + } + }); + }, + stopFlash: function() { + engine.stopTimer(this.flash_timer); + this.flash_timer = null; + this.trigger(); + }, + }); + + this.show_focus_connection = engine.makeConnection(eu.group, "focused_effect", function(focused_effect, group, control) { + if (focused_effect === 0) { + engine.setValue(eu.group, "show_focus", 0); + if (ShowFocusedEffectParameters) { + engine.setValue(eu.group, "show_parameters", 0); + } + } else { + engine.setValue(eu.group, "show_focus", 1); + if (ShowFocusedEffectParameters) { + engine.setValue(eu.group, "show_parameters", 1); + } + } + }); + this.show_focus_connection.trigger(); + + this.touch_strip = new this.EffectUnitTouchStrip(); + this.enableButtons = new components.ComponentContainer(); + for (var n = 1; n <= 3; n++) { + this.enableButtons[n] = new this.EffectEnableButton(n); + } + + this.bpmTap = new this.BpmTapButton(); + + this.enableButtons.reconnectComponents(); + + this.forEachComponent(function (component) { + if (component.group === undefined) { + component.group = eu.group; + } + }); +}; +MixtrackPlatinum.EffectUnit.prototype = new components.ComponentContainer(); + +MixtrackPlatinum.Deck = function(number, midi_chan, effects_unit) { + var deck = this; + var eu = effects_unit; + this.active = (number == 1 || number == 2); + + components.Deck.call(this, number); + + this.bpm = new components.Component({ + outKey: "bpm", + output: function(value, group, control) { + MixtrackPlatinum.sendScreenBpmMidi(number, Math.round(value * 100)); + }, + }); + + this.duration = new components.Component({ + outKey: "duration", + output: function(duration, group, control) { + // update duration + MixtrackPlatinum.sendScreenDurationMidi(number, duration * 1000); + + // when the duration changes, we need to update the play position + deck.position.trigger(); + }, + }); + + this.position = new components.Component({ + outKey: "playposition", + output: function(playposition, group, control) { + // the controller appears to expect a value in the range of 0-52 + // representing the position of the track. Here we send a message to the + // controller to update the position display with our current position. + var pos = Math.round(playposition * 52); + if (pos < 0) { + pos = 0; + } + midi.sendShortMsg(0xB0 | midi_chan, 0x3F, pos); + + // get the current duration + duration = deck.duration.outGetValue(); + + // update the time display + var time = MixtrackPlatinum.timeMs(number, playposition, duration); + MixtrackPlatinum.sendScreenTimeMidi(number, time); + + // update the spinner (range 64-115, 52 values) + // + // the visual spinner in the mixxx interface takes 1.8 seconds to loop + // (60 seconds/min divided by 33 1/3 revolutions per min) + var period = 60 / (33+1/3); + var midiResolution = 52; // the controller expects a value range of 64-115 + var timeElapsed = duration * playposition; + var spinner = Math.round(timeElapsed % period * (midiResolution / period)); + if (spinner < 0) { + spinner += 115; + } else { + spinner += 64; + } + + midi.sendShortMsg(0xB0 | midi_chan, 0x06, spinner); + }, + }); + + this.play_button = new components.PlayButton({ + midi: [0x90 + midi_chan, 0x00], + off: 0x01, + sendShifted: true, + shiftControl: true, + shiftOffset: 4, + unshift: function() { + components.PlayButton.prototype.unshift.call(this); + this.type = components.Button.prototype.types.toggle; + }, + shift: function() { + this.inKey = 'play_stutter'; + this.type = components.Button.prototype.types.push; + }, + }); + + this.load = new components.Button({ + inKey: 'LoadSelectedTrack', + shift: function() { + if (ShiftLoadEjects) { + this.inKey = 'eject'; + } + else { + this.inKey = 'LoadSelectedTrackAndPlay'; + } + }, + unshift: function() { + this.inKey = 'LoadSelectedTrack'; + }, + }); + + this.cue_button = new components.CueButton({ + midi: [0x90 + midi_chan, 0x01], + off: 0x01, + sendShifted: true, + shiftControl: true, + shiftOffset: 4, + }); + + this.sync_button = new components.SyncButton({ + midi: [0x90 + midi_chan, 0x02], + off: 0x01, + sendShifted: true, + shiftControl: true, + shiftOffset: 1, + }); + + this.pfl_button = new components.Button({ + midi: [0x90 + midi_chan, 0x1B], + key: 'pfl', + off: 0x01, + type: components.Button.prototype.types.toggle, + connect: function() { + components.Button.prototype.connect.call(this); + this.connections[1] = engine.makeConnection(this.group, this.outKey, MixtrackPlatinum.pflToggle); + }, + }); + + this.hotcue_buttons = new components.ComponentContainer(); + this.sampler_buttons = new components.ComponentContainer(); + for (var i = 1; i <= 4; ++i) { + this.hotcue_buttons[i] = new components.HotcueButton({ + midi: [0x94 + midi_chan, 0x18 + i - 1], + number: i, + sendShifted: true, + shiftControl: true, + shiftOffset: 8, + }); + + // sampler buttons 5-8 + this.sampler_buttons[i] = new components.SamplerButton({ + midi: [0x94 + midi_chan, 0x18 + i - 1], + sendShifted: true, + shiftControl: true, + shiftOffset: 8, + number: i+4, + loaded: 0x00, + playing: 0x7F, + }); + } + this.hotcues = this.hotcue_buttons; + + this.pitch = new components.Pot({ + inKey: 'rate', + invert: true, + }); + if (!this.active) { + this.pitch.firstValueReceived = true; + } + + var pitch_or_keylock = function (channel, control, value, status, group) { + if (this.other.inGetValue() > 0.0 && this.isPress(channel, control, value, status)) { + // toggle keylock, both keys pressed + script.toggleControl(this.group, "keylock"); + } + else { + components.Button.prototype.input.call(this, channel, control, value, status, group); + } + }; + this.pitch_bend_up = new components.Button({ + inKey: 'rate_temp_up', + input: pitch_or_keylock, + }); + this.pitch_bend_down = new components.Button({ + inKey: 'rate_temp_down', + input: pitch_or_keylock, + }); + this.pitch_bend_up.other = this.pitch_bend_down; + this.pitch_bend_down.other = this.pitch_bend_up; + + var key_up_or_down = function (channel, control, value, status, group) { + this.is_pressed = this.isPress(channel, control, value, status); + if (this.is_pressed) { + if (this.other.is_pressed) { + // reset if both buttons are pressed + engine.setValue(deck.currentDeck, "pitch_adjust", 0.0); + } + else { + this.inSetValue(1.0); + } + } + }; + this.key_up = new components.Button({ + inKey: 'pitch_up', + direction: 1, + input: key_up_or_down, + }); + this.key_down = new components.Button({ + inKey: 'pitch_down', + direction: -1, + input: key_up_or_down, + }); + this.key_up.other = this.key_down; + this.key_down.other = this.key_up; + + loop_base = function(midino, obj) { + return _.assign({ + midi: [0x94 + midi_chan, midino], + on: 0x01, + sendShifted: true, + shiftChannel: true, + shiftOffset: -0x10, + }, obj); + }; + + this.alternate_manloop = new components.ComponentContainer({ + loop_in: new components.HotcueButton(loop_base(0x38, { + number: 5, + })), + loop_out: new components.HotcueButton(loop_base(0x39, { + number: 6, + })), + loop_toggle: new components.HotcueButton(loop_base(0x32, { + number: 7, + })), + // there are two hotcue 8 controls, one for the loop_halve button and + // one for the loop_double button. These buttons are two individual + // functions when in manual loop mode, but they behave as one button + // in hotcue mode. + loop_halve: new components.HotcueButton(loop_base(0x34, { + number: 8, + })), + loop_double: new components.HotcueButton(loop_base(0x35, { + number: 8, + })), + }); + this.normal_manloop = new components.ComponentContainer({ + loop_in: new components.Button(loop_base(0x38, { + inKey: 'loop_in', + outKey: 'loop_start_position', + outValueScale: function (value) { + return (value != -1) ? this.on : this.off; + }, + })), + loop_out: new components.Button(loop_base(0x39, { + inKey: 'loop_out', + outKey: 'loop_end_position', + outValueScale: function (value) { + return (value != -1) ? this.on : this.off; + }, + })), + loop_toggle: new components.LoopToggleButton(loop_base(0x32, {})), + loop_halve: new components.Button(loop_base(0x34, { + key: 'loop_halve', + input: function(channel, control, value, status) { + if (this.isPress(channel, control, value, status)) { + engine.setValue(deck.currentDeck, "loop_scale", 0.5); + } + }, + })), + loop_double: new components.Button(loop_base(0x35, { + key: 'loop_double', + input: function(channel, control, value, status) { + if (this.isPress(channel, control, value, status)) { + engine.setValue(deck.currentDeck, "loop_scale", 2.0); + } + }, + })), + }); + // swap normal and alternate manual loop controls + if (UseManualLoopAsCue) { + var manloop = this.normal_manloop; + this.normal_manloop = this.alternate_manloop; + this.alternate_manloop = manloop; + } + this.manloop = this.normal_manloop; + + auto_loop_hotcue = function(midino, obj) { + return _.assign({ + midi: [0x94 + midi_chan, midino], + on: 0x40, + sendShifted: true, + shiftControl: true, + shiftOffset: 0x08, + }, obj); + }; + + auto_loop_base = function(midino, obj) { + return _.assign({ + midi: [0x94 + midi_chan, midino], + on: 0x40, + sendShifted: true, + shiftChannel: true, + shiftOffset: -0x10, + }, obj); + }; + + this.alternate_autoloop = new components.ComponentContainer({ + auto1: new components.HotcueButton(auto_loop_hotcue(0x14, { + number: 5, + })), + auto2: new components.HotcueButton(auto_loop_hotcue(0x15, { + number: 6, + })), + auto3: new components.HotcueButton(auto_loop_hotcue(0x16, { + number: 7, + })), + auto4: new components.HotcueButton(auto_loop_hotcue(0x17, { + number: 8, + })), + }); + this.alternate_autoloop.roll1 = this.alternate_autoloop.auto1; + this.alternate_autoloop.roll2 = this.alternate_autoloop.auto2; + this.alternate_autoloop.roll3 = this.alternate_autoloop.auto3; + this.alternate_autoloop.roll4 = this.alternate_autoloop.auto4; + + this.normal_autoloop = new components.ComponentContainer({ + auto1: new components.Button(auto_loop_base(0x14, { + inKey: 'beatloop_1_toggle', + outKey: 'beatloop_1_enabled', + })), + auto2: new components.Button(auto_loop_base(0x15, { + inKey: 'beatloop_2_toggle', + outKey: 'beatloop_2_enabled', + })), + auto3: new components.Button(auto_loop_base(0x16, { + inKey: 'beatloop_4_toggle', + outKey: 'beatloop_4_enabled', + })), + auto4: new components.Button(auto_loop_base(0x17, { + inKey: 'beatloop_8_toggle', + outKey: 'beatloop_8_enabled', + })), + + roll1: new components.Button(auto_loop_base(0x1C, { + inKey: 'beatlooproll_0.0625_activate', + outKey: 'beatloop_0.0625_enabled', + })), + roll2: new components.Button(auto_loop_base(0x1D, { + inKey: 'beatlooproll_0.125_activate', + outKey: 'beatloop_0.125_enabled', + })), + roll3: new components.Button(auto_loop_base(0x1E, { + inKey: 'beatlooproll_0.25_activate', + outKey: 'beatloop_0.25_enabled', + })), + roll4: new components.Button(auto_loop_base(0x1F, { + inKey: 'beatlooproll_0.5_activate', + outKey: 'beatloop_0.5_enabled', + })), + }); + + // swap normal and alternate auto loop controls + if (UseAutoLoopAsCue) { + var autoloop = this.normal_autoloop; + this.normal_autoloop = this.alternate_autoloop; + this.alternate_autoloop = autoloop; + } + this.autoloop = this.normal_autoloop; + + this.pad_mode = new components.Component({ + input: function (channel, control, value, status, group) { + // only handle button down events + if (value != 0x7F) return; + + var shifted_hotcues = deck.sampler_buttons; + var normal_hotcues = deck.hotcue_buttons; + if (UseCueAsSampler) { + shifted_hotcues = deck.hotcue_buttons; + normal_hotcues = deck.sampler_buttons; + } + + // if shifted, set a special mode + if (this.isShifted) { + // manual loop + if (control == 0x0E) { + deck.manloop = deck.alternate_manloop; + deck.manloop.reconnectComponents(); + } + // auto loop + else if (control == 0x06) { + deck.autoloop = deck.alternate_autoloop; + deck.autoloop.reconnectComponents(); + } + + // hotcue sampler + if (control == 0x0B) { + deck.hotcues.forEachComponent(function(component) { + component.disconnect(); + }); + deck.hotcues = shifted_hotcues; + deck.hotcues.reconnectComponents(); + } + // reset hotcues in all other modes + else { + deck.hotcues.forEachComponent(function(component) { + component.disconnect(); + }); + deck.hotcues = deck.hotcue_buttons; + deck.hotcues.reconnectComponents(); + } + } + // otherwise set a normal mode + else { + // manual loop + if (control == 0x0E) { + deck.manloop = deck.normal_manloop; + deck.manloop.reconnectComponents(); + } + // auto loop + else if (control == 0x06) { + deck.autoloop = deck.normal_autoloop; + deck.autoloop.reconnectComponents(); + } + + // hotcue sampler + if (control == 0x0B) { + deck.hotcues.forEachComponent(function(component) { + component.disconnect(); + }); + deck.hotcues = normal_hotcues; + deck.hotcues.reconnectComponents(); + } + // reset hotcues + else { + deck.hotcues.forEachComponent(function(component) { + component.disconnect(); + }); + deck.hotcues = deck.hotcue_buttons; + deck.hotcues.reconnectComponents(); + } + } + }, + shift: function() { + this.isShifted = true; + }, + unshift: function() { + this.isShifted = false; + }, + }); + + this.EqEffectKnob = function (group, in_key, fx_key, filter_knob) { + this.unshift_group = group; + this.unshift_key = in_key; + this.fx_key = fx_key; + if (filter_knob) { + this.shift_key = 'super1'; + } + this.ignore_next = null; + components.Pot.call(this, { + group: group, + inKey: in_key, + }); + }; + this.EqEffectKnob.prototype = new components.Pot({ + input: function (channel, control, value, status, group) { + // if the control group and key has changed, ignore_next will hold + // the old settings. We need to tell the soft takeover engine to + // ignore the next values for that control so that when we + // eventually switch back to it, soft takeover will manage it + // properly. + // + // We call IgnoreNextValue() here instead of in shift()/unshift() + // (via connect()/disconnect()) because if we did that, pressing + // the shift key would cause the next value on the control to be + // ignored even if the control wasn't moved, which would trigger + // a phantom soft takeover if the control was moved fast enough. We + // only need to IgnoreNextValue() if the control has actually moved + // after switching the target group/key. + if (this.ignore_next) { + engine.softTakeoverIgnoreNextValue(this.ignore_next.group, this.ignore_next.key); + this.ignore_next = null; + } + components.Pot.prototype.input.call(this, channel, control, value, status, group); + }, + connect: function() { + // enable soft takeover on our controls + for (var i = 1; i <= 3; i ++) { + var group = '[EffectRack1_EffectUnit' + eu.currentUnitNumber + '_Effect' + i + ']'; + engine.softTakeover(group, this.fx_key, true); + } + components.Pot.prototype.connect.call(this); + }, + shift: function() { + var focused_effect = engine.getValue(eu.group, "focused_effect"); + if (focused_effect === 0) { + // we need this here so that shift+filter works with soft + // takeover because touching the touch strip disables it each + // time + if (this.shift_key) { + engine.softTakeover(eu.group, this.shift_key, true); + this.switchControl(eu.group, this.shift_key); + } + } + else { + var group = '[EffectRack1_EffectUnit' + eu.currentUnitNumber + '_Effect' + focused_effect + ']'; + this.switchControl(group, this.fx_key); + } + }, + unshift: function() { + this.switchControl(this.unshift_group, this.unshift_key); + }, + switchControl: function(group, key) { + if (this.group != group || this.inKey != key) { + this.ignore_next = { 'group': this.group, 'key': this.inKey }; + } + this.group = group; + this.inKey = key; + }, + }); + + var eq_group = '[EqualizerRack1_' + this.currentDeck + '_Effect1]'; + this.high_eq = new this.EqEffectKnob(eq_group, 'parameter3', 'parameter3'); + this.mid_eq = new this.EqEffectKnob(eq_group, 'parameter2', 'parameter4'); + this.low_eq = new this.EqEffectKnob(eq_group, 'parameter1', 'parameter5'); + + this.filter = new this.EqEffectKnob( + '[QuickEffectRack1_' + this.currentDeck + ']', + 'super1', + 'parameter1', + true); + + this.gain = new this.EqEffectKnob( + this.currentDeck, + 'pregain', + 'parameter2'); + + this.reconnectComponents(function (c) { + if (c.group === undefined) { + c.group = deck.currentDeck; + } + }); + + // don't light up sampler buttons in hotcue mode + this.sampler_buttons.forEachComponent(function(component) { + component.disconnect(); + }); + + this.setActive = function(active) { + this.active = active; + + if (!active) { + // trigger soft takeover on the pitch control + this.pitch.disconnect(); + } + }; +}; + +MixtrackPlatinum.Deck.prototype = new components.Deck(); + +MixtrackPlatinum.Sampler = function(base) { + for (var i = 1; i <= 4; ++i) { + this[i] = new components.SamplerButton({ + midi: [0x9F, 0x20 + i], + number: base+i-1, + loaded: 0x00, + playing: 0x7F, + }); + } +}; + +MixtrackPlatinum.Sampler.prototype = new components.ComponentContainer(); + +MixtrackPlatinum.HeadGain = function(sampler) { + components.Pot.call(this); + + this.ignore_next = null; + this.shifted = false; + this.sampler = sampler; + this.sampler.forEachComponent(function(component) { + engine.softTakeover(component.group, 'volume', true); + }); +}; +MixtrackPlatinum.HeadGain.prototype = new components.Pot({ + group: '[Master]', + inKey: 'headGain', + input: function (channel, control, value, status, group) { + // we call softTakeoverIgnoreNextValue() here on the non-targeted + // control only if the control was moved when focus was switched. This + // is to avoid a phantom triggering of soft takeover that can happen if + // ignoreNextValue() is called un-conditionally when the control target + // is changed (like in shfit()/unshift()). + if (this.ignore_next == "sampler" && !this.shifted) { + this.sampler.forEachComponent(function(component) { + engine.softTakeoverIgnoreNextValue(component.group, 'volume'); + }); + this.ignore_next = null; + } + else if (this.ignore_next == "headgain" && this.shifted) { + engine.softTakeoverIgnoreNextValue(this.group, this.inKey); + this.ignore_next = null; + } + + if (this.shifted) { + // make head gain control the sampler volume when shifted + var pot = this; + this.sampler.forEachComponent(function(component) { + engine.setParameter(component.group, 'volume', pot.inValueScale(value)); + }); + } else { + components.Pot.prototype.input.call(this, channel, control, value, status, group); + } + }, + shift: function() { + this.shifted = true; + this.ignore_next = "headgain"; + }, + unshift: function() { + this.shifted = false; + this.ignore_next = "sampler"; + }, +}); + +MixtrackPlatinum.BrowseKnob = function() { + this.knob = new components.Encoder({ + group: '[Library]', + input: function (channel, control, value, status, group) { + if (value === 1) { + engine.setParameter(this.group, this.inKey + 'Down', 1); + } else if (value === 127) { + engine.setParameter(this.group, this.inKey + 'Up', 1); + } + }, + unshift: function() { + this.inKey = 'Move'; + }, + shift: function() { + this.inKey = 'Scroll'; + }, + }); + + this.button = new components.Button({ + group: '[Library]', + inKey: 'GoToItem', + unshift: function() { + this.inKey = 'GoToItem'; + }, + shift: function() { + this.inKey = 'MoveFocusForward'; + }, + }); +}; + +MixtrackPlatinum.BrowseKnob.prototype = new components.ComponentContainer(); + +MixtrackPlatinum.encodeNumToArray = function(number) { + var number_array = [ + (number >> 28) & 0x0F, + (number >> 24) & 0x0F, + (number >> 20) & 0x0F, + (number >> 16) & 0x0F, + (number >> 12) & 0x0F, + (number >> 8) & 0x0F, + (number >> 4) & 0x0F, + number & 0x0F, + ]; + + if (number < 0) number_array[0] = 0x07; + else number_array[0] = 0x08; + + return number_array; +}; + +MixtrackPlatinum.sendScreenDurationMidi = function(deck, duration) { + if (duration < 1) { + duration = 1; + } + durationArray = MixtrackPlatinum.encodeNumToArray(duration - 1); + + var bytePrefix = [0xF0, 0x00, 0x20, 0x7F, deck, 0x03]; + var bytePostfix = [0xF7]; + var byteArray = bytePrefix.concat(durationArray, bytePostfix); + midi.sendSysexMsg(byteArray, byteArray.length); +}; + +MixtrackPlatinum.sendScreenTimeMidi = function(deck, time) { + var timeArray = MixtrackPlatinum.encodeNumToArray(time); + + var bytePrefix = [0xF0, 0x00, 0x20, 0x7F, deck, 0x04]; + var bytePostfix = [0xF7]; + var byteArray = bytePrefix.concat(timeArray, bytePostfix); + midi.sendSysexMsg(byteArray, byteArray.length); +}; + +MixtrackPlatinum.sendScreenBpmMidi = function(deck, bpm) { + bpmArray = MixtrackPlatinum.encodeNumToArray(bpm); + bpmArray.shift(); + bpmArray.shift(); + + var bytePrefix = [0xF0, 0x00, 0x20, 0x7F, deck, 0x01]; + var bytePostfix = [0xF7]; + var byteArray = bytePrefix.concat(bpmArray, bytePostfix); + midi.sendSysexMsg(byteArray, byteArray.length); +}; + +MixtrackPlatinum.elapsedToggle = function (channel, control, value, status, group) { + if (value != 0x7F) return; + + var current_setting = engine.getValue('[Controls]', 'ShowDurationRemaining'); + if (current_setting === 0) { + // currently showing elapsed, set to remaining + engine.setValue('[Controls]', 'ShowDurationRemaining', 1); + } else if (current_setting === 1) { + // currently showing remaining, set to elapsed + engine.setValue('[Controls]', 'ShowDurationRemaining', 0); + } else { + // currently showing both (that means we are showing remaining, set to elapsed + engine.setValue('[Controls]', 'ShowDurationRemaining', 0); + } +}; + +MixtrackPlatinum.timeElapsedCallback = function(value, group, control) { + // 0 = elapsed + // 1 = remaining + // 2 = both (we ignore this as the controller can't show both) + var on_off; + if (value === 0) { + // show elapsed + on_off = 0x00; + } else if (value === 1) { + // show remaining + on_off = 0x7F; + } else { + // both, ignore the event + return; + } + + // update all 4 decks on the controller + midi.sendShortMsg(0x90, 0x46, on_off); + midi.sendShortMsg(0x91, 0x46, on_off); + midi.sendShortMsg(0x92, 0x46, on_off); + midi.sendShortMsg(0x93, 0x46, on_off); +}; + +MixtrackPlatinum.timeMs = function(deck, position, duration) { + return Math.round(duration * position * 1000); +}; + +// these functions track if the user has let go of the jog wheel but it is +// still spinning +MixtrackPlatinum.scratch_timer = []; // initialized before use (null is an acceptable value) +MixtrackPlatinum.scratch_tick = []; // initialized before use +MixtrackPlatinum.resetScratchTimer = function (deck, tick) { + if (!MixtrackPlatinum.scratch_timer[deck]) return; + MixtrackPlatinum.scratch_tick[deck] = tick; +}; + +MixtrackPlatinum.startScratchTimer = function (deck) { + if (MixtrackPlatinum.scratch_timer[deck]) return; + + MixtrackPlatinum.scratch_tick[deck] = 0; + MixtrackPlatinum.scratch_timer[deck] = engine.beginTimer(20, function() { + MixtrackPlatinum.scratchTimerCallback(deck); + }); +}; + +MixtrackPlatinum.stopScratchTimer = function (deck) { + if (MixtrackPlatinum.scratch_timer[deck]) { + engine.stopTimer(MixtrackPlatinum.scratch_timer[deck]); + } + MixtrackPlatinum.scratch_timer[deck] = null; +}; + +MixtrackPlatinum.scratchTimerCallback = function (deck) { + // here we see if the platter is still physically moving even though the + // platter is not being touched. For forward motion, we stop scratching + // before the platter has physically stopped and delay a little longer + // when moving back. This is to mimic actual vinyl better. + if ((MixtrackPlatinum.scratch_direction[deck] // forward + && Math.abs(MixtrackPlatinum.scratch_tick[deck]) > 2) + || (!MixtrackPlatinum.scratch_direction[deck] // backward + && Math.abs(MixtrackPlatinum.scratch_tick[deck]) > 1)) + { + // reset tick detection + MixtrackPlatinum.scratch_tick[deck] = 0; + return; + } + + MixtrackPlatinum.scratchDisable(deck); +}; + +MixtrackPlatinum.scratchDisable = function (deck) { + MixtrackPlatinum.searching[deck] = false; + MixtrackPlatinum.stopScratchTimer(deck); + engine.scratchDisable(deck, false); +}; + +MixtrackPlatinum.scratchEnable = function (deck) { + var alpha = 1.0/8; + var beta = alpha/32; + + engine.scratchEnable(deck, 1011, 33+1/3, alpha, beta); + MixtrackPlatinum.stopScratchTimer(deck); +}; + +// The button that enables/disables scratching +// these arrays are indexed from 1, so we initialize them with 5 values +MixtrackPlatinum.touching = [false, false, false, false, false]; +MixtrackPlatinum.searching = [false, false, false, false, false]; +MixtrackPlatinum.wheelTouch = function (channel, control, value, status, group) { + var deck = channel + 1; + + // ignore touch events if not in vinyl mode + if (!MixtrackPlatinum.shift + && !MixtrackPlatinum.searching[deck] + && !MixtrackPlatinum.wheel[channel] + && value != 0) + { + return; + } + + MixtrackPlatinum.touching[deck] = 0x7F == value; + + + // don't start scratching if shift is pressed + if (value === 0x7F + && !MixtrackPlatinum.shift + && !MixtrackPlatinum.searching[deck]) + { + MixtrackPlatinum.scratchEnable(deck); + } + else if (value === 0x7F + && (MixtrackPlatinum.shift + || MixtrackPlatinum.searching[deck])) + { + MixtrackPlatinum.scratchDisable(deck); + MixtrackPlatinum.searching[deck] = true; + MixtrackPlatinum.stopScratchTimer(deck); + } + else { // If button up + MixtrackPlatinum.startScratchTimer(deck); + } +}; + +// The wheel that actually controls the scratching +// indexed by deck numbers starting at 1, so include an extra element +MixtrackPlatinum.scratch_direction = [null, null, null, null, null]; // true == forward +MixtrackPlatinum.scratch_accumulator = [0, 0, 0, 0, 0]; +MixtrackPlatinum.last_scratch_tick = [0, 0, 0, 0, 0]; +MixtrackPlatinum.wheelTurn = function (channel, control, value, status, group) { + var deck = channel + 1; + var direction; + var newValue; + if (value < 64) { + direction = true; + } else { + direction = false; + } + + // if the platter is spun fast enough, value will wrap past the 64 midpoint + // but the platter will be spinning in the opposite direction we expect it + // to be + var delta = Math.abs(MixtrackPlatinum.last_scratch_tick[deck] - value); + if (MixtrackPlatinum.scratch_direction[deck] !== null && MixtrackPlatinum.scratch_direction[deck] != direction && delta < 64) { + direction = !direction; + } + + if (direction) { + newValue = value; + } else { + newValue = value - 128; + } + + // detect searching the track + if (MixtrackPlatinum.searching[deck]) { + var position = engine.getValue(group, 'playposition'); + if (position <= 0) position = 0; + if (position >= 1) position = 1; + engine.setValue(group, 'playposition', position + newValue * 0.0001); + MixtrackPlatinum.resetScratchTimer(deck, newValue); + return; + } + + // stop scratching if the wheel direction changes and the platter is not + // being touched + if (MixtrackPlatinum.scratch_direction[deck] === null) { + MixtrackPlatinum.scratch_direction[deck] = direction; + } + else if (MixtrackPlatinum.scratch_direction[deck] != direction) { + if (!MixtrackPlatinum.touching[deck]) { + MixtrackPlatinum.scratchDisable(deck); + } + MixtrackPlatinum.scratch_accumulator[deck] = 0; + } + + MixtrackPlatinum.last_scratch_tick[deck] = value; + MixtrackPlatinum.scratch_direction[deck] = direction; + MixtrackPlatinum.scratch_accumulator[deck] += Math.abs(newValue); + + // handle scratching + if (engine.isScratching(deck)) { + engine.scratchTick(deck, newValue); // Scratch! + MixtrackPlatinum.resetScratchTimer(deck, newValue); + } + // handle beat jumping + else if (MixtrackPlatinum.shift) { + if (MixtrackPlatinum.scratch_accumulator[deck] > 61) { + MixtrackPlatinum.scratch_accumulator[deck] -= 61; + if (direction) { // forward + engine.setParameter(group, 'beatjump_1_forward', 1); + } else { + engine.setParameter(group, 'beatjump_1_backward', 1); + } + } + } + // handle pitch bending + else { + engine.setValue(group, 'jog', newValue * 0.1); // Pitch bend + } +}; + +MixtrackPlatinum.wheel = []; // initialzed in the MixtrackPlatinum.init() function +MixtrackPlatinum.wheelToggle = function (channel, control, value, status, group) { + if (value != 0x7F) return; + MixtrackPlatinum.wheel[channel] = !MixtrackPlatinum.wheel[channel]; + var on_off = 0x01; + if (MixtrackPlatinum.wheel[channel]) on_off = 0x7F; + midi.sendShortMsg(0x90 | channel, 0x07, on_off); +}; + +MixtrackPlatinum.deckSwitch = function (channel, control, value, status, group) { + var deck = channel + 1; + MixtrackPlatinum.decks[deck].setActive(value == 0x7F); + + // change effects racks + if (MixtrackPlatinum.decks[deck].active && (channel == 0x00 || channel == 0x02)) { + MixtrackPlatinum.effects[1].setCurrentUnit(deck); + } + else if (MixtrackPlatinum.decks[deck].active && (channel == 0x01 || channel == 0x03)) { + MixtrackPlatinum.effects[2].setCurrentUnit(deck); + } + + // also zero vu meters + if (value != 0x7F) return; + midi.sendShortMsg(0xBF, 0x44, 0); + midi.sendShortMsg(0xBF, 0x45, 0); +}; + +// zero vu meters when toggling pfl +MixtrackPlatinum.pflToggle = function(value, group, control) { + midi.sendShortMsg(0xBF, 0x44, 0); + midi.sendShortMsg(0xBF, 0x45, 0); +}; + +MixtrackPlatinum.vuCallback = function(value, group, control) { + // the top LED lights up at 81 + var level = value * 80; + + // if any channel pfl is active, show channel levels + if (engine.getValue('[Channel1]', 'pfl') + || engine.getValue('[Channel2]', 'pfl') + || engine.getValue('[Channel3]', 'pfl') + || engine.getValue('[Channel4]', 'pfl')) + { + if (engine.getValue(group, "PeakIndicator")) { + level = 81; + } + + if (group == '[Channel1]' && MixtrackPlatinum.decks[1].active) { + midi.sendShortMsg(0xBF, 0x44, level); + } + else if (group == '[Channel3]' && MixtrackPlatinum.decks[3].active) { + midi.sendShortMsg(0xBF, 0x44, level); + } + else if (group == '[Channel2]' && MixtrackPlatinum.decks[2].active) { + midi.sendShortMsg(0xBF, 0x45, level); + } + else if (group == '[Channel4]' && MixtrackPlatinum.decks[4].active) { + midi.sendShortMsg(0xBF, 0x45, level); + } + } + else if (group == '[Master]' && control == 'VuMeterL') { + if (engine.getValue(group, "PeakIndicatorL")) { + level = 81; + } + midi.sendShortMsg(0xBF, 0x44, level); + } + else if (group == '[Master]' && control == 'VuMeterR') { + if (engine.getValue(group, "PeakIndicatorR")) { + level = 81; + } + midi.sendShortMsg(0xBF, 0x45, level); + } +}; + + +// track the state of the shift key +MixtrackPlatinum.shift = false; +MixtrackPlatinum.shiftToggle = function (channel, control, value, status, group) { + MixtrackPlatinum.shift = value == 0x7F; + + if (MixtrackPlatinum.shift) { + MixtrackPlatinum.decks.shift(); + MixtrackPlatinum.sampler_all.shift(); + MixtrackPlatinum.effects.shift(); + MixtrackPlatinum.browse.shift(); + MixtrackPlatinum.head_gain.shift(); + + // reset the beat jump scratch accumulators + MixtrackPlatinum.scratch_accumulator[1] = 0; + MixtrackPlatinum.scratch_accumulator[2] = 0; + MixtrackPlatinum.scratch_accumulator[3] = 0; + MixtrackPlatinum.scratch_accumulator[4] = 0; + } + else { + MixtrackPlatinum.decks.unshift(); + MixtrackPlatinum.sampler_all.unshift(); + MixtrackPlatinum.effects.unshift(); + MixtrackPlatinum.browse.unshift(); + MixtrackPlatinum.head_gain.unshift(); + } +}; diff --git a/res/controllers/Numark-N4-scripts.js b/res/controllers/Numark-N4-scripts.js index 2172a594f7d0..e0cf81bdea19 100644 --- a/res/controllers/Numark-N4-scripts.js +++ b/res/controllers/Numark-N4-scripts.js @@ -17,7 +17,11 @@ NumarkN4.encoderResolution=0.05; // 1/encoderResolution = number of steps going NumarkN4.resetHotCuePageOnTrackLoad=true; // resets the page of the Hotcue back to 1 after loading a new track. -NumarkN4.cueReverseRoll=true; +NumarkN4.cueReverseRoll=true; // enables the ability to do a reverse roll while shift-pressing the cue button + +// true = wrap around => scrolling past 4 will reset the page to the first page and vice versa +// false = clamp the the pages to the [1:4] range +NumarkN4.hotcuePageIndexBehavior=true; // possible ranges (0.0..3.0 where 0.06=6%) NumarkN4.rateRanges = [0, // default (gets set via script later; don't modifify) @@ -35,6 +39,11 @@ NumarkN4.vinylTouched = [false,false,false,false]; NumarkN4.globalShift = false; +NumarkN4.scratchXFader = { + xFaderMode: 0, // fast cut (additive) + xFaderCurve: 999.60, + xFaderCalibration: 1.0 +}; components.Encoder.prototype.input = function (channel, control, value, status, group) { this.inSetParameter( @@ -68,19 +77,27 @@ components.Component.prototype.send = function (value) { } }; +// gets filled via trigger of the callbacks in NumarkN4.crossfaderCallbackConnections +NumarkN4.storedCrossfaderParams = {}; +NumarkN4.crossfaderCallbackConnections = []; +NumarkN4.CrossfaderChangeCallback = function (value, group, control) { + // indicates that the crossfader settings were changed while during session + this.changed = true; + NumarkN4.storedCrossfaderParams[control] = value; +} + NumarkN4.init = function (id) { - NumarkN4.xFaderSettings = { - mode: engine.getValue("[Mixer Profile]", "xFaderMode"), - curve: engine.getValue("[Mixer Profile]","xFaderCurve"), - calibration: engine.getValue("[Mixer Profile]","xFaderCalibration") - } - NumarkN4.setCrossfaderSettings(NumarkN4.xFaderSettings); NumarkN4.rateRanges[0]=engine.getValue("[Channel1]","rateRange"); NumarkN4.Decks=[]; for (var i=1;i<=4;i++){ // Array is based on 1 because it makes more sense in the XML NumarkN4.Decks[i] = new NumarkN4.Deck(i); - + } + // create xFader callbacks and trigger them to fill NumarkN4.storedCrossfaderParams + for (const control in NumarkN4.scratchXFader) { + var connectionObject = engine.makeConnection("[Mixer Profile]", control, NumarkN4.CrossfaderChangeCallback); + connectionObject.trigger(); + NumarkN4.crossfaderCallbackConnections.push(connectionObject); } NumarkN4.Mixer = new NumarkN4.MixerTemplate(); @@ -90,12 +107,6 @@ NumarkN4.init = function (id) { }; -NumarkN4.setCrossfaderSettings = function (settingsStruct) { - engine.setValue("[Mixer Profile]","xFaderMode",settingsStruct.mode); - engine.setValue("[Mixer Profile]","xFaderCurve",settingsStruct.curve); - engine.setValue("[Mixer Profile]","xFaderCalibration",settingsStruct.calibration); -} - NumarkN4.topContainer = function (channel) { this.group = '[Channel'+channel+']'; var theContainer = this; @@ -194,7 +205,8 @@ NumarkN4.topContainer = function (channel) { if (displayFeedback == undefined) { displayFeedback = true; } - layer = Math.max(Math.min(layer,3),0); // clamp layer value to [0;3] range + // when the layer becommes negative, the (layer+4) will force a positive/valid page indexOf + layer = NumarkN4.hotcuePageIndexBehavior ? (layer+4)%4 : Math.max(Math.min(layer,3),0); // clamp layer value to [0;3] range this.hotCuePage = layer; if (this.timer !== 0) { engine.stopTimer(this.timer); @@ -300,19 +312,24 @@ NumarkN4.MixerTemplate = function () { inKey: "mute", }); - // NOTE: [Mixer Profile] is not a documented group. Taken from script.crossfaderCurve - // BUG: Help on Mixxx forum is needed this.changeCrossfaderContour = new components.Button({ midi: [0x90,0x4B], + state: false, input: function (channel, control, value, status, group) { - if (this.isPress(channel,control, value, status)) { - NumarkN4.setCrossfaderSettings({ - mode: 0, // fast cut (additive) - curve: 999.60, - calibration: 1.0 - }); + NumarkN4.crossfaderCallbackConnections.forEach(connection => {connection.disconnect()}); + NumarkN4.crossfaderCallbackConnections = []; + const setParamsAndConnectCallbacks = (xfaderParameters) => { + for (const control in xfaderParameters) { + engine.setValue("[Mixer Profile]", control, xfaderParameters[control]); + NumarkN4.crossfaderCallbackConnections.push( + engine.makeConnection("[Mixer Profile]", control, NumarkN4.CrossfaderChangeCallback) + ); + } + }; + if (this.isPress(channel, control, value, status)) { + setParamsAndConnectCallbacks(NumarkN4.scratchXFader); } else { - NumarkN4.setCrossfaderSettings(NumarkN4.xFaderSettings); + setParamsAndConnectCallbacks(NumarkN4.storedCrossfaderParams); } } }); @@ -544,10 +561,10 @@ NumarkN4.Deck = function (channel) { }); this.manageChannelIndicator = function () { - this.alternating=!this.alternating; //mimics a static variable this.duration=engine.getParameter(theDeck.group, "duration"); // checks if the playposition is in the warnTimeFrame if (engine.getParameter(theDeck.group, "playposition") * this.duration > (this.duration - NumarkN4.warnAfterTime)) { + this.alternating=!this.alternating; //mimics a static variable midi.sendShortMsg(0xB0,0x1D+channel, this.alternating?0x7F:0x0); } else { midi.sendShortMsg(0xB0,0x1D+channel, 0x7F); @@ -560,8 +577,14 @@ NumarkN4.Deck = function (channel) { theDeck.blinkTimer=0; return; // return early so no new timer gets created. } - //timer is more efficent is this case than a callback because it would be called too often. - theDeck.blinkTimer=engine.beginTimer(NumarkN4.blinkInterval,theDeck.manageChannelIndicator); + // this previouslyLoaded guard is needed because everytime a new track gets + // loaded into a deck without previously ejecting, a new timer would get + // spawned which conflicted with the old (still running) timers. + if (!this.previouslyLoaded) { + //timer is more efficent is this case than a callback because it would be called too often. + theDeck.blinkTimer=engine.beginTimer(NumarkN4.blinkInterval,theDeck.manageChannelIndicator); + } + this.previouslyLoaded=value; }); this.pitchBendMinus = new components.Button({ midi: [0x90+channel,0x18,0xB0+channel,0x3D], @@ -675,7 +698,12 @@ NumarkN4.shutdown = function () { // View Definition of Array for explanation. NumarkN4.Decks[i].shutdown(); } - // reset crossfader parameters to user preferences. - NumarkN4.setCrossfaderSettings(NumarkN4.xFaderSettings); + // revert the crossfader parameters only if they haven't been changed by the + // user and if they are currently set to scratch + if (!NumarkN4.CrossfaderChangeCallback.changed || NumarkN4.changeCrossfaderContour.state) { + for (const control in NumarkN4.storedCrossfaderParams) { + engine.setValue("[Mixer Profile]", control, NumarkN4.storedCrossfaderParams[control]); + } + } // midi.sendSysexMsg(NumarkN4.ShutoffSequence,NumarkN4.ShutoffSequence.length); }; diff --git a/res/controllers/Pioneer DDJ-SX.midi.xml b/res/controllers/Pioneer DDJ-SX.midi.xml index 1d62f27e3d2d..d68e311aab07 100644 --- a/res/controllers/Pioneer DDJ-SX.midi.xml +++ b/res/controllers/Pioneer DDJ-SX.midi.xml @@ -9,7 +9,6 @@ - diff --git a/res/controllers/Pioneer-DDJ-SB2.midi.xml b/res/controllers/Pioneer-DDJ-SB2.midi.xml index c528dbff9662..c964b7de0655 100644 --- a/res/controllers/Pioneer-DDJ-SB2.midi.xml +++ b/res/controllers/Pioneer-DDJ-SB2.midi.xml @@ -9,7 +9,6 @@ - diff --git a/res/controllers/Reloop Terminal Mix 2-4.midi.xml b/res/controllers/Reloop Terminal Mix 2-4.midi.xml index 9b42dd32f104..160f60ad68ab 100644 --- a/res/controllers/Reloop Terminal Mix 2-4.midi.xml +++ b/res/controllers/Reloop Terminal Mix 2-4.midi.xml @@ -10,7 +10,6 @@ A complete 4-deck preset for a single Reloop Terminal Mix 2 or 4. - diff --git a/res/controllers/Vestax VCI-400.midi.xml b/res/controllers/Vestax VCI-400.midi.xml index 3b004e45837a..f5cca9bf7e30 100644 --- a/res/controllers/Vestax VCI-400.midi.xml +++ b/res/controllers/Vestax VCI-400.midi.xml @@ -8,804 +8,752 @@ - + - [Playlist] - LoadSelectedIntoFirstStopped - MIDI Learned from 4 messages. - 0x9E - 0x71 + [Master] + VestaxVCI400.shiftActivate + 0x90 + 0x01 - + [Channel1] - VestaxVCI400.wheelTouch + sync_enabled + MIDI Learned from 22 messages. 0x92 - 0x27 + 0x01 - + [Channel2] - VestaxVCI400.wheelTouch + sync_enabled + MIDI Learned from 88 messages. 0x93 - 0x27 + 0x01 - + [Channel3] - VestaxVCI400.wheelTouch + sync_enabled + MIDI Learned from 24 messages. 0x94 - 0x27 + 0x01 - + [Channel4] - VestaxVCI400.wheelTouch + sync_enabled + MIDI Learned from 90 messages. 0x95 - 0x27 + 0x01 + + + + + + [Master] + VestaxVCI400.fx1ToggleButton1 + 0x9C + 0x01 + + + + + + [Master] + VestaxVCI400.fx2ToggleButton1 + 0x9D + 0x01 [Channel1] - reverseroll - MIDI Learned from 36 messages. - 0x94 - 0x26 + beatsync + 0xB2 + 0x01 - [Channel4] - reverseroll + [Channel2] + beatsync + 0xB3 + 0x01 + + + + + + [EffectRack1_EffectUnit1_Effect1] + parameter1 MIDI Learned from 54 messages. - 0x95 - 0x26 + 0xBC + 0x01 - [Channel3] - vinylcontrol_enabled - MIDI Learned from 14 messages. - 0x94 - 0x25 + [EffectRack1_EffectUnit2_Effect1] + parameter1 + MIDI Learned from 144 messages. + 0xBD + 0x01 - [Channel3] - VestaxVCI400.deckSwitch + [Channel1] + VestaxVCI400.loadTrack + MIDI Learned from 96 messages. 0x92 - 0x23 + 0x02 - [Channel4] - vinylcontrol_enabled - MIDI Learned from 16 messages. - 0x95 - 0x25 + [Channel2] + VestaxVCI400.loadTrack + MIDI Learned from 98 messages. + 0x93 + 0x02 - + [Channel3] - vinylcontrol_mode - MIDI Learned from 4 messages. + VestaxVCI400.loadTrack + MIDI Learned from 100 messages. 0x94 - 0x24 + 0x02 - + [Channel4] - VestaxVCI400.deckSwitch - 0x93 - 0x23 + VestaxVCI400.loadTrack + MIDI Learned from 102 messages. + 0x95 + 0x02 - [Channel1] - VestaxVCI400.deckSwitch - 0x92 - 0x22 + [Master] + VestaxVCI400.fx1ToggleButton2 + 0x9C + 0x02 - [Channel4] - vinylcontrol_mode - MIDI Learned from 8 messages. - 0x95 - 0x24 + [Master] + VestaxVCI400.fx2ToggleButton2 + 0x9D + 0x02 - + - [Channel3] - reverseroll - MIDI Learned from 42 messages. - 0x94 - 0x23 + [Channel1] + VestaxVCI400.loadTrack + 0xB2 + 0x02 - + [Channel2] - VestaxVCI400.deckSwitch - 0x93 - 0x22 + VestaxVCI400.loadTrack + 0xB3 + 0x02 - [Channel2] - reverseroll - MIDI Learned from 48 messages. - 0x95 - 0x23 + [EffectRack1_EffectUnit1_Effect1] + parameter2 + MIDI Learned from 120 messages. + 0xBC + 0x02 - [Channel1] - reverseroll - MIDI Learned from 6 messages. - 0x94 - 0x22 + [EffectRack1_EffectUnit2_Effect1] + parameter2 + MIDI Learned from 308 messages. + 0xBD + 0x02 - [Channel4] - reverseroll - MIDI Learned from 30 messages. - 0x95 - 0x22 + [EffectRack1_EffectUnit1] + group_[Channel1]_enable + MIDI Learned from 2 messages. + 0x92 + 0x03 - [Channel3] - play - MIDI Learned from 8 messages. + [EffectRack1_EffectUnit1] + group_[Channel2]_enable + MIDI Learned from 6 messages. + 0x93 + 0x03 + + + + + + [EffectRack1_EffectUnit1] + group_[Channel3]_enable + MIDI Learned from 10 messages. 0x94 - 0x21 + 0x03 - [Channel4] - play - MIDI Learned from 26 messages. + [EffectRack1_EffectUnit1] + group_[Channel4]_enable + MIDI Learned from 14 messages. 0x95 - 0x21 + 0x03 - [Channel3] - cue_default - MIDI Learned from 25 messages. - 0x94 - 0x20 + [Master] + VestaxVCI400.fx1ToggleButton3 + 0x9C + 0x03 - + - [Channel1] - vinylcontrol_enabled - MIDI Learned from 10 messages. - 0x92 - 0x1E + [Master] + VestaxVCI400.fx2ToggleButton3 + 0x9D + 0x03 - + - [Channel4] - cue_default - MIDI Learned from 42 messages. - 0x95 - 0x20 + [EffectRack1_EffectUnit1_Effect1] + parameter3 + MIDI Learned from 116 messages. + 0xBC + 0x03 - [Channel3] - reverseroll - MIDI Learned from 24 messages. - 0x94 - 0x1F + [EffectRack1_EffectUnit2_Effect1] + parameter3 + MIDI Learned from 330 messages. + 0xBD + 0x03 - [Channel2] - vinylcontrol_enabled - MIDI Learned from 12 messages. - 0x93 - 0x1E + [EffectRack1_EffectUnit2] + group_[Channel1]_enable + MIDI Learned from 4 messages. + 0x92 + 0x04 - [Channel1] - vinylcontrol_mode - MIDI Learned from 2 messages. - 0x92 - 0x1D - - - - - - [Channel2] - reverseroll - MIDI Learned from 24 messages. - 0x95 - 0x1F + [EffectRack1_EffectUnit2] + group_[Channel2]_enable + MIDI Learned from 8 messages. + 0x93 + 0x04 - [Channel1] - reverseroll - MIDI Learned from 6 messages. + [EffectRack1_EffectUnit2] + group_[Channel3]_enable + MIDI Learned from 12 messages. 0x94 - 0x1E + 0x04 - [Channel2] - vinylcontrol_mode - MIDI Learned from 6 messages. - 0x93 - 0x1D + [EffectRack1_EffectUnit2] + group_[Channel4]_enable + MIDI Learned from 16 messages. + 0x95 + 0x04 - [Channel1] - play - MIDI Learned from 2 messages. - 0x92 - 0x1C + [Master] + VestaxVCI400.fx1ToggleButton4 + 0x9C + 0x04 - + - [Channel4] - reverseroll - MIDI Learned from 82 messages. - 0x95 - 0x1E + [Master] + VestaxVCI400.fx2ToggleButton4 + 0x9D + 0x04 - + - [Channel3] - play - MIDI Learned from 8 messages. - 0x94 - 0x1D + [EffectRack1_EffectUnit2] + VestaxVCI400.fx1Knob + MIDI Learned from 144 messages. + 0xBC + 0x04 - + - [Channel2] - play - MIDI Learned from 20 messages. - 0x93 - 0x1C + [EffectRack1_EffectUnit2] + VestaxVCI400.fx2Knob + MIDI Learned from 144 messages. + 0xBD + 0x04 - + [Channel1] - cue_default - MIDI Learned from 4 messages. + pfl + MIDI Learned from 46 messages. 0x92 - 0x1B + 0x05 - [Channel4] - play - MIDI Learned from 78 messages. - 0x95 - 0x1D + [Channel2] + pfl + MIDI Learned from 60 messages. + 0x93 + 0x05 [Channel3] - cue_default - MIDI Learned from 2 messages. + pfl + MIDI Learned from 17 messages. 0x94 - 0x1C + 0x05 - [Channel2] - cue_default - MIDI Learned from 22 messages. - 0x93 - 0x1B + [Channel4] + pfl + MIDI Learned from 70 messages. + 0x95 + 0x05 [Channel1] - play - MIDI Learned from 2 messages. - 0x92 - 0x1A + VestaxVCI400.pitchKnob + MIDI Learned from 35 messages. + 0xB2 + 0x05 - + - [Channel4] - cue_default - MIDI Learned from 80 messages. - 0x95 - 0x1C + [Channel2] + VestaxVCI400.pitchKnob + 0xB3 + 0x05 - + [Channel3] - reverseroll - MIDI Learned from 12 messages. - 0x94 - 0x1B + VestaxVCI400.pitchKnob + 0xB4 + 0x05 - + - [Channel2] - play - MIDI Learned from 14 messages. - 0x93 - 0x1A + [Channel4] + VestaxVCI400.pitchKnob + 0xB5 + 0x05 - + [Channel1] - cue_default - MIDI Learned from 4 messages. + VestaxVCI400.vinylButton + MIDI Learned from 2 messages. 0x92 - 0x19 + 0x06 - + - [Channel1] - VestaxVCI400.modeSampler - 0x92 - 0x18 + [Channel2] + VestaxVCI400.vinylButton + MIDI Learned from 6 messages. + 0x93 + 0x06 - [Channel2] - reverseroll - MIDI Learned from 18 messages. - 0x95 - 0x1B + [Channel3] + VestaxVCI400.vinylButton + MIDI Learned from 4 messages. + 0x94 + 0x06 - + - [Channel2] - cue_default - MIDI Learned from 16 messages. - 0x93 - 0x19 + [Channel4] + VestaxVCI400.vinylButton + MIDI Learned from 2 messages. + 0x95 + 0x06 - + - [Channel2] - VestaxVCI400.modeSampler - 0x93 - 0x18 + [Channel1] + VestaxVCI400.loopKnob + MIDI Learned from 3 messages. + 0xB2 + 0x06 - [Channel1] - VestaxVCI400.modeRoll - 0x92 - 0x17 + [Channel2] + VestaxVCI400.loopKnob + 0xB3 + 0x06 [Channel3] - VestaxVCI400.modeSampler - 0x94 - 0x18 + VestaxVCI400.loopKnob + 0xB4 + 0x06 - [Channel2] - VestaxVCI400.modeRoll - 0x93 - 0x17 + [Channel4] + VestaxVCI400.loopKnob + 0xB5 + 0x06 [Channel1] - VestaxVCI400.modeLoop + VestaxVCI400.padbutton1Activate + MIDI Learned from 2 messages. 0x92 - 0x16 + 0x07 - [Channel4] - VestaxVCI400.modeSampler - 0x95 - 0x18 + [Channel2] + VestaxVCI400.padbutton1Activate + MIDI Learned from 14 messages. + 0x93 + 0x07 [Channel3] - VestaxVCI400.modeRoll + VestaxVCI400.padbutton1Activate + MIDI Learned from 26 messages. 0x94 - 0x17 + 0x07 - [Channel2] - VestaxVCI400.modeLoop - 0x93 - 0x16 + [Channel4] + VestaxVCI400.padbutton1Activate + MIDI Learned from 20 messages. + 0x95 + 0x07 [Channel1] - VestaxVCI400.modeHotcue + VestaxVCI400.padbutton2Activate 0x92 - 0x15 + 0x08 - [Channel4] - VestaxVCI400.modeRoll - 0x95 - 0x17 - - + [Channel2] + VestaxVCI400.padbutton2Activate + 0x93 + 0x08 + + [Channel3] - VestaxVCI400.modeLoop + VestaxVCI400.padbutton2Activate 0x94 - 0x16 + 0x08 - [Channel2] - VestaxVCI400.modeHotcue - 0x93 - 0x15 + [Channel4] + VestaxVCI400.padbutton2Activate + 0x95 + 0x08 - [Channel1] - reloop_exit + [EffectRack1_EffectUnit1] + group_[Master]_enable MIDI Learned from 2 messages. - 0x92 - 0x14 + 0x9C + 0x08 - [Channel4] - VestaxVCI400.modeLoop - 0x95 - 0x16 + [EffectRack1_EffectUnit2] + group_[Master]_enable + MIDI Learned from 4 messages. + 0x9D + 0x08 - + - [Channel3] - VestaxVCI400.modeHotcue - 0x94 - 0x15 + [Channel1] + VestaxVCI400.padbutton3Activate + MIDI Learned from 6 messages. + 0x92 + 0x09 [Channel2] - reloop_exit - MIDI Learned from 2 messages. + VestaxVCI400.padbutton3Activate + MIDI Learned from 18 messages. 0x93 - 0x14 + 0x09 - + - [Channel1] - rate - MIDI Learned from 560 messages. - 0xB2 - 0x32 + [Channel3] + VestaxVCI400.padbutton3Activate + MIDI Learned from 10 messages. + 0x94 + 0x09 - - + [Channel4] - VestaxVCI400.modeHotcue + VestaxVCI400.padbutton3Activate + MIDI Learned from 24 messages. 0x95 - 0x15 + 0x09 - [Channel3] - reloop_exit + [EffectRack1_EffectUnit1] + next_chain MIDI Learned from 2 messages. - 0x94 - 0x14 + 0x9C + 0x09 - [Channel2] - rate - MIDI Learned from 2184 messages. - 0xB3 - 0x32 - - - - - - - [Channel1] - volume - MIDI Learned from 432 messages. - 0xB2 - 0x31 - - - - - - [Channel4] - reloop_exit - MIDI Learned from 2 messages. - 0x95 - 0x14 + [EffectRack1_EffectUnit2] + next_chain + MIDI Learned from 4 messages. + 0x9D + 0x09 [Channel1] - pitch_adjust_set_default + VestaxVCI400.padbutton4Activate MIDI Learned from 4 messages. 0x92 - 0x11 - - - - - - [Channel3] - rate - MIDI Learned from 540 messages. - 0xB4 - 0x32 - - - - - - - [Channel2] - volume - 0xB3 - 0x31 + 0x0A - + [Channel2] - pitch_adjust_set_default - MIDI Learned from 4 messages. + VestaxVCI400.padbutton4Activate + MIDI Learned from 16 messages. 0x93 - 0x11 - - - - - - [Channel4] - rate - MIDI Learned from 3496 messages. - 0xB5 - 0x32 - - - - - - - [Channel3] - volume - MIDI Learned from 48 messages. - 0xB4 - 0x31 + 0x0A - + [Channel3] - pitch_adjust_set_default - MIDI Learned from 4 messages. + VestaxVCI400.padbutton4Activate + MIDI Learned from 12 messages. 0x94 - 0x11 - - - - - - [Channel4] - volume - MIDI Learned from 1056 messages. - 0xB5 - 0x31 + 0x0A - + [Channel4] - pitch_adjust_set_default - MIDI Learned from 4 messages. + VestaxVCI400.padbutton4Activate + MIDI Learned from 22 messages. 0x95 - 0x11 + 0x0A - + [Channel1] - VestaxVCI400.padbutton8Activate - MIDI Learned from 2 messages. + VestaxVCI400.padbutton5Activate + MIDI Learned from 8 messages. 0x92 - 0x0E + 0x0B [Channel2] - VestaxVCI400.padbutton8Activate - MIDI Learned from 18 messages. + VestaxVCI400.padbutton5Activate + MIDI Learned from 24 messages. 0x93 - 0x0E - - - - - - [Channel1] - VestaxVCI400.padbutton7Activate - MIDI Learned from 4 messages. - 0x92 - 0x0D + 0x0B [Channel3] - VestaxVCI400.padbutton8Activate - MIDI Learned from 10 messages. + VestaxVCI400.padbutton5Activate + MIDI Learned from 16 messages. 0x94 - 0x0E + 0x0B - [Channel2] - VestaxVCI400.padbutton7Activate - MIDI Learned from 20 messages. - 0x93 - 0x0D + [Channel4] + VestaxVCI400.padbutton5Activate + MIDI Learned from 32 messages. + 0x95 + 0x0B @@ -820,29 +768,27 @@ - [Channel4] - VestaxVCI400.padbutton8Activate - MIDI Learned from 26 messages. - 0x95 - 0x0E + [Channel2] + VestaxVCI400.padbutton6Activate + 0x93 + 0x0C [Channel3] - VestaxVCI400.padbutton7Activate - MIDI Learned from 12 messages. + VestaxVCI400.padbutton6Activate 0x94 - 0x0D + 0x0C - [Channel2] + [Channel4] VestaxVCI400.padbutton6Activate - 0x93 + 0x95 0x0C @@ -850,1141 +796,1195 @@ [Channel1] - VestaxVCI400.padbutton5Activate - MIDI Learned from 8 messages. - 0x92 - 0x0B + pregain + MIDI Learned from 770 messages. + 0xB2 + 0x0C - + - [Channel4] - VestaxVCI400.padbutton7Activate - MIDI Learned from 28 messages. - 0x95 - 0x0D + [Channel2] + pregain + MIDI Learned from 700 messages. + 0xB3 + 0x0C - + [Channel3] - VestaxVCI400.padbutton6Activate - 0x94 + pregain + MIDI Learned from 368 messages. + 0xB4 0x0C - + - [Channel2] - VestaxVCI400.padbutton5Activate - MIDI Learned from 24 messages. - 0x93 - 0x0B + [Channel4] + pregain + MIDI Learned from 680 messages. + 0xB5 + 0x0C - + [Channel1] - VestaxVCI400.padbutton4Activate + VestaxVCI400.padbutton7Activate MIDI Learned from 4 messages. 0x92 - 0x0A + 0x0D - [Channel4] - VestaxVCI400.padbutton6Activate - 0x95 - 0x0C + [Channel2] + VestaxVCI400.padbutton7Activate + MIDI Learned from 20 messages. + 0x93 + 0x0D [Channel3] - VestaxVCI400.padbutton5Activate - MIDI Learned from 16 messages. + VestaxVCI400.padbutton7Activate + MIDI Learned from 12 messages. 0x94 - 0x0B + 0x0D - [Channel2] - VestaxVCI400.padbutton4Activate - MIDI Learned from 16 messages. - 0x93 - 0x0A + [Channel4] + VestaxVCI400.padbutton7Activate + MIDI Learned from 28 messages. + 0x95 + 0x0D - [Channel1] - VestaxVCI400.padbutton3Activate - MIDI Learned from 6 messages. - 0x92 - 0x09 + [EqualizerRack1_[Channel1]_Effect1] + parameter3 + MIDI Learned from 651 messages. + 0xB2 + 0x0D - + - [Channel4] - VestaxVCI400.padbutton5Activate - MIDI Learned from 32 messages. - 0x95 - 0x0B + [EqualizerRack1_[Channel2]_Effect1] + parameter3 + MIDI Learned from 648 messages. + 0xB3 + 0x0D - + - [Channel3] - VestaxVCI400.padbutton4Activate - MIDI Learned from 12 messages. - 0x94 - 0x0A + [EqualizerRack1_[Channel3]_Effect1] + parameter3 + MIDI Learned from 405 messages. + 0xB4 + 0x0D - + - [Channel2] - VestaxVCI400.padbutton3Activate - MIDI Learned from 18 messages. - 0x93 - 0x09 + [EqualizerRack1_[Channel4]_Effect1] + parameter3 + MIDI Learned from 759 messages. + 0xB5 + 0x0D - + [Channel1] - VestaxVCI400.padbutton2Activate + VestaxVCI400.padbutton8Activate + MIDI Learned from 2 messages. 0x92 - 0x08 + 0x0E - [Channel4] - VestaxVCI400.padbutton4Activate - MIDI Learned from 22 messages. - 0x95 - 0x0A + [Channel2] + VestaxVCI400.padbutton8Activate + MIDI Learned from 18 messages. + 0x93 + 0x0E [Channel3] - VestaxVCI400.padbutton3Activate + VestaxVCI400.padbutton8Activate MIDI Learned from 10 messages. 0x94 - 0x09 + 0x0E - [Channel2] - VestaxVCI400.padbutton2Activate - 0x93 - 0x08 + [Channel4] + VestaxVCI400.padbutton8Activate + MIDI Learned from 26 messages. + 0x95 + 0x0E - [Channel1] - VestaxVCI400.padbutton1Activate - MIDI Learned from 2 messages. - 0x92 - 0x07 + [EqualizerRack1_[Channel1]_Effect1] + parameter2 + MIDI Learned from 560 messages. + 0xB2 + 0x0E - + - [Channel4] - VestaxVCI400.padbutton3Activate - MIDI Learned from 24 messages. - 0x95 - 0x09 + [EqualizerRack1_[Channel2]_Effect1] + parameter2 + MIDI Learned from 572 messages. + 0xB3 + 0x0E - + - [Channel3] - VestaxVCI400.padbutton2Activate - 0x94 - 0x08 + [EqualizerRack1_[Channel3]_Effect1] + parameter2 + MIDI Learned from 378 messages. + 0xB4 + 0x0E - + - [Channel2] - VestaxVCI400.padbutton1Activate - MIDI Learned from 14 messages. - 0x93 - 0x07 + [EqualizerRack1_[Channel4]_Effect1] + parameter2 + MIDI Learned from 704 messages. + 0xB5 + 0x0E - + - [Channel1] - VestaxVCI400.vinylButton - MIDI Learned from 2 messages. - 0x92 - 0x06 + [EqualizerRack1_[Channel1]_Effect1] + parameter1 + MIDI Learned from 513 messages. + 0xB2 + 0x0F - + - [Channel4] - VestaxVCI400.padbutton2Activate - 0x95 - 0x08 + [EqualizerRack1_[Channel2]_Effect1] + parameter1 + MIDI Learned from 550 messages. + 0xB3 + 0x0F - + - [Channel3] - VestaxVCI400.padbutton1Activate - MIDI Learned from 26 messages. - 0x94 - 0x07 + [EqualizerRack1_[Channel3]_Effect1] + parameter1 + MIDI Learned from 338 messages. + 0xB4 + 0x0F - + - [Channel2] - VestaxVCI400.vinylButton - MIDI Learned from 6 messages. - 0x93 - 0x06 + [EqualizerRack1_[Channel4]_Effect1] + parameter1 + MIDI Learned from 775 messages. + 0xB5 + 0x0F - + - [Channel1] - pfl - MIDI Learned from 46 messages. - 0x92 - 0x05 + [QuickEffectRack1_[Channel1]] + super1 + MIDI Learned from 106 messages. + 0xB2 + 0x10 - [Channel4] - VestaxVCI400.padbutton1Activate - MIDI Learned from 20 messages. - 0x95 - 0x07 + [QuickEffectRack1_[Channel2]] + super1 + MIDI Learned from 226 messages. + 0xB3 + 0x10 - + - [Channel3] - VestaxVCI400.vinylButton - MIDI Learned from 4 messages. - 0x94 - 0x06 + [QuickEffectRack1_[Channel3]] + super1 + MIDI Learned from 213 messages. + 0xB4 + 0x10 - + - [Channel2] - pfl - MIDI Learned from 60 messages. - 0x93 - 0x05 + [QuickEffectRack1_[Channel4]] + super1 + MIDI Learned from 248 messages. + 0xB5 + 0x10 - [EffectRack1_EffectUnit2] - group_[Channel1]_enable + [Channel1] + pitch_adjust_set_default MIDI Learned from 4 messages. 0x92 - 0x04 + 0x11 - [Master] - VestaxVCI400.shiftActivate - 0x90 - 0x01 - - - - - - [Channel4] - VestaxVCI400.vinylButton - MIDI Learned from 2 messages. - 0x95 - 0x06 + [Channel2] + pitch_adjust_set_default + MIDI Learned from 4 messages. + 0x93 + 0x11 - + [Channel3] - pfl - MIDI Learned from 17 messages. + pitch_adjust_set_default + MIDI Learned from 4 messages. 0x94 - 0x05 + 0x11 - [EffectRack1_EffectUnit2] - group_[Channel2]_enable - MIDI Learned from 8 messages. - 0x93 - 0x04 + [Channel4] + pitch_adjust_set_default + MIDI Learned from 4 messages. + 0x95 + 0x11 - [EffectRack1_EffectUnit1] - group_[Channel1]_enable - MIDI Learned from 2 messages. - 0x92 - 0x03 + [Channel1] + volume + MIDI Learned from 432 messages. + 0xB2 + 0x11 - + - [Channel1] - VestaxVCI400.loadTrack - MIDI Learned from 96 messages. - 0x92 - 0x02 + [Channel2] + volume + 0xB3 + 0x11 - + - [Channel4] - pfl - MIDI Learned from 70 messages. - 0x95 - 0x05 + [Channel3] + volume + MIDI Learned from 48 messages. + 0xB4 + 0x11 - + - [EffectRack1_EffectUnit2] - group_[Channel3]_enable - MIDI Learned from 12 messages. - 0x94 - 0x04 + [Channel4] + volume + MIDI Learned from 1056 messages. + 0xB5 + 0x11 - + - [EffectRack1_EffectUnit1] - group_[Channel2]_enable - MIDI Learned from 6 messages. - 0x93 - 0x03 + [Channel1] + rate + MIDI Learned from 560 messages. + 0xB2 + 0x12 - + + [Channel2] - VestaxVCI400.loadTrack - MIDI Learned from 98 messages. - 0x93 - 0x02 + rate + MIDI Learned from 2184 messages. + 0xB3 + 0x12 - + + - [Channel1] - sync_enabled - MIDI Learned from 22 messages. - 0x92 - 0x01 + [Channel3] + rate + MIDI Learned from 540 messages. + 0xB4 + 0x12 - + + - [EffectRack1_EffectUnit2] - group_[Channel4]_enable - MIDI Learned from 16 messages. - 0x95 - 0x04 + [Channel4] + rate + MIDI Learned from 3496 messages. + 0xB5 + 0x12 - + + - [EffectRack1_EffectUnit1] - group_[Channel3]_enable - MIDI Learned from 10 messages. - 0x94 - 0x03 + [Channel1] + VestaxVCI400.wheelMove + 0xB2 + 0x13 - + - [EffectRack1_EffectUnit1] - group_[Channel4]_enable - MIDI Learned from 14 messages. - 0x95 - 0x03 + [Channel2] + VestaxVCI400.wheelMove + 0xB3 + 0x13 - + [Channel3] - VestaxVCI400.loadTrack - MIDI Learned from 100 messages. - 0x94 - 0x02 + VestaxVCI400.wheelMove + 0xB4 + 0x13 - - [Channel2] - sync_enabled - MIDI Learned from 88 messages. - 0x93 - 0x01 - - - - [Channel4] - VestaxVCI400.loadTrack - MIDI Learned from 102 messages. - 0x95 - 0x02 + VestaxVCI400.wheelMove + 0xB5 + 0x13 - [Channel3] - sync_enabled - MIDI Learned from 24 messages. - 0x94 - 0x01 + [Channel1] + reloop_exit + MIDI Learned from 2 messages. + 0x92 + 0x14 - [Master] - volume - MIDI Learned from 928 messages. - 0xBE - 0x2B + [Channel2] + reloop_exit + MIDI Learned from 2 messages. + 0x93 + 0x14 - [EffectRack1_EffectUnit1] - next_chain + [Channel3] + reloop_exit MIDI Learned from 2 messages. - 0x9C - 0x09 + 0x94 + 0x14 [Channel4] - sync_enabled - MIDI Learned from 90 messages. + reloop_exit + MIDI Learned from 2 messages. 0x95 - 0x01 + 0x14 [Master] - headMix - 0xBE - 0x2A + crossfader + 0xB0 + 0x14 - [EffectRack1_EffectUnit2] - next_chain - MIDI Learned from 4 messages. - 0x9D - 0x09 + [Channel1] + VestaxVCI400.beatLoop + 0xB2 + 0x14 - + - [EffectRack1_EffectUnit1] - group_[Master]_enable - MIDI Learned from 2 messages. - 0x9C - 0x08 + [Channel1] + VestaxVCI400.modeHotcue + 0x92 + 0x15 - + - [EffectRack1_EffectUnit2] - group_[Master]_enable - MIDI Learned from 4 messages. - 0x9D - 0x08 + [Channel2] + VestaxVCI400.modeHotcue + 0x93 + 0x15 - + - [Playlist] - SelectTrackKnob - MIDI Learned from 13 messages. - 0xBE - 0x28 + [Channel3] + VestaxVCI400.modeHotcue + 0x94 + 0x15 - + - [Master] - VestaxVCI400.fx1ToggleButton4 - 0x9C - 0x04 + [Channel4] + VestaxVCI400.modeHotcue + 0x95 + 0x15 - [Master] - VestaxVCI400.fx1ToggleButton3 - 0x9C - 0x03 + [Channel1] + VestaxVCI400.modeLoop + 0x92 + 0x16 - [Master] - VestaxVCI400.fx2ToggleButton4 - 0x9D - 0x04 + [Channel2] + VestaxVCI400.modeLoop + 0x93 + 0x16 - [Master] - VestaxVCI400.fx1ToggleButton2 - 0x9C - 0x02 + [Channel3] + VestaxVCI400.modeLoop + 0x94 + 0x16 - [Master] - VestaxVCI400.fx2ToggleButton3 - 0x9D - 0x03 + [Channel4] + VestaxVCI400.modeLoop + 0x95 + 0x16 - [Master] - VestaxVCI400.fx1ToggleButton1 - 0x9C - 0x01 + [Channel1] + VestaxVCI400.modeRoll + 0x92 + 0x17 - [Master] - VestaxVCI400.fx2ToggleButton2 - 0x9D - 0x02 + [Channel2] + VestaxVCI400.modeRoll + 0x93 + 0x17 - [Master] - VestaxVCI400.fx2ToggleButton1 - 0x9D - 0x01 + [Channel3] + VestaxVCI400.modeRoll + 0x94 + 0x17 - [Master] - crossfader - 0xB0 - 0x14 + [Channel4] + VestaxVCI400.modeRoll + 0x95 + 0x17 - + [Channel1] - VestaxVCI400.beatLoop - 0xB2 - 0x14 + VestaxVCI400.modeSampler + 0x92 + 0x18 - [Channel1] - VestaxVCI400.wheelMove - 0xB2 - 0x13 + [Channel2] + VestaxVCI400.modeSampler + 0x93 + 0x18 - [Channel2] - VestaxVCI400.wheelMove - 0xB3 - 0x13 + [Channel3] + VestaxVCI400.modeSampler + 0x94 + 0x18 - [Channel1] - rate - MIDI Learned from 560 messages. - 0xB2 - 0x12 + [Channel4] + VestaxVCI400.modeSampler + 0x95 + 0x18 - - + - [Channel3] - VestaxVCI400.wheelMove - 0xB4 - 0x13 + [Channel1] + cue_default + MIDI Learned from 4 messages. + 0x92 + 0x19 - + [Channel2] - rate - MIDI Learned from 2184 messages. - 0xB3 - 0x12 + cue_default + MIDI Learned from 16 messages. + 0x93 + 0x19 - - + [Channel1] - volume - MIDI Learned from 432 messages. - 0xB2 - 0x11 + VestaxVCI400.playButton + MIDI Learned from 2 messages. + 0x92 + 0x1A - + - [Channel4] - VestaxVCI400.wheelMove - 0xB5 - 0x13 + [Channel2] + VestaxVCI400.playButton + MIDI Learned from 14 messages. + 0x93 + 0x1A - [Channel3] - rate - MIDI Learned from 540 messages. - 0xB4 - 0x12 + [Channel1] + cue_default + MIDI Learned from 4 messages. + 0x92 + 0x1B - - + [Channel2] - volume - 0xB3 - 0x11 + cue_default + MIDI Learned from 22 messages. + 0x93 + 0x1B - + - [QuickEffectRack1_[Channel1]] - super1 - MIDI Learned from 106 messages. - 0xB2 - 0x10 + [Channel3] + VestaxVCI400.censorButton + MIDI Learned from 12 messages. + 0x94 + 0x1B - + - [Channel4] - rate - MIDI Learned from 3496 messages. - 0xB5 - 0x12 + [Channel2] + VestaxVCI400.censorButton + MIDI Learned from 18 messages. + 0x95 + 0x1B - - + - [Channel3] - volume - MIDI Learned from 48 messages. - 0xB4 - 0x11 + [Channel1] + VestaxVCI400.playButton + MIDI Learned from 2 messages. + 0x92 + 0x1C - + - [EqualizerRack1_[Channel1]_Effect1] - parameter1 - MIDI Learned from 513 messages. - 0xB2 - 0x0F + [Channel2] + VestaxVCI400.playButton + MIDI Learned from 20 messages. + 0x93 + 0x1C - + - [QuickEffectRack1_[Channel2]] - super1 - MIDI Learned from 226 messages. - 0xB3 - 0x10 + [Channel3] + cue_default + MIDI Learned from 2 messages. + 0x94 + 0x1C [Channel4] - volume - MIDI Learned from 1056 messages. - 0xB5 - 0x11 + cue_default + MIDI Learned from 80 messages. + 0x95 + 0x1C - + - [EqualizerRack1_[Channel2]_Effect1] - parameter1 - MIDI Learned from 550 messages. - 0xB3 - 0x0F + [Channel1] + vinylcontrol_mode + MIDI Learned from 2 messages. + 0x92 + 0x1D - [EqualizerRack1_[Channel1]_Effect1] - parameter2 - MIDI Learned from 560 messages. - 0xB2 - 0x0E + [Channel2] + vinylcontrol_mode + MIDI Learned from 6 messages. + 0x93 + 0x1D - [QuickEffectRack1_[Channel3]] - super1 - MIDI Learned from 213 messages. - 0xB4 - 0x10 + [Channel3] + VestaxVCI400.playButton + MIDI Learned from 8 messages. + 0x94 + 0x1D - + - [EqualizerRack1_[Channel3]_Effect1] - parameter1 - MIDI Learned from 338 messages. - 0xB4 - 0x0F + [Channel4] + VestaxVCI400.playButton + MIDI Learned from 78 messages. + 0x95 + 0x1D - + - [EqualizerRack1_[Channel2]_Effect1] - parameter2 - MIDI Learned from 572 messages. - 0xB3 - 0x0E + [Channel1] + vinylcontrol_enabled + MIDI Learned from 10 messages. + 0x92 + 0x1E - [EqualizerRack1_[Channel1]_Effect1] - parameter3 - MIDI Learned from 651 messages. - 0xB2 - 0x0D + [Channel2] + vinylcontrol_enabled + MIDI Learned from 12 messages. + 0x93 + 0x1E - [QuickEffectRack1_[Channel4]] - super1 - MIDI Learned from 248 messages. - 0xB5 - 0x10 + [Channel1] + VestaxVCI400.censorButton + MIDI Learned from 6 messages. + 0x94 + 0x1E - + - [EqualizerRack1_[Channel4]_Effect1] - parameter1 - MIDI Learned from 775 messages. - 0xB5 - 0x0F + [Channel4] + VestaxVCI400.censorButton + MIDI Learned from 82 messages. + 0x95 + 0x1E - + - [EqualizerRack1_[Channel3]_Effect1] - parameter2 - MIDI Learned from 378 messages. - 0xB4 - 0x0E + [Channel3] + VestaxVCI400.censorButton + MIDI Learned from 24 messages. + 0x94 + 0x1F - + - [EqualizerRack1_[Channel2]_Effect1] - parameter3 - MIDI Learned from 648 messages. - 0xB3 - 0x0D + [Channel2] + VestaxVCI400.censorButton + MIDI Learned from 24 messages. + 0x95 + 0x1F - + - [Channel1] - pregain - MIDI Learned from 770 messages. - 0xB2 - 0x0C + [Channel3] + cue_default + MIDI Learned from 25 messages. + 0x94 + 0x20 - [EqualizerRack1_[Channel4]_Effect1] - parameter2 - MIDI Learned from 704 messages. - 0xB5 - 0x0E + [Channel4] + cue_default + MIDI Learned from 42 messages. + 0x95 + 0x20 - [EqualizerRack1_[Channel3]_Effect1] - parameter3 - MIDI Learned from 405 messages. - 0xB4 - 0x0D + [Channel3] + VestaxVCI400.playButton + MIDI Learned from 8 messages. + 0x94 + 0x21 - + + + + + [Channel4] + VestaxVCI400.playButton + MIDI Learned from 26 messages. + 0x95 + 0x21 + + + + + + [Channel1] + VestaxVCI400.deckSwitch + 0x92 + 0x22 + + [Channel2] - pregain - MIDI Learned from 700 messages. - 0xB3 - 0x0C + VestaxVCI400.deckSwitch + 0x93 + 0x22 - + - [EqualizerRack1_[Channel4]_Effect1] - parameter3 - MIDI Learned from 759 messages. - 0xB5 - 0x0D + [Channel1] + VestaxVCI400.censorButton + MIDI Learned from 6 messages. + 0x94 + 0x22 - + + + + + [Channel4] + VestaxVCI400.censorButton + MIDI Learned from 30 messages. + 0x95 + 0x22 + + [Channel3] - pregain - MIDI Learned from 368 messages. - 0xB4 - 0x0C + VestaxVCI400.deckSwitch + 0x92 + 0x23 - + [Channel4] - pregain - MIDI Learned from 680 messages. - 0xB5 - 0x0C + VestaxVCI400.deckSwitch + 0x93 + 0x23 - + - [Channel1] - VestaxVCI400.loopKnob - MIDI Learned from 3 messages. - 0xB2 - 0x06 + [Channel3] + VestaxVCI400.censorButton + MIDI Learned from 42 messages. + 0x94 + 0x23 [Channel2] - VestaxVCI400.loopKnob - 0xB3 - 0x06 + VestaxVCI400.censorButton + MIDI Learned from 48 messages. + 0x95 + 0x23 + + + + + + [Channel3] + vinylcontrol_mode + MIDI Learned from 4 messages. + 0x94 + 0x24 + + + + + + [Channel4] + vinylcontrol_mode + MIDI Learned from 8 messages. + 0x95 + 0x24 + + + + + + [Channel3] + vinylcontrol_enabled + MIDI Learned from 14 messages. + 0x94 + 0x25 + + + + + + [Channel4] + vinylcontrol_enabled + MIDI Learned from 16 messages. + 0x95 + 0x25 - + [Channel1] - VestaxVCI400.pitchKnob - MIDI Learned from 35 messages. - 0xB2 - 0x05 + VestaxVCI400.censorButton + MIDI Learned from 36 messages. + 0x94 + 0x26 - [Channel3] - VestaxVCI400.loopKnob - 0xB4 - 0x06 + [Channel4] + VestaxVCI400.censorButton + MIDI Learned from 54 messages. + 0x95 + 0x26 - [Channel2] - VestaxVCI400.pitchKnob - 0xB3 - 0x05 + [Channel1] + VestaxVCI400.wheelTouch + 0x92 + 0x27 - [Channel4] - VestaxVCI400.loopKnob - 0xB5 - 0x06 + [Channel2] + VestaxVCI400.wheelTouch + 0x93 + 0x27 [Channel3] - VestaxVCI400.pitchKnob - 0xB4 - 0x05 + VestaxVCI400.wheelTouch + 0x94 + 0x27 [Channel4] - VestaxVCI400.pitchKnob - 0xB5 - 0x05 + VestaxVCI400.wheelTouch + 0x95 + 0x27 - [Channel1] - VestaxVCI400.loadTrack - 0xB2 - 0x02 + [Library] + MoveVertical + MIDI Learned from 7 messages. + 0xBE + 0x28 - + - [Channel2] - VestaxVCI400.loadTrack - 0xB3 - 0x02 + [Master] + headMix + 0xBE + 0x2A - + - [Channel1] - beatsync - 0xB2 - 0x01 + [Master] + volume + MIDI Learned from 928 messages. + 0xBE + 0x2B - [Channel2] - beatsync - 0xB3 - 0x01 + [Channel1] + volume + MIDI Learned from 432 messages. + 0xB2 + 0x31 - + - [EffectRack1_EffectUnit2] - VestaxVCI400.fx1Knob - MIDI Learned from 144 messages. - 0xBC - 0x04 + [Channel2] + volume + 0xB3 + 0x31 - + - [EffectRack1_EffectUnit1_Effect1] - parameter3 - MIDI Learned from 116 messages. - 0xBC - 0x03 + [Channel3] + volume + MIDI Learned from 48 messages. + 0xB4 + 0x31 - + - [EffectRack1_EffectUnit2] - VestaxVCI400.fx2Knob - MIDI Learned from 144 messages. - 0xBD - 0x04 + [Channel4] + volume + MIDI Learned from 1056 messages. + 0xB5 + 0x31 - + - [EffectRack1_EffectUnit1_Effect1] - parameter2 - MIDI Learned from 120 messages. - 0xBC - 0x02 + [Channel1] + rate + MIDI Learned from 560 messages. + 0xB2 + 0x32 - + + - [EffectRack1_EffectUnit2_Effect1] - parameter3 - MIDI Learned from 330 messages. - 0xBD - 0x03 + [Channel2] + rate + MIDI Learned from 2184 messages. + 0xB3 + 0x32 - + + - [EffectRack1_EffectUnit1_Effect1] - parameter1 - MIDI Learned from 54 messages. - 0xBC - 0x01 + [Channel3] + rate + MIDI Learned from 540 messages. + 0xB4 + 0x32 - + + - [EffectRack1_EffectUnit2_Effect1] - parameter2 - MIDI Learned from 308 messages. - 0xBD - 0x02 + [Channel4] + rate + MIDI Learned from 3496 messages. + 0xB5 + 0x32 - + + - [EffectRack1_EffectUnit2_Effect1] - parameter1 - MIDI Learned from 144 messages. - 0xBD - 0x01 + [Library] + MoveFocus + MIDI Learned from 2 messages. + 0x9E + 0x71 @@ -1992,60 +1992,60 @@ - [Channel3] - play_indicator - 0x94 - 0x21 + [Channel1] + cue_indicator + 0x92 + 0x1B 0.5 - [Channel3] - play_indicator - 0x94 - 0x1D + [Channel1] + cue_indicator + 0x92 + 0x19 0.5 - [EffectRack1_EffectUnit2] - group_[Master]_enable - 0x9D - 0x08 - 0.5 + [Channel1] + pfl + 0x92 + 0x05 + 0.1 - [Channel2] - reverse - 0x95 - 0x23 + [Channel1] + play_indicator + 0x92 + 0x1C 0.5 - [Channel2] - reverse - 0x95 - 0x1F + [Channel1] + play_indicator + 0x92 + 0x1A 0.5 - [Channel2] + [Channel1] reverse - 0x95 - 0x1B + 0x94 + 0x26 0.5 - [EffectRack1_EffectUnit1] - next_chain - 0x9C - 0x09 + [Channel1] + reverse + 0x94 + 0x22 0.5 - [Channel2] - pfl - 0x93 - 0x05 - 0.1 + [Channel1] + reverse + 0x94 + 0x1E + 0.5 [Channel1] @@ -2054,6 +2054,13 @@ 0x01 0.5 + + [Channel1] + vinylcontrol_enabled + 0x92 + 0x1E + 0.5 + [Channel1] vinylcontrol_mode @@ -2076,68 +2083,61 @@ 0.5 - [Channel4] - vinylcontrol_enabled - 0x95 - 0x25 - 0.5 + [Channel2] + pfl + 0x93 + 0x05 + 0.1 - [EffectRack1_EffectUnit1] - group_[Channel2]_enable + [Channel2] + play_indicator 0x93 - 0x03 + 0x1C 0.5 - [Channel4] + [Channel2] play_indicator - 0x95 - 0x21 + 0x93 + 0x1A 0.5 - [Channel4] - play_indicator + [Channel2] + reverse 0x95 - 0x1D + 0x23 0.5 - [EffectRack1_EffectUnit1] - group_[Channel4]_enable + [Channel2] + reverse 0x95 - 0x03 + 0x1F 0.5 - [Channel1] + [Channel2] reverse - 0x94 - 0x26 + 0x95 + 0x1B 0.5 - [Channel1] - reverse - 0x94 - 0x22 + [Channel2] + sync_enabled + 0x93 + 0x01 0.5 - [Channel1] - reverse - 0x94 + [Channel2] + vinylcontrol_enabled + 0x93 0x1E 0.5 - - [Channel3] - pfl - 0x94 - 0x05 - 0.1 - [Channel2] vinylcontrol_mode @@ -2146,66 +2146,73 @@ 0.2 - [Channel1] + [Channel3] cue_indicator - 0x92 - 0x1B + 0x94 + 0x20 0.5 - [Channel1] + [Channel3] cue_indicator - 0x92 - 0x19 + 0x94 + 0x1C 0.5 - [EffectRack1_EffectUnit2] - group_[Channel2]_enable - 0x93 - 0x04 - 0.5 + [Channel3] + pfl + 0x94 + 0x05 + 0.1 [Channel3] - vinylcontrol_enabled + play_indicator 0x94 - 0x25 + 0x21 0.5 - [Channel1] + [Channel3] play_indicator - 0x92 - 0x1C + 0x94 + 0x1D 0.5 - [Channel1] - play_indicator - 0x92 - 0x1A + [Channel3] + reverse + 0x94 + 0x23 0.5 - [Channel4] - sync_enabled - 0x95 - 0x01 + [Channel3] + reverse + 0x94 + 0x1F 0.5 - [EffectRack1_EffectUnit1] - group_[Channel1]_enable - 0x92 - 0x03 + [Channel3] + reverse + 0x94 + 0x1B 0.5 - [EffectRack1_EffectUnit2] - group_[Channel4]_enable - 0x95 - 0x04 + [Channel3] + sync_enabled + 0x94 + 0x01 + 0.5 + + + [Channel3] + vinylcontrol_enabled + 0x94 + 0x25 0.5 @@ -2237,17 +2244,17 @@ 0.1 - [Channel2] - vinylcontrol_enabled - 0x93 - 0x1E + [Channel4] + play_indicator + 0x95 + 0x21 0.5 - [EffectRack1_EffectUnit1] - group_[Channel3]_enable - 0x94 - 0x03 + [Channel4] + play_indicator + 0x95 + 0x1D 0.5 @@ -2272,31 +2279,17 @@ 0.5 - [Channel2] - play_indicator - 0x93 - 0x1C - 0.5 - - - [Channel2] - play_indicator - 0x93 - 0x1A - 0.5 - - - [Channel3] + [Channel4] sync_enabled - 0x94 + 0x95 0x01 0.5 - [EffectRack1_EffectUnit2] - group_[Channel1]_enable - 0x92 - 0x04 + [Channel4] + vinylcontrol_enabled + 0x95 + 0x25 0.5 @@ -2307,80 +2300,87 @@ 0.2 - [Channel3] - cue_indicator - 0x94 - 0x20 + [EffectRack1_EffectUnit1] + group_[Channel1]_enable + 0x92 + 0x03 0.5 - [Channel3] - cue_indicator + [EffectRack1_EffectUnit1] + group_[Channel2]_enable + 0x93 + 0x03 + 0.5 + + + [EffectRack1_EffectUnit1] + group_[Channel3]_enable 0x94 - 0x1C + 0x03 0.5 [EffectRack1_EffectUnit1] - group_[Master]_enable - 0x9C - 0x08 + group_[Channel4]_enable + 0x95 + 0x03 0.5 - [Channel1] - vinylcontrol_enabled - 0x92 - 0x1E + [EffectRack1_EffectUnit1] + group_[Master]_enable + 0x9C + 0x08 0.5 - [EffectRack1_EffectUnit2] + [EffectRack1_EffectUnit1] next_chain - 0x9D + 0x9C 0x09 0.5 - [Channel1] - pfl + [EffectRack1_EffectUnit2] + group_[Channel1]_enable 0x92 - 0x05 - 0.1 + 0x04 + 0.5 [EffectRack1_EffectUnit2] - group_[Channel3]_enable - 0x94 + group_[Channel2]_enable + 0x93 0x04 0.5 - [Channel3] - reverse + [EffectRack1_EffectUnit2] + group_[Channel3]_enable 0x94 - 0x23 + 0x04 0.5 - [Channel3] - reverse - 0x94 - 0x1F + [EffectRack1_EffectUnit2] + group_[Channel4]_enable + 0x95 + 0x04 0.5 - [Channel3] - reverse - 0x94 - 0x1B + [EffectRack1_EffectUnit2] + group_[Master]_enable + 0x9D + 0x08 0.5 - [Channel2] - sync_enabled - 0x93 - 0x01 + [EffectRack1_EffectUnit2] + next_chain + 0x9D + 0x09 0.5 diff --git a/res/controllers/Vestax-VCI-400-scripts.js b/res/controllers/Vestax-VCI-400-scripts.js index 1da2432f485d..11776ca975ad 100644 --- a/res/controllers/Vestax-VCI-400-scripts.js +++ b/res/controllers/Vestax-VCI-400-scripts.js @@ -678,17 +678,31 @@ VestaxVCI400.Deck.prototype.onWheelMove = function(value) { } }; -VestaxVCI400.brake = function (channel, control, value, status, group) { - try{ - if (value == 0) { - return; - } - var deck = VestaxVCI400.GetDeck(group).deckNumber; - engine.brake(deck, true, .1, .9); +// The play button usually does play/pause as normal, but if shift is held +// we do a braking stop. +VestaxVCI400.playButton = function (channel, control, value, status, group) { + if (value === 0) { + return; } - catch(ex) { - VestaxVCI400.printError(ex); - } + var playing = engine.getValue(group, "play"); + if (playing && VestaxVCI400.shiftActive) { + script.brake(channel, control, value, status, group, 100.0); + return; + } + + script.toggleControl(group, "play"); +}; + +// The censor button usually does a reverse roll, but if shift is held +// we do a backspin stop. +VestaxVCI400.censorButton = function (channel, control, value, status, group) { + var playing = engine.getValue(group, "play"); + if (playing && VestaxVCI400.shiftActive && value !== 0) { + script.spinback(channel, control, value, status, group, 30.0, -10.0); + return; + } + + engine.setValue(group, "reverseroll", value); }; VestaxVCI400.vinylButton = function (channel, control, value, status, group) { diff --git a/res/controllers/common-controller-scripts.js b/res/controllers/common-controller-scripts.js index f52940ef9b44..687f422b1462 100644 --- a/res/controllers/common-controller-scripts.js +++ b/res/controllers/common-controller-scripts.js @@ -326,9 +326,8 @@ script.midiPitch = function (LSB, MSB, status) { -------- ------------------------------------------------------ */ script.spinback = function(channel, control, value, status, group, factor, rate) { // if brake is called without defined factor and rate, reset to defaults - if (factor === undefined && rate === undefined) { + if (factor === undefined) { factor = 1; - rate = -10; } // if brake is called without defined rate, reset to default if (rate === undefined) { diff --git a/res/controllers/lodash.mixxx.js b/res/controllers/lodash.mixxx.js deleted file mode 100644 index 2fd971121480..000000000000 --- a/res/controllers/lodash.mixxx.js +++ /dev/null @@ -1,2242 +0,0 @@ -/** - * @license - * Lodash (Custom Build) - * Build: `lodash strict exports="global" include="assign,merge"` - * Copyright JS Foundation and other contributors - * Released under MIT license - * Based on Underscore.js 1.8.3 - * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - */ -;(function() { - 'use strict'; - - /** Used as a safe reference for `undefined` in pre-ES5 environments. */ - var undefined; - - /** Used as the semantic version number. */ - var VERSION = '4.17.1'; - - /** Used as the size to enable large array optimizations. */ - var LARGE_ARRAY_SIZE = 200; - - /** Used to stand-in for `undefined` hash values. */ - var HASH_UNDEFINED = '__lodash_hash_undefined__'; - - /** Used to detect hot functions by number of calls within a span of milliseconds. */ - var HOT_COUNT = 800, - HOT_SPAN = 16; - - /** Used as references for various `Number` constants. */ - var MAX_SAFE_INTEGER = 9007199254740991; - - /** `Object#toString` result references. */ - var argsTag = '[object Arguments]', - arrayTag = '[object Array]', - asyncTag = '[object AsyncFunction]', - boolTag = '[object Boolean]', - dateTag = '[object Date]', - errorTag = '[object Error]', - funcTag = '[object Function]', - genTag = '[object GeneratorFunction]', - mapTag = '[object Map]', - numberTag = '[object Number]', - nullTag = '[object Null]', - objectTag = '[object Object]', - proxyTag = '[object Proxy]', - regexpTag = '[object RegExp]', - setTag = '[object Set]', - stringTag = '[object String]', - undefinedTag = '[object Undefined]', - weakMapTag = '[object WeakMap]'; - - var arrayBufferTag = '[object ArrayBuffer]', - dataViewTag = '[object DataView]', - float32Tag = '[object Float32Array]', - float64Tag = '[object Float64Array]', - int8Tag = '[object Int8Array]', - int16Tag = '[object Int16Array]', - int32Tag = '[object Int32Array]', - uint8Tag = '[object Uint8Array]', - uint8ClampedTag = '[object Uint8ClampedArray]', - uint16Tag = '[object Uint16Array]', - uint32Tag = '[object Uint32Array]'; - - /** - * Used to match `RegExp` - * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). - */ - var reRegExpChar = /[\\^$.*+?()[\]{}|]/g; - - /** Used to detect host constructors (Safari). */ - var reIsHostCtor = /^\[object .+?Constructor\]$/; - - /** Used to detect unsigned integer values. */ - var reIsUint = /^(?:0|[1-9]\d*)$/; - - /** Used to identify `toStringTag` values of typed arrays. */ - var typedArrayTags = {}; - typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = - typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = - typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = - typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = - typedArrayTags[uint32Tag] = true; - typedArrayTags[argsTag] = typedArrayTags[arrayTag] = - typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = - typedArrayTags[dataViewTag] = typedArrayTags[dateTag] = - typedArrayTags[errorTag] = typedArrayTags[funcTag] = - typedArrayTags[mapTag] = typedArrayTags[numberTag] = - typedArrayTags[objectTag] = typedArrayTags[regexpTag] = - typedArrayTags[setTag] = typedArrayTags[stringTag] = - typedArrayTags[weakMapTag] = false; - - /** Detect free variable `global` from Node.js. */ - var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; - - /** Detect free variable `self`. */ - var freeSelf = typeof self == 'object' && self && self.Object === Object && self; - - /** Used as a reference to the global object. */ - var root = freeGlobal || freeSelf || Function('return this')(); - - /** Detect free variable `exports`. */ - var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports; - - /** Detect free variable `module`. */ - var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module; - - /** Detect the popular CommonJS extension `module.exports`. */ - var moduleExports = freeModule && freeModule.exports === freeExports; - - /** Detect free variable `process` from Node.js. */ - var freeProcess = moduleExports && freeGlobal.process; - - /** Used to access faster Node.js helpers. */ - var nodeUtil = (function() { - try { - return freeProcess && freeProcess.binding && freeProcess.binding('util'); - } catch (e) {} - }()); - - /* Node.js helper references. */ - var nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray; - - /*--------------------------------------------------------------------------*/ - - /** - * A faster alternative to `Function#apply`, this function invokes `func` - * with the `this` binding of `thisArg` and the arguments of `args`. - * - * @private - * @param {Function} func The function to invoke. - * @param {*} thisArg The `this` binding of `func`. - * @param {Array} args The arguments to invoke `func` with. - * @returns {*} Returns the result of `func`. - */ - function apply(func, thisArg, args) { - switch (args.length) { - case 0: return func.call(thisArg); - case 1: return func.call(thisArg, args[0]); - case 2: return func.call(thisArg, args[0], args[1]); - case 3: return func.call(thisArg, args[0], args[1], args[2]); - } - return func.apply(thisArg, args); - } - - /** - * The base implementation of `_.times` without support for iteratee shorthands - * or max array length checks. - * - * @private - * @param {number} n The number of times to invoke `iteratee`. - * @param {Function} iteratee The function invoked per iteration. - * @returns {Array} Returns the array of results. - */ - function baseTimes(n, iteratee) { - var index = -1, - result = Array(n); - - while (++index < n) { - result[index] = iteratee(index); - } - return result; - } - - /** - * The base implementation of `_.unary` without support for storing metadata. - * - * @private - * @param {Function} func The function to cap arguments for. - * @returns {Function} Returns the new capped function. - */ - function baseUnary(func) { - return function(value) { - return func(value); - }; - } - - /** - * Gets the value at `key` of `object`. - * - * @private - * @param {Object} [object] The object to query. - * @param {string} key The key of the property to get. - * @returns {*} Returns the property value. - */ - function getValue(object, key) { - return object == null ? undefined : object[key]; - } - - /** - * Creates a unary function that invokes `func` with its argument transformed. - * - * @private - * @param {Function} func The function to wrap. - * @param {Function} transform The argument transform. - * @returns {Function} Returns the new function. - */ - function overArg(func, transform) { - return function(arg) { - return func(transform(arg)); - }; - } - - /*--------------------------------------------------------------------------*/ - - /** Used for built-in method references. */ - var arrayProto = Array.prototype, - funcProto = Function.prototype, - objectProto = Object.prototype; - - /** Used to detect overreaching core-js shims. */ - var coreJsData = root['__core-js_shared__']; - - /** Used to resolve the decompiled source of functions. */ - var funcToString = funcProto.toString; - - /** Used to check objects for own properties. */ - var hasOwnProperty = objectProto.hasOwnProperty; - - /** Used to detect methods masquerading as native. */ - var maskSrcKey = (function() { - var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || ''); - return uid ? ('Symbol(src)_1.' + uid) : ''; - }()); - - /** - * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) - * of values. - */ - var nativeObjectToString = objectProto.toString; - - /** Used to infer the `Object` constructor. */ - var objectCtorString = funcToString.call(Object); - - /** Used to detect if a method is native. */ - var reIsNative = RegExp('^' + - funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&') - .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' - ); - - /** Built-in value references. */ - var Buffer = moduleExports ? root.Buffer : undefined, - Symbol = root.Symbol, - Uint8Array = root.Uint8Array, - allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined, - getPrototype = overArg(Object.getPrototypeOf, Object), - objectCreate = Object.create, - propertyIsEnumerable = objectProto.propertyIsEnumerable, - splice = arrayProto.splice, - symToStringTag = Symbol ? Symbol.toStringTag : undefined; - - var defineProperty = (function() { - try { - var func = getNative(Object, 'defineProperty'); - func({}, '', {}); - return func; - } catch (e) {} - }()); - - /* Built-in method references for those with the same name as other `lodash` methods. */ - var nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined, - nativeKeys = overArg(Object.keys, Object), - nativeMax = Math.max, - nativeNow = Date.now; - - /* Built-in method references that are verified to be native. */ - var Map = getNative(root, 'Map'), - nativeCreate = getNative(Object, 'create'); - - /** Used to lookup unminified function names. */ - var realNames = {}; - - /*------------------------------------------------------------------------*/ - - /** - * Creates a `lodash` object which wraps `value` to enable implicit method - * chain sequences. Methods that operate on and return arrays, collections, - * and functions can be chained together. Methods that retrieve a single value - * or may return a primitive value will automatically end the chain sequence - * and return the unwrapped value. Otherwise, the value must be unwrapped - * with `_#value`. - * - * Explicit chain sequences, which must be unwrapped with `_#value`, may be - * enabled using `_.chain`. - * - * The execution of chained methods is lazy, that is, it's deferred until - * `_#value` is implicitly or explicitly called. - * - * Lazy evaluation allows several methods to support shortcut fusion. - * Shortcut fusion is an optimization to merge iteratee calls; this avoids - * the creation of intermediate arrays and can greatly reduce the number of - * iteratee executions. Sections of a chain sequence qualify for shortcut - * fusion if the section is applied to an array of at least `200` elements - * and any iteratees accept only one argument. The heuristic for whether a - * section qualifies for shortcut fusion is subject to change. - * - * Chaining is supported in custom builds as long as the `_#value` method is - * directly or indirectly included in the build. - * - * In addition to lodash methods, wrappers have `Array` and `String` methods. - * - * The wrapper `Array` methods are: - * `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift` - * - * The wrapper `String` methods are: - * `replace` and `split` - * - * The wrapper methods that support shortcut fusion are: - * `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`, - * `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`, - * `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray` - * - * The chainable wrapper methods are: - * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`, - * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`, - * `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`, - * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`, - * `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`, - * `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`, - * `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`, - * `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`, - * `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`, - * `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`, - * `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`, - * `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`, - * `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`, - * `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`, - * `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`, - * `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`, - * `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`, - * `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`, - * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`, - * `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`, - * `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`, - * `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`, - * `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`, - * `zipObject`, `zipObjectDeep`, and `zipWith` - * - * The wrapper methods that are **not** chainable by default are: - * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`, - * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `conformsTo`, `deburr`, - * `defaultTo`, `divide`, `each`, `eachRight`, `endsWith`, `eq`, `escape`, - * `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`, - * `findLastIndex`, `findLastKey`, `first`, `floor`, `forEach`, `forEachRight`, - * `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`, - * `hasIn`, `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`, - * `isArguments`, `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`, - * `isBoolean`, `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`, - * `isEqualWith`, `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`, - * `isMap`, `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`, - * `isNumber`, `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`, - * `isSafeInteger`, `isSet`, `isString`, `isUndefined`, `isTypedArray`, - * `isWeakMap`, `isWeakSet`, `join`, `kebabCase`, `last`, `lastIndexOf`, - * `lowerCase`, `lowerFirst`, `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`, - * `min`, `minBy`, `multiply`, `noConflict`, `noop`, `now`, `nth`, `pad`, - * `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`, - * `repeat`, `result`, `round`, `runInContext`, `sample`, `shift`, `size`, - * `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`, `sortedLastIndex`, - * `sortedLastIndexBy`, `startCase`, `startsWith`, `stubArray`, `stubFalse`, - * `stubObject`, `stubString`, `stubTrue`, `subtract`, `sum`, `sumBy`, - * `template`, `times`, `toFinite`, `toInteger`, `toJSON`, `toLength`, - * `toLower`, `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`, - * `trimEnd`, `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`, - * `upperFirst`, `value`, and `words` - * - * @name _ - * @constructor - * @category Seq - * @param {*} value The value to wrap in a `lodash` instance. - * @returns {Object} Returns the new `lodash` wrapper instance. - * @example - * - * function square(n) { - * return n * n; - * } - * - * var wrapped = _([1, 2, 3]); - * - * // Returns an unwrapped value. - * wrapped.reduce(_.add); - * // => 6 - * - * // Returns a wrapped value. - * var squares = wrapped.map(square); - * - * _.isArray(squares); - * // => false - * - * _.isArray(squares.value()); - * // => true - */ - function lodash() { - // No operation performed. - } - - /** - * The base implementation of `_.create` without support for assigning - * properties to the created object. - * - * @private - * @param {Object} proto The object to inherit from. - * @returns {Object} Returns the new object. - */ - var baseCreate = (function() { - function object() {} - return function(proto) { - if (!isObject(proto)) { - return {}; - } - if (objectCreate) { - return objectCreate(proto); - } - object.prototype = proto; - var result = new object; - object.prototype = undefined; - return result; - }; - }()); - - /*------------------------------------------------------------------------*/ - - /** - * Creates a hash object. - * - * @private - * @constructor - * @param {Array} [entries] The key-value pairs to cache. - */ - function Hash(entries) { - var index = -1, - length = entries == null ? 0 : entries.length; - - this.clear(); - while (++index < length) { - var entry = entries[index]; - this.set(entry[0], entry[1]); - } - } - - /** - * Removes all key-value entries from the hash. - * - * @private - * @name clear - * @memberOf Hash - */ - function hashClear() { - this.__data__ = nativeCreate ? nativeCreate(null) : {}; - this.size = 0; - } - - /** - * Removes `key` and its value from the hash. - * - * @private - * @name delete - * @memberOf Hash - * @param {Object} hash The hash to modify. - * @param {string} key The key of the value to remove. - * @returns {boolean} Returns `true` if the entry was removed, else `false`. - */ - function hashDelete(key) { - var result = this.has(key) && delete this.__data__[key]; - this.size -= result ? 1 : 0; - return result; - } - - /** - * Gets the hash value for `key`. - * - * @private - * @name get - * @memberOf Hash - * @param {string} key The key of the value to get. - * @returns {*} Returns the entry value. - */ - function hashGet(key) { - var data = this.__data__; - if (nativeCreate) { - var result = data[key]; - return result === HASH_UNDEFINED ? undefined : result; - } - return hasOwnProperty.call(data, key) ? data[key] : undefined; - } - - /** - * Checks if a hash value for `key` exists. - * - * @private - * @name has - * @memberOf Hash - * @param {string} key The key of the entry to check. - * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. - */ - function hashHas(key) { - var data = this.__data__; - return nativeCreate ? data[key] !== undefined : hasOwnProperty.call(data, key); - } - - /** - * Sets the hash `key` to `value`. - * - * @private - * @name set - * @memberOf Hash - * @param {string} key The key of the value to set. - * @param {*} value The value to set. - * @returns {Object} Returns the hash instance. - */ - function hashSet(key, value) { - var data = this.__data__; - this.size += this.has(key) ? 0 : 1; - data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value; - return this; - } - - // Add methods to `Hash`. - Hash.prototype.clear = hashClear; - Hash.prototype['delete'] = hashDelete; - Hash.prototype.get = hashGet; - Hash.prototype.has = hashHas; - Hash.prototype.set = hashSet; - - /*------------------------------------------------------------------------*/ - - /** - * Creates an list cache object. - * - * @private - * @constructor - * @param {Array} [entries] The key-value pairs to cache. - */ - function ListCache(entries) { - var index = -1, - length = entries == null ? 0 : entries.length; - - this.clear(); - while (++index < length) { - var entry = entries[index]; - this.set(entry[0], entry[1]); - } - } - - /** - * Removes all key-value entries from the list cache. - * - * @private - * @name clear - * @memberOf ListCache - */ - function listCacheClear() { - this.__data__ = []; - this.size = 0; - } - - /** - * Removes `key` and its value from the list cache. - * - * @private - * @name delete - * @memberOf ListCache - * @param {string} key The key of the value to remove. - * @returns {boolean} Returns `true` if the entry was removed, else `false`. - */ - function listCacheDelete(key) { - var data = this.__data__, - index = assocIndexOf(data, key); - - if (index < 0) { - return false; - } - var lastIndex = data.length - 1; - if (index == lastIndex) { - data.pop(); - } else { - splice.call(data, index, 1); - } - --this.size; - return true; - } - - /** - * Gets the list cache value for `key`. - * - * @private - * @name get - * @memberOf ListCache - * @param {string} key The key of the value to get. - * @returns {*} Returns the entry value. - */ - function listCacheGet(key) { - var data = this.__data__, - index = assocIndexOf(data, key); - - return index < 0 ? undefined : data[index][1]; - } - - /** - * Checks if a list cache value for `key` exists. - * - * @private - * @name has - * @memberOf ListCache - * @param {string} key The key of the entry to check. - * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. - */ - function listCacheHas(key) { - return assocIndexOf(this.__data__, key) > -1; - } - - /** - * Sets the list cache `key` to `value`. - * - * @private - * @name set - * @memberOf ListCache - * @param {string} key The key of the value to set. - * @param {*} value The value to set. - * @returns {Object} Returns the list cache instance. - */ - function listCacheSet(key, value) { - var data = this.__data__, - index = assocIndexOf(data, key); - - if (index < 0) { - ++this.size; - data.push([key, value]); - } else { - data[index][1] = value; - } - return this; - } - - // Add methods to `ListCache`. - ListCache.prototype.clear = listCacheClear; - ListCache.prototype['delete'] = listCacheDelete; - ListCache.prototype.get = listCacheGet; - ListCache.prototype.has = listCacheHas; - ListCache.prototype.set = listCacheSet; - - /*------------------------------------------------------------------------*/ - - /** - * Creates a map cache object to store key-value pairs. - * - * @private - * @constructor - * @param {Array} [entries] The key-value pairs to cache. - */ - function MapCache(entries) { - var index = -1, - length = entries == null ? 0 : entries.length; - - this.clear(); - while (++index < length) { - var entry = entries[index]; - this.set(entry[0], entry[1]); - } - } - - /** - * Removes all key-value entries from the map. - * - * @private - * @name clear - * @memberOf MapCache - */ - function mapCacheClear() { - this.size = 0; - this.__data__ = { - 'hash': new Hash, - 'map': new (Map || ListCache), - 'string': new Hash - }; - } - - /** - * Removes `key` and its value from the map. - * - * @private - * @name delete - * @memberOf MapCache - * @param {string} key The key of the value to remove. - * @returns {boolean} Returns `true` if the entry was removed, else `false`. - */ - function mapCacheDelete(key) { - var result = getMapData(this, key)['delete'](key); - this.size -= result ? 1 : 0; - return result; - } - - /** - * Gets the map value for `key`. - * - * @private - * @name get - * @memberOf MapCache - * @param {string} key The key of the value to get. - * @returns {*} Returns the entry value. - */ - function mapCacheGet(key) { - return getMapData(this, key).get(key); - } - - /** - * Checks if a map value for `key` exists. - * - * @private - * @name has - * @memberOf MapCache - * @param {string} key The key of the entry to check. - * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. - */ - function mapCacheHas(key) { - return getMapData(this, key).has(key); - } - - /** - * Sets the map `key` to `value`. - * - * @private - * @name set - * @memberOf MapCache - * @param {string} key The key of the value to set. - * @param {*} value The value to set. - * @returns {Object} Returns the map cache instance. - */ - function mapCacheSet(key, value) { - var data = getMapData(this, key), - size = data.size; - - data.set(key, value); - this.size += data.size == size ? 0 : 1; - return this; - } - - // Add methods to `MapCache`. - MapCache.prototype.clear = mapCacheClear; - MapCache.prototype['delete'] = mapCacheDelete; - MapCache.prototype.get = mapCacheGet; - MapCache.prototype.has = mapCacheHas; - MapCache.prototype.set = mapCacheSet; - - /*------------------------------------------------------------------------*/ - - /** - * Creates a stack cache object to store key-value pairs. - * - * @private - * @constructor - * @param {Array} [entries] The key-value pairs to cache. - */ - function Stack(entries) { - var data = this.__data__ = new ListCache(entries); - this.size = data.size; - } - - /** - * Removes all key-value entries from the stack. - * - * @private - * @name clear - * @memberOf Stack - */ - function stackClear() { - this.__data__ = new ListCache; - this.size = 0; - } - - /** - * Removes `key` and its value from the stack. - * - * @private - * @name delete - * @memberOf Stack - * @param {string} key The key of the value to remove. - * @returns {boolean} Returns `true` if the entry was removed, else `false`. - */ - function stackDelete(key) { - var data = this.__data__, - result = data['delete'](key); - - this.size = data.size; - return result; - } - - /** - * Gets the stack value for `key`. - * - * @private - * @name get - * @memberOf Stack - * @param {string} key The key of the value to get. - * @returns {*} Returns the entry value. - */ - function stackGet(key) { - return this.__data__.get(key); - } - - /** - * Checks if a stack value for `key` exists. - * - * @private - * @name has - * @memberOf Stack - * @param {string} key The key of the entry to check. - * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. - */ - function stackHas(key) { - return this.__data__.has(key); - } - - /** - * Sets the stack `key` to `value`. - * - * @private - * @name set - * @memberOf Stack - * @param {string} key The key of the value to set. - * @param {*} value The value to set. - * @returns {Object} Returns the stack cache instance. - */ - function stackSet(key, value) { - var data = this.__data__; - if (data instanceof ListCache) { - var pairs = data.__data__; - if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) { - pairs.push([key, value]); - this.size = ++data.size; - return this; - } - data = this.__data__ = new MapCache(pairs); - } - data.set(key, value); - this.size = data.size; - return this; - } - - // Add methods to `Stack`. - Stack.prototype.clear = stackClear; - Stack.prototype['delete'] = stackDelete; - Stack.prototype.get = stackGet; - Stack.prototype.has = stackHas; - Stack.prototype.set = stackSet; - - /*------------------------------------------------------------------------*/ - - /** - * Creates an array of the enumerable property names of the array-like `value`. - * - * @private - * @param {*} value The value to query. - * @param {boolean} inherited Specify returning inherited property names. - * @returns {Array} Returns the array of property names. - */ - function arrayLikeKeys(value, inherited) { - var isArr = isArray(value), - isArg = !isArr && isArguments(value), - isBuff = !isArr && !isArg && isBuffer(value), - isType = !isArr && !isArg && !isBuff && isTypedArray(value), - skipIndexes = isArr || isArg || isBuff || isType, - result = skipIndexes ? baseTimes(value.length, String) : [], - length = result.length; - - for (var key in value) { - if ((inherited || hasOwnProperty.call(value, key)) && - !(skipIndexes && ( - // Safari 9 has enumerable `arguments.length` in strict mode. - key == 'length' || - // Node.js 0.10 has enumerable non-index properties on buffers. - (isBuff && (key == 'offset' || key == 'parent')) || - // PhantomJS 2 has enumerable non-index properties on typed arrays. - (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) || - // Skip index properties. - isIndex(key, length) - ))) { - result.push(key); - } - } - return result; - } - - /** - * This function is like `assignValue` except that it doesn't assign - * `undefined` values. - * - * @private - * @param {Object} object The object to modify. - * @param {string} key The key of the property to assign. - * @param {*} value The value to assign. - */ - function assignMergeValue(object, key, value) { - if ((value !== undefined && !eq(object[key], value)) || - (value === undefined && !(key in object))) { - baseAssignValue(object, key, value); - } - } - - /** - * Assigns `value` to `key` of `object` if the existing value is not equivalent - * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) - * for equality comparisons. - * - * @private - * @param {Object} object The object to modify. - * @param {string} key The key of the property to assign. - * @param {*} value The value to assign. - */ - function assignValue(object, key, value) { - var objValue = object[key]; - if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) || - (value === undefined && !(key in object))) { - baseAssignValue(object, key, value); - } - } - - /** - * Gets the index at which the `key` is found in `array` of key-value pairs. - * - * @private - * @param {Array} array The array to inspect. - * @param {*} key The key to search for. - * @returns {number} Returns the index of the matched value, else `-1`. - */ - function assocIndexOf(array, key) { - var length = array.length; - while (length--) { - if (eq(array[length][0], key)) { - return length; - } - } - return -1; - } - - /** - * The base implementation of `assignValue` and `assignMergeValue` without - * value checks. - * - * @private - * @param {Object} object The object to modify. - * @param {string} key The key of the property to assign. - * @param {*} value The value to assign. - */ - function baseAssignValue(object, key, value) { - if (key == '__proto__' && defineProperty) { - defineProperty(object, key, { - 'configurable': true, - 'enumerable': true, - 'value': value, - 'writable': true - }); - } else { - object[key] = value; - } - } - - /** - * The base implementation of `baseForOwn` which iterates over `object` - * properties returned by `keysFunc` and invokes `iteratee` for each property. - * Iteratee functions may exit iteration early by explicitly returning `false`. - * - * @private - * @param {Object} object The object to iterate over. - * @param {Function} iteratee The function invoked per iteration. - * @param {Function} keysFunc The function to get the keys of `object`. - * @returns {Object} Returns `object`. - */ - var baseFor = createBaseFor(); - - /** - * The base implementation of `getTag` without fallbacks for buggy environments. - * - * @private - * @param {*} value The value to query. - * @returns {string} Returns the `toStringTag`. - */ - function baseGetTag(value) { - if (value == null) { - return value === undefined ? undefinedTag : nullTag; - } - value = Object(value); - return (symToStringTag && symToStringTag in value) - ? getRawTag(value) - : objectToString(value); - } - - /** - * The base implementation of `_.isArguments`. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an `arguments` object, - */ - function baseIsArguments(value) { - return isObjectLike(value) && baseGetTag(value) == argsTag; - } - - /** - * The base implementation of `_.isNative` without bad shim checks. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a native function, - * else `false`. - */ - function baseIsNative(value) { - if (!isObject(value) || isMasked(value)) { - return false; - } - var pattern = isFunction(value) ? reIsNative : reIsHostCtor; - return pattern.test(toSource(value)); - } - - /** - * The base implementation of `_.isTypedArray` without Node.js optimizations. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. - */ - function baseIsTypedArray(value) { - return isObjectLike(value) && - isLength(value.length) && !!typedArrayTags[baseGetTag(value)]; - } - - /** - * The base implementation of `_.keys` which doesn't treat sparse arrays as dense. - * - * @private - * @param {Object} object The object to query. - * @returns {Array} Returns the array of property names. - */ - function baseKeys(object) { - if (!isPrototype(object)) { - return nativeKeys(object); - } - var result = []; - for (var key in Object(object)) { - if (hasOwnProperty.call(object, key) && key != 'constructor') { - result.push(key); - } - } - return result; - } - - /** - * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense. - * - * @private - * @param {Object} object The object to query. - * @returns {Array} Returns the array of property names. - */ - function baseKeysIn(object) { - if (!isObject(object)) { - return nativeKeysIn(object); - } - var isProto = isPrototype(object), - result = []; - - for (var key in object) { - if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) { - result.push(key); - } - } - return result; - } - - /** - * The base implementation of `_.merge` without support for multiple sources. - * - * @private - * @param {Object} object The destination object. - * @param {Object} source The source object. - * @param {number} srcIndex The index of `source`. - * @param {Function} [customizer] The function to customize merged values. - * @param {Object} [stack] Tracks traversed source values and their merged - * counterparts. - */ - function baseMerge(object, source, srcIndex, customizer, stack) { - if (object === source) { - return; - } - baseFor(source, function(srcValue, key) { - if (isObject(srcValue)) { - stack || (stack = new Stack); - baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack); - } - else { - var newValue = customizer - ? customizer(object[key], srcValue, (key + ''), object, source, stack) - : undefined; - - if (newValue === undefined) { - newValue = srcValue; - } - assignMergeValue(object, key, newValue); - } - }, keysIn); - } - - /** - * A specialized version of `baseMerge` for arrays and objects which performs - * deep merges and tracks traversed objects enabling objects with circular - * references to be merged. - * - * @private - * @param {Object} object The destination object. - * @param {Object} source The source object. - * @param {string} key The key of the value to merge. - * @param {number} srcIndex The index of `source`. - * @param {Function} mergeFunc The function to merge values. - * @param {Function} [customizer] The function to customize assigned values. - * @param {Object} [stack] Tracks traversed source values and their merged - * counterparts. - */ - function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) { - var objValue = object[key], - srcValue = source[key], - stacked = stack.get(srcValue); - - if (stacked) { - assignMergeValue(object, key, stacked); - return; - } - var newValue = customizer - ? customizer(objValue, srcValue, (key + ''), object, source, stack) - : undefined; - - var isCommon = newValue === undefined; - - if (isCommon) { - var isArr = isArray(srcValue), - isBuff = !isArr && isBuffer(srcValue), - isTyped = !isArr && !isBuff && isTypedArray(srcValue); - - newValue = srcValue; - if (isArr || isBuff || isTyped) { - if (isArray(objValue)) { - newValue = objValue; - } - else if (isArrayLikeObject(objValue)) { - newValue = copyArray(objValue); - } - else if (isBuff) { - isCommon = false; - newValue = cloneBuffer(srcValue, true); - } - else if (isTyped) { - isCommon = false; - newValue = cloneTypedArray(srcValue, true); - } - else { - newValue = []; - } - } - else if (isPlainObject(srcValue) || isArguments(srcValue)) { - newValue = objValue; - if (isArguments(objValue)) { - newValue = toPlainObject(objValue); - } - else if (!isObject(objValue) || (srcIndex && isFunction(objValue))) { - newValue = initCloneObject(srcValue); - } - } - else { - isCommon = false; - } - } - if (isCommon) { - // Recursively merge objects and arrays (susceptible to call stack limits). - stack.set(srcValue, newValue); - mergeFunc(newValue, srcValue, srcIndex, customizer, stack); - stack['delete'](srcValue); - } - assignMergeValue(object, key, newValue); - } - - /** - * The base implementation of `_.rest` which doesn't validate or coerce arguments. - * - * @private - * @param {Function} func The function to apply a rest parameter to. - * @param {number} [start=func.length-1] The start position of the rest parameter. - * @returns {Function} Returns the new function. - */ - function baseRest(func, start) { - return setToString(overRest(func, start, identity), func + ''); - } - - /** - * The base implementation of `setToString` without support for hot loop shorting. - * - * @private - * @param {Function} func The function to modify. - * @param {Function} string The `toString` result. - * @returns {Function} Returns `func`. - */ - var baseSetToString = !defineProperty ? identity : function(func, string) { - return defineProperty(func, 'toString', { - 'configurable': true, - 'enumerable': false, - 'value': constant(string), - 'writable': true - }); - }; - - /** - * Creates a clone of `buffer`. - * - * @private - * @param {Buffer} buffer The buffer to clone. - * @param {boolean} [isDeep] Specify a deep clone. - * @returns {Buffer} Returns the cloned buffer. - */ - function cloneBuffer(buffer, isDeep) { - if (isDeep) { - return buffer.slice(); - } - var length = buffer.length, - result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length); - - buffer.copy(result); - return result; - } - - /** - * Creates a clone of `arrayBuffer`. - * - * @private - * @param {ArrayBuffer} arrayBuffer The array buffer to clone. - * @returns {ArrayBuffer} Returns the cloned array buffer. - */ - function cloneArrayBuffer(arrayBuffer) { - var result = new arrayBuffer.constructor(arrayBuffer.byteLength); - new Uint8Array(result).set(new Uint8Array(arrayBuffer)); - return result; - } - - /** - * Creates a clone of `typedArray`. - * - * @private - * @param {Object} typedArray The typed array to clone. - * @param {boolean} [isDeep] Specify a deep clone. - * @returns {Object} Returns the cloned typed array. - */ - function cloneTypedArray(typedArray, isDeep) { - var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer; - return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length); - } - - /** - * Copies the values of `source` to `array`. - * - * @private - * @param {Array} source The array to copy values from. - * @param {Array} [array=[]] The array to copy values to. - * @returns {Array} Returns `array`. - */ - function copyArray(source, array) { - var index = -1, - length = source.length; - - array || (array = Array(length)); - while (++index < length) { - array[index] = source[index]; - } - return array; - } - - /** - * Copies properties of `source` to `object`. - * - * @private - * @param {Object} source The object to copy properties from. - * @param {Array} props The property identifiers to copy. - * @param {Object} [object={}] The object to copy properties to. - * @param {Function} [customizer] The function to customize copied values. - * @returns {Object} Returns `object`. - */ - function copyObject(source, props, object, customizer) { - var isNew = !object; - object || (object = {}); - - var index = -1, - length = props.length; - - while (++index < length) { - var key = props[index]; - - var newValue = customizer - ? customizer(object[key], source[key], key, object, source) - : undefined; - - if (newValue === undefined) { - newValue = source[key]; - } - if (isNew) { - baseAssignValue(object, key, newValue); - } else { - assignValue(object, key, newValue); - } - } - return object; - } - - /** - * Creates a function like `_.assign`. - * - * @private - * @param {Function} assigner The function to assign values. - * @returns {Function} Returns the new assigner function. - */ - function createAssigner(assigner) { - return baseRest(function(object, sources) { - var index = -1, - length = sources.length, - customizer = length > 1 ? sources[length - 1] : undefined, - guard = length > 2 ? sources[2] : undefined; - - customizer = (assigner.length > 3 && typeof customizer == 'function') - ? (length--, customizer) - : undefined; - - if (guard && isIterateeCall(sources[0], sources[1], guard)) { - customizer = length < 3 ? undefined : customizer; - length = 1; - } - object = Object(object); - while (++index < length) { - var source = sources[index]; - if (source) { - assigner(object, source, index, customizer); - } - } - return object; - }); - } - - /** - * Creates a base function for methods like `_.forIn` and `_.forOwn`. - * - * @private - * @param {boolean} [fromRight] Specify iterating from right to left. - * @returns {Function} Returns the new base function. - */ - function createBaseFor(fromRight) { - return function(object, iteratee, keysFunc) { - var index = -1, - iterable = Object(object), - props = keysFunc(object), - length = props.length; - - while (length--) { - var key = props[fromRight ? length : ++index]; - if (iteratee(iterable[key], key, iterable) === false) { - break; - } - } - return object; - }; - } - - /** - * Gets the data for `map`. - * - * @private - * @param {Object} map The map to query. - * @param {string} key The reference key. - * @returns {*} Returns the map data. - */ - function getMapData(map, key) { - var data = map.__data__; - return isKeyable(key) - ? data[typeof key == 'string' ? 'string' : 'hash'] - : data.map; - } - - /** - * Gets the native function at `key` of `object`. - * - * @private - * @param {Object} object The object to query. - * @param {string} key The key of the method to get. - * @returns {*} Returns the function if it's native, else `undefined`. - */ - function getNative(object, key) { - var value = getValue(object, key); - return baseIsNative(value) ? value : undefined; - } - - /** - * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values. - * - * @private - * @param {*} value The value to query. - * @returns {string} Returns the raw `toStringTag`. - */ - function getRawTag(value) { - var isOwn = hasOwnProperty.call(value, symToStringTag), - tag = value[symToStringTag]; - - try { - value[symToStringTag] = undefined; - var unmasked = true; - } catch (e) {} - - var result = nativeObjectToString.call(value); - if (unmasked) { - if (isOwn) { - value[symToStringTag] = tag; - } else { - delete value[symToStringTag]; - } - } - return result; - } - - /** - * Initializes an object clone. - * - * @private - * @param {Object} object The object to clone. - * @returns {Object} Returns the initialized clone. - */ - function initCloneObject(object) { - return (typeof object.constructor == 'function' && !isPrototype(object)) - ? baseCreate(getPrototype(object)) - : {}; - } - - /** - * Checks if `value` is a valid array-like index. - * - * @private - * @param {*} value The value to check. - * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. - * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. - */ - function isIndex(value, length) { - length = length == null ? MAX_SAFE_INTEGER : length; - return !!length && - (typeof value == 'number' || reIsUint.test(value)) && - (value > -1 && value % 1 == 0 && value < length); - } - - /** - * Checks if the given arguments are from an iteratee call. - * - * @private - * @param {*} value The potential iteratee value argument. - * @param {*} index The potential iteratee index or key argument. - * @param {*} object The potential iteratee object argument. - * @returns {boolean} Returns `true` if the arguments are from an iteratee call, - * else `false`. - */ - function isIterateeCall(value, index, object) { - if (!isObject(object)) { - return false; - } - var type = typeof index; - if (type == 'number' - ? (isArrayLike(object) && isIndex(index, object.length)) - : (type == 'string' && index in object) - ) { - return eq(object[index], value); - } - return false; - } - - /** - * Checks if `value` is suitable for use as unique object key. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is suitable, else `false`. - */ - function isKeyable(value) { - var type = typeof value; - return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean') - ? (value !== '__proto__') - : (value === null); - } - - /** - * Checks if `func` has its source masked. - * - * @private - * @param {Function} func The function to check. - * @returns {boolean} Returns `true` if `func` is masked, else `false`. - */ - function isMasked(func) { - return !!maskSrcKey && (maskSrcKey in func); - } - - /** - * Checks if `value` is likely a prototype object. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a prototype, else `false`. - */ - function isPrototype(value) { - var Ctor = value && value.constructor, - proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto; - - return value === proto; - } - - /** - * This function is like - * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) - * except that it includes inherited enumerable properties. - * - * @private - * @param {Object} object The object to query. - * @returns {Array} Returns the array of property names. - */ - function nativeKeysIn(object) { - var result = []; - if (object != null) { - for (var key in Object(object)) { - result.push(key); - } - } - return result; - } - - /** - * Converts `value` to a string using `Object.prototype.toString`. - * - * @private - * @param {*} value The value to convert. - * @returns {string} Returns the converted string. - */ - function objectToString(value) { - return nativeObjectToString.call(value); - } - - /** - * A specialized version of `baseRest` which transforms the rest array. - * - * @private - * @param {Function} func The function to apply a rest parameter to. - * @param {number} [start=func.length-1] The start position of the rest parameter. - * @param {Function} transform The rest array transform. - * @returns {Function} Returns the new function. - */ - function overRest(func, start, transform) { - start = nativeMax(start === undefined ? (func.length - 1) : start, 0); - return function() { - var args = arguments, - index = -1, - length = nativeMax(args.length - start, 0), - array = Array(length); - - while (++index < length) { - array[index] = args[start + index]; - } - index = -1; - var otherArgs = Array(start + 1); - while (++index < start) { - otherArgs[index] = args[index]; - } - otherArgs[start] = transform(array); - return apply(func, this, otherArgs); - }; - } - - /** - * Sets the `toString` method of `func` to return `string`. - * - * @private - * @param {Function} func The function to modify. - * @param {Function} string The `toString` result. - * @returns {Function} Returns `func`. - */ - var setToString = shortOut(baseSetToString); - - /** - * Creates a function that'll short out and invoke `identity` instead - * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN` - * milliseconds. - * - * @private - * @param {Function} func The function to restrict. - * @returns {Function} Returns the new shortable function. - */ - function shortOut(func) { - var count = 0, - lastCalled = 0; - - return function() { - var stamp = nativeNow(), - remaining = HOT_SPAN - (stamp - lastCalled); - - lastCalled = stamp; - if (remaining > 0) { - if (++count >= HOT_COUNT) { - return arguments[0]; - } - } else { - count = 0; - } - return func.apply(undefined, arguments); - }; - } - - /** - * Converts `func` to its source code. - * - * @private - * @param {Function} func The function to convert. - * @returns {string} Returns the source code. - */ - function toSource(func) { - if (func != null) { - try { - return funcToString.call(func); - } catch (e) {} - try { - return (func + ''); - } catch (e) {} - } - return ''; - } - - /*------------------------------------------------------------------------*/ - - /** - * Performs a - * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) - * comparison between two values to determine if they are equivalent. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to compare. - * @param {*} other The other value to compare. - * @returns {boolean} Returns `true` if the values are equivalent, else `false`. - * @example - * - * var object = { 'a': 1 }; - * var other = { 'a': 1 }; - * - * _.eq(object, object); - * // => true - * - * _.eq(object, other); - * // => false - * - * _.eq('a', 'a'); - * // => true - * - * _.eq('a', Object('a')); - * // => false - * - * _.eq(NaN, NaN); - * // => true - */ - function eq(value, other) { - return value === other || (value !== value && other !== other); - } - - /** - * Checks if `value` is likely an `arguments` object. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an `arguments` object, - * else `false`. - * @example - * - * _.isArguments(function() { return arguments; }()); - * // => true - * - * _.isArguments([1, 2, 3]); - * // => false - */ - var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) { - return isObjectLike(value) && hasOwnProperty.call(value, 'callee') && - !propertyIsEnumerable.call(value, 'callee'); - }; - - /** - * Checks if `value` is classified as an `Array` object. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an array, else `false`. - * @example - * - * _.isArray([1, 2, 3]); - * // => true - * - * _.isArray(document.body.children); - * // => false - * - * _.isArray('abc'); - * // => false - * - * _.isArray(_.noop); - * // => false - */ - var isArray = Array.isArray; - - /** - * Checks if `value` is array-like. A value is considered array-like if it's - * not a function and has a `value.length` that's an integer greater than or - * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is array-like, else `false`. - * @example - * - * _.isArrayLike([1, 2, 3]); - * // => true - * - * _.isArrayLike(document.body.children); - * // => true - * - * _.isArrayLike('abc'); - * // => true - * - * _.isArrayLike(_.noop); - * // => false - */ - function isArrayLike(value) { - return value != null && isLength(value.length) && !isFunction(value); - } - - /** - * This method is like `_.isArrayLike` except that it also checks if `value` - * is an object. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an array-like object, - * else `false`. - * @example - * - * _.isArrayLikeObject([1, 2, 3]); - * // => true - * - * _.isArrayLikeObject(document.body.children); - * // => true - * - * _.isArrayLikeObject('abc'); - * // => false - * - * _.isArrayLikeObject(_.noop); - * // => false - */ - function isArrayLikeObject(value) { - return isObjectLike(value) && isArrayLike(value); - } - - /** - * Checks if `value` is a buffer. - * - * @static - * @memberOf _ - * @since 4.3.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a buffer, else `false`. - * @example - * - * _.isBuffer(new Buffer(2)); - * // => true - * - * _.isBuffer(new Uint8Array(2)); - * // => false - */ - var isBuffer = nativeIsBuffer || stubFalse; - - /** - * Checks if `value` is classified as a `Function` object. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a function, else `false`. - * @example - * - * _.isFunction(_); - * // => true - * - * _.isFunction(/abc/); - * // => false - */ - function isFunction(value) { - if (!isObject(value)) { - return false; - } - // The use of `Object#toString` avoids issues with the `typeof` operator - // in Safari 9 which returns 'object' for typed arrays and other constructors. - var tag = baseGetTag(value); - return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag; - } - - /** - * Checks if `value` is a valid array-like length. - * - * **Note:** This method is loosely based on - * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. - * @example - * - * _.isLength(3); - * // => true - * - * _.isLength(Number.MIN_VALUE); - * // => false - * - * _.isLength(Infinity); - * // => false - * - * _.isLength('3'); - * // => false - */ - function isLength(value) { - return typeof value == 'number' && - value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; - } - - /** - * Checks if `value` is the - * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) - * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an object, else `false`. - * @example - * - * _.isObject({}); - * // => true - * - * _.isObject([1, 2, 3]); - * // => true - * - * _.isObject(_.noop); - * // => true - * - * _.isObject(null); - * // => false - */ - function isObject(value) { - var type = typeof value; - return value != null && (type == 'object' || type == 'function'); - } - - /** - * Checks if `value` is object-like. A value is object-like if it's not `null` - * and has a `typeof` result of "object". - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is object-like, else `false`. - * @example - * - * _.isObjectLike({}); - * // => true - * - * _.isObjectLike([1, 2, 3]); - * // => true - * - * _.isObjectLike(_.noop); - * // => false - * - * _.isObjectLike(null); - * // => false - */ - function isObjectLike(value) { - return value != null && typeof value == 'object'; - } - - /** - * Checks if `value` is a plain object, that is, an object created by the - * `Object` constructor or one with a `[[Prototype]]` of `null`. - * - * @static - * @memberOf _ - * @since 0.8.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. - * @example - * - * function Foo() { - * this.a = 1; - * } - * - * _.isPlainObject(new Foo); - * // => false - * - * _.isPlainObject([1, 2, 3]); - * // => false - * - * _.isPlainObject({ 'x': 0, 'y': 0 }); - * // => true - * - * _.isPlainObject(Object.create(null)); - * // => true - */ - function isPlainObject(value) { - if (!isObjectLike(value) || baseGetTag(value) != objectTag) { - return false; - } - var proto = getPrototype(value); - if (proto === null) { - return true; - } - var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor; - return typeof Ctor == 'function' && Ctor instanceof Ctor && - funcToString.call(Ctor) == objectCtorString; - } - - /** - * Checks if `value` is classified as a typed array. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. - * @example - * - * _.isTypedArray(new Uint8Array); - * // => true - * - * _.isTypedArray([]); - * // => false - */ - var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray; - - /** - * Converts `value` to a plain object flattening inherited enumerable string - * keyed properties of `value` to own properties of the plain object. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category Lang - * @param {*} value The value to convert. - * @returns {Object} Returns the converted plain object. - * @example - * - * function Foo() { - * this.b = 2; - * } - * - * Foo.prototype.c = 3; - * - * _.assign({ 'a': 1 }, new Foo); - * // => { 'a': 1, 'b': 2 } - * - * _.assign({ 'a': 1 }, _.toPlainObject(new Foo)); - * // => { 'a': 1, 'b': 2, 'c': 3 } - */ - function toPlainObject(value) { - return copyObject(value, keysIn(value)); - } - - /*------------------------------------------------------------------------*/ - - /** - * Assigns own enumerable string keyed properties of source objects to the - * destination object. Source objects are applied from left to right. - * Subsequent sources overwrite property assignments of previous sources. - * - * **Note:** This method mutates `object` and is loosely based on - * [`Object.assign`](https://mdn.io/Object/assign). - * - * @static - * @memberOf _ - * @since 0.10.0 - * @category Object - * @param {Object} object The destination object. - * @param {...Object} [sources] The source objects. - * @returns {Object} Returns `object`. - * @see _.assignIn - * @example - * - * function Foo() { - * this.a = 1; - * } - * - * function Bar() { - * this.c = 3; - * } - * - * Foo.prototype.b = 2; - * Bar.prototype.d = 4; - * - * _.assign({ 'a': 0 }, new Foo, new Bar); - * // => { 'a': 1, 'c': 3 } - */ - var assign = createAssigner(function(object, source) { - if (isPrototype(source) || isArrayLike(source)) { - copyObject(source, keys(source), object); - return; - } - for (var key in source) { - if (hasOwnProperty.call(source, key)) { - assignValue(object, key, source[key]); - } - } - }); - - /** - * Creates an array of the own enumerable property names of `object`. - * - * **Note:** Non-object values are coerced to objects. See the - * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) - * for more details. - * - * @static - * @since 0.1.0 - * @memberOf _ - * @category Object - * @param {Object} object The object to query. - * @returns {Array} Returns the array of property names. - * @example - * - * function Foo() { - * this.a = 1; - * this.b = 2; - * } - * - * Foo.prototype.c = 3; - * - * _.keys(new Foo); - * // => ['a', 'b'] (iteration order is not guaranteed) - * - * _.keys('hi'); - * // => ['0', '1'] - */ - function keys(object) { - return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object); - } - - /** - * Creates an array of the own and inherited enumerable property names of `object`. - * - * **Note:** Non-object values are coerced to objects. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category Object - * @param {Object} object The object to query. - * @returns {Array} Returns the array of property names. - * @example - * - * function Foo() { - * this.a = 1; - * this.b = 2; - * } - * - * Foo.prototype.c = 3; - * - * _.keysIn(new Foo); - * // => ['a', 'b', 'c'] (iteration order is not guaranteed) - */ - function keysIn(object) { - return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object); - } - - /** - * This method is like `_.assign` except that it recursively merges own and - * inherited enumerable string keyed properties of source objects into the - * destination object. Source properties that resolve to `undefined` are - * skipped if a destination value exists. Array and plain object properties - * are merged recursively. Other objects and value types are overridden by - * assignment. Source objects are applied from left to right. Subsequent - * sources overwrite property assignments of previous sources. - * - * **Note:** This method mutates `object`. - * - * @static - * @memberOf _ - * @since 0.5.0 - * @category Object - * @param {Object} object The destination object. - * @param {...Object} [sources] The source objects. - * @returns {Object} Returns `object`. - * @example - * - * var object = { - * 'a': [{ 'b': 2 }, { 'd': 4 }] - * }; - * - * var other = { - * 'a': [{ 'c': 3 }, { 'e': 5 }] - * }; - * - * _.merge(object, other); - * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] } - */ - var merge = createAssigner(function(object, source, srcIndex) { - baseMerge(object, source, srcIndex); - }); - - /*------------------------------------------------------------------------*/ - - /** - * Creates a function that returns `value`. - * - * @static - * @memberOf _ - * @since 2.4.0 - * @category Util - * @param {*} value The value to return from the new function. - * @returns {Function} Returns the new constant function. - * @example - * - * var objects = _.times(2, _.constant({ 'a': 1 })); - * - * console.log(objects); - * // => [{ 'a': 1 }, { 'a': 1 }] - * - * console.log(objects[0] === objects[1]); - * // => true - */ - function constant(value) { - return function() { - return value; - }; - } - - /** - * This method returns the first argument it receives. - * - * @static - * @since 0.1.0 - * @memberOf _ - * @category Util - * @param {*} value Any value. - * @returns {*} Returns `value`. - * @example - * - * var object = { 'a': 1 }; - * - * console.log(_.identity(object) === object); - * // => true - */ - function identity(value) { - return value; - } - - /** - * This method returns `false`. - * - * @static - * @memberOf _ - * @since 4.13.0 - * @category Util - * @returns {boolean} Returns `false`. - * @example - * - * _.times(2, _.stubFalse); - * // => [false, false] - */ - function stubFalse() { - return false; - } - - /*------------------------------------------------------------------------*/ - - // Add methods that return wrapped values in chain sequences. - lodash.assign = assign; - lodash.constant = constant; - lodash.keys = keys; - lodash.keysIn = keysIn; - lodash.merge = merge; - lodash.toPlainObject = toPlainObject; - - /*------------------------------------------------------------------------*/ - - // Add methods that return unwrapped values in chain sequences. - lodash.eq = eq; - lodash.identity = identity; - lodash.isArguments = isArguments; - lodash.isArray = isArray; - lodash.isArrayLike = isArrayLike; - lodash.isArrayLikeObject = isArrayLikeObject; - lodash.isBuffer = isBuffer; - lodash.isFunction = isFunction; - lodash.isLength = isLength; - lodash.isObject = isObject; - lodash.isObjectLike = isObjectLike; - lodash.isPlainObject = isPlainObject; - lodash.isTypedArray = isTypedArray; - lodash.stubFalse = stubFalse; - - /*------------------------------------------------------------------------*/ - - /** - * The semantic version number. - * - * @static - * @memberOf _ - * @type {string} - */ - lodash.VERSION = VERSION; - - /*--------------------------------------------------------------------------*/ - - // Export to the global object. - root._ = lodash; -}.call(this)); diff --git a/res/controllers/midi-components-0.0.js b/res/controllers/midi-components-0.0.js index 0118c67bb862..60cc9abc056e 100644 --- a/res/controllers/midi-components-0.0.js +++ b/res/controllers/midi-components-0.0.js @@ -31,7 +31,7 @@ if (Array.isArray(options) && typeof options[0] === 'number') { this.midi = options; } else { - _.assign(this, options); + Object.assign(this, options); } if (typeof this.unshift === 'function') { @@ -444,9 +444,7 @@ Encoder.prototype = new Component(); var ComponentContainer = function (initialLayer) { - if (typeof initialLayer === 'object') { - this.applyLayer(initialLayer); - } + Object.assign(this, initialLayer); }; ComponentContainer.prototype = { forEachComponent: function (operation, recursive) { @@ -534,25 +532,6 @@ this.isShifted = false; }); }, - applyLayer: function (newLayer, reconnectComponents) { - if (reconnectComponents !== false) { - reconnectComponents = true; - } - if (reconnectComponents === true) { - this.forEachComponent(function (component) { - component.disconnect(); - }); - } - - _.merge(this, newLayer); - - if (reconnectComponents === true) { - this.forEachComponent(function (component) { - component.connect(); - component.trigger(); - }); - } - }, }; var Deck = function (deckNumbers) { diff --git a/res/mixxx.qrc b/res/mixxx.qrc index 915ca548d0a3..d711b8dcd196 100644 --- a/res/mixxx.qrc +++ b/res/mixxx.qrc @@ -65,7 +65,6 @@ translations/mixxx_cs.qm translations/mixxx_da.qm translations/mixxx_de.qm - translations/mixxx_de-DE.qm translations/mixxx_el.qm translations/mixxx_en.qm translations/mixxx_en_GB.qm diff --git a/res/skins/Deere (64 Samplers)/skin.xml b/res/skins/Deere (64 Samplers)/skin.xml index c1b23d72970c..9f76f64f2060 100644 --- a/res/skins/Deere (64 Samplers)/skin.xml +++ b/res/skins/Deere (64 Samplers)/skin.xml @@ -75,7 +75,7 @@ Mixxx -